Master web.xml to use in all webapp projects - java

I'm developing multiple web applications in Eclipse Mars 2 using java 1.7. I build the files using Maven and test them using a jboss (WildFly) plugin. Each of them uses a web.xml and share 90% of their logic. They all use spring, they all use the same session config, the same filters etc. The difference is the authorization checks and security roles.
Recently I had to do some updates, and it was burden to update all web.xml separately. I'm looking for a solution to define a "web.xml" parent or master file which houses all the common logic, and then inject the small specific parts. What options do I have?

I would move as much as you can out of web.xml and into annotations on the classes. For example, on a filter, you can do something like:
import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
#WebFilter(filterName = "TimeOfDayFilter",
urlPatterns = {"/*"},
initParams = {
#WebInitParam(name = "mood", value = "awake")})
public class TimeOfDayFilter implements Filter {
(taken from here)
In this way, you've moved much of the traditional configuration that is done in web.xml into the Java class. The same thing can be done with servlets.
Note that this isn't always the right answer. In filters, for example, you can only order them (that is, have a chain of filters) if you're using web.xml. But the more you can move out of web.xml the better.

Related

Configuring servlet url-patterns without web.xml

I know this can be done in servlet 3.0 with the #Webservlet annotation where you just assign the url-patterns and not have to do any configurations within a web.xml. Is there a way to programmatically assign a servlets url-pattern for applications running servlet 2.5?
I am creating a library which multiple applications will depend on and trying to make it so each of these applications do not have to explicitly configure any servlet url mappings for the servlets in the library I am creating within their respective web.xml file.
Thanks,
Since the web.xml and #Webservlet are both mechanisms for the server to know where to route requests by examining the war, you would have to be able to manipulate the server if you wanted to do it in code. This is at least theoretically possible, since the server could offer for example a JMX endpoint for configuration or you could go directly into the innards of the server.
However while it might be possible, it would be a non-standard way and you would have to write different tricks for all the servers you want to support. That's not something you want to do.
Finally, if you're creating a library, why does it have servlets in it? It shouldn't be the responsibility of the library to create servlets or decide which urls they're assigned to.

Configuring a Jetty server with Glassfish servlet

I have a working web-application that I built, successfully deployed to Heroku, and is functioning well. However, I'm trying to tune the server/servlet config, and that's when I realized that I don't know what my application is actually doing.
For glassfish, this is the config that's needed.
However, for Jetty, this is the config that's needed.
I realized I have no idea which of the above my application is actually using, so I started digging in my code and found the following:
The main method being called by Heroku is instantiating the following Jetty server/webappcontext.
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
However, the jetty config seems to rely on a number of files (such as etc/jetty.xml, webapps folder or war files) which my project does not have at all.
In addition, my web.xml file defines the following servlet:
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
The fact that my application is defining a Jetty server but Glassfish servlet concerned me quite a bit. In an effort to standardize everything around Jetty, I tried adding the jetty servlet to my pom.xml dependencies and changed the above to:
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
However, this change caused my application to break. It still compiles successfully and all my jerset-test based integration tests still succeed locally. But when I actually run the server, none of the routes work.
Some questions:
Is it a ill-advised to use a Jetty server along with a Glassfish servlet (container)?
If yes, what servlet (container?) should I replace Glassfish with, and what do I need to do to get the new Jetty servlet working?
If no, what config should I be using for my current setup? Should I be implementing the Glassfish config or the Jersey config?
I've spent many hours trying to read through various documentations, tutorials and stack-overflow threads, but they all either assume prior knowledge about servlets, JavaEE and related topics (none of which I'm familiar with), or they are oriented towards building brand new hello-world apps from scratch (as opposed to porting an existing working app over, which is what I'm trying to do). Any explanations you could give, without assuming prior knowledge, relevant to the context described above, would be much appreciated.
Edit: I think I'm starting to understand now that a Servlet is the code that generates the response for a request, and the ServletContainer is what provides the infrastructure for the Servlet. I've never had to deal with Servlets directly in building my web-app. Here's an example of what a route looks like in my app:
#Path(Ping.REST_PREFIX)
public class Ping {
static final String REST_PREFIX = "/ping";
#GET
public static Response get(#DefaultValue("getPing") #QueryParam("param") String param) {
return Response.ok().entity(param).build();
}
#Path("/pong")
#GET
public static Response getPong(#DefaultValue("getPong") #QueryParam("param") String param) {
return Response.ok().entity(param).build();
}
}
How can I port code like the above into a Jetty ServletContainer, without rewriting vast sections of my application?
You are not using a "Glassfish Servlet Container", you are using a "Jersey Servlet Container".
Jersey is the project you are using.
Glassfish was the umbrella organization (sometimes called "a forge") that helps manage/maintain the Jersey project (along with dozens of other projects).
Difference com.sun.jersey and org.glassfish.jersey
The Jersey project can now be found at the java.net organization.
https://jersey.java.net/

Runtime loading of Controllers for Spring MVC and dynamically mapping requests/URLs

We are starting a new project using Spring MVC, and we would like to move away from annotation-driven request/url mapping. We wish to implement the following use case:
Use Case A
User enters a URL.
The request mapping handler retrieves a list of mappings (e.g. from the DB), and based on this dynamic list of mappings, it calls the relevant controller.
This is because we want to be able to do the following as well:
Use Case B
We want to load a new Controller (perhaps a new reports module) into the web app without having to redeploy or do a server restart.
We will map this new Controller to a URL and persist it somewhere (most likely the DB).
We would like the Controller to be registered in the Spring app context (managed by Spring).
We would then like to use this new Controller in the request mapping.
We've taken an initial look at the different ways we can implement this, but we are unsure of the best architecture/method to go about this route. A couple of questions:
For Use Case A, how do we implement this within the Spring MVC framework (or if it's possible)?
For Use Case B, is there a good framework or way to be able to do dynamically loading and registering of this for web applications? We've taken a cursory look at OSGI but it seems to be advisable for use in non-web applications.
For Use case A :
Instead of DB you can keep the url mappings in a property file and then use property place holder to initialize beans using xml configuration on context up. This way remaining inside the spring framework, you can avoid annotations.
For Use Case B :
Tomcat supports dynamic reloading of classes but that to of only non structural changes in class file. But this has memory leaks as well as it doesnt cleans up old instance of class loader rather it creates a new instance.
Its quite achievable using spring-mvc-router API.
Please check below link
url-action mapping & routing in Spring MVC 3.0
Here the URL can be configured to controller.method using .conf file, but this can be achievable using java configuration, and i haven't tried so far.
Also if xml configuration chosen, then check out the property 'autoReloadEnabled', but its not adviceable for production use.
Hope this helps!!!

Enabling/disabling servlet in a way other than web.xml

i wonder if there's a way to enable or disable servlets (or at least mappings for servlets) other than web.xml. I have multiple kinds of servers which use the same web.xml (i can't change this) so this is why another way of enabling/disabling servlets would be useful.
Thanks,
Teo
You could use #WebServlet annotation with servlet 3.0 onwards, not sure if this will work for your requirement, please comment if this isn't the way you want to
#WebServlet("/hello")
public class HelloServlet extends HttpServlet {
// code code code
}
As far as i am aware there is no such thing as programmatic disabling of servlets other that the deployment descriptor.
The way that i would approach such an issue is the following:
-I would add an if statement in each of my servlets service() method that i would like to control access to such as:
if(MyCustomSecurity.isServletAccessible(request)){
//here is your code that you have right now
}else{
//redirect request to an error page maybe
}
-Create this method isServletAccessible() in MyCustomSecurity class that would return a boolean on weather the user is allowed to acceess the servlet or not
If you are using Tomcat 7.x / Servlet 3.0 you can programmatically add a servlet filter to dynamically enable/disable access to some of your servlets without touching your web.xml file nor your application code.
I'd just create a web filter that reads some kind of configuration and passes or redirects on specific, configured paths.
Another option is to block paths on security layer e.g. Spring Security (actually it uses something like described above).
what about creating a Filter (a class that implements javax.servlet.Filter), then in a xml or properties file or even in database, you can add the servlets' names that the user can access or can't access.

Dynamically add classes to Guice through reflection

Is it possible with Guice (and even in Java in general) to iterate over all classes in a particular package and add them to Guice?
The underlying problem: I'd like to be able to route all traffic to /admin/* to a single servlet which redirects accordingly. Then I'd like to be able to just add servlets to the same package and have them get picked up automatically. E.g. If I navigate to /admin/showCompanyDetails, I'd like that to redirect to a servlet called showCompanyDetails.java in the admin package.
Furthermore, I'd like this to work in such a way that all I have to do to add further admin functions is to drop a new class into the admin package. I.e. No factory methods to update and no containers to add to.
So far, the closest I've come is to have the redirect servlet create a Guice injector with a module that contains all the admin servlets. But as I said, I'd like to avoid having to update a Guice module.
Also, I'd like this to be possible in AppEngine.
And I want a pony.
There are some possibilities:
Use Servlet 3 #WebServlet annotations on your servlet classes, so they get picked up by a Servlet 3 web container. Then you can use Guice to inject dependencies, see here for an example.
Use guice-automatic-injection to bind your servlet classes in your classpath (they must contain their path similar to Servlet 3 via annotations or provide an accessor for it). Then you can create a Guice servlet module which retrieves all those servlets from Guice and registers them as servlets to their provided paths.
Both ways may be usable in AppEngine, but I haven't got experience with it.
Getting a pony is easy if you use just Object as its base class ;p

Categories