Over a million developers have joined DZone.
Platinum Partner

Reviewing the Early Draft: Servlet 3.0

· Java Zone

The Java Zone is brought to you in partnership with AppDynamics. Discover how AppDynamics steps in to upgrade your performance game and prevent your enterprise from these top 10 Java performance problems.

First of all: Yes! There is a new Servlet spec coming! I had already seen some examples on this years JavaOne, but you can now download the complete early draft here. But after I browsed through it, I came to the conclusion that I don't like the new spec. There are currently some strange decisions and unclarities in it. Please allow me to give some examples:

@Servlet(urlMappings={"/foo", "/bar"})
public class SampleUsingAnnotationAttributes {
     @GET
     public void handleGet(HttpServletRequest req, HttpServletResponse res) {
          //Handle the GET
     }
}

This piece of code is a new servlet. A lot of features are now based on annotations. And there is some good things in this, look at the @Servlet annotation. This annotation contains the locations where this servlet is going to be mapped. So there is no more need to put all this in the web.xml.

But then there is the @GET annotation. And I really don't see what this annotation improves over having a HttpServlet interface with a doGet method. The only thing that would be useful is when you can put @GET and @POST on one method. But as far as I know now this is currently not supported. A couple of problems/unclarities with this:

You don't have code completion (an interface would have this)
Its a lot more error-prone (an interface forces the right parameters)
Its unclear/unspecified what happens when a Servlet has duplicate HttpMethod annotations; (2x @GET in one Servlet)

The same kind of problems arise in other places using annotations, for example in the ServletFilter:

@ServletFilter
@FilterMapping(“/foo”)
public class MyFilter {
     public void doFilter(HttpServletRequest req, HttpServletResponse res) {
          ...
     }
}

In this example we see that you can define a ServletFilter using the ServletFilter annotation. The first oddity is the @FilterMapping annotation.. why does the @ServletFilter need a seperate filtermapping annotation while the @Servlet just places this in its properties. Not very consistant. :(

Also, we now have a POJO being a ServletFilter, but its specified nowhere that your filter must contain this doFilter method. Just like the methods in the @Servlet its easy to make a typo and it wouldn't be noticed until runtime probably.
Why not use an interface for this?

This same problem also arises in the @ServletContextListener:

@ServletContextListener
public class MyListener {

     public void contextInitialized(ServletContextEvent sce) {
          ServletContext sc = sce.getServletContext();
          
          sc.addServlet("myServlet", "Sample servlet", "foo.bar.MyServlet", null, -1);

          sc.addServletMapping("myServlet", new String[] { 
               "/urlpattern/*" 
          });
     }
}

What forces the signature "public void contextInitialized(ServletContextEvent sce)"?
Nothing does, easy to make mistakes.

For some reason it seems like the JSR-315 group is very eager to put annotations everywhere. But I'm having serious doubt if this is the correct way to do this. Something like mapping a Servlet to a URL, this is cool. You are adding meta-data (mapping information) to a class. But specifying that a method is a GET method, this says something about the role of the method. People, why not just leave this hardcoded... using interfaces and parent classes. This isn't meta-data right? This shouldn't be configured with annotations...

But its not all bad, there are some cool new features in the spec. I really like the "Suspending Requests" idea. If you have a long running backend process (JDBC call, webservice, JMS) you don't want the Servlet to lock and wait for it. With the new feature you can suspend a Servlet and resume it once the backend is done.

Also new is 'Pluggability', the Servlet auto-discovery mode. During startup a scanner will (try to) find all the Servlets from the classpath and instantiate them. Then there is no more need to define all the Servlets in the web.xml! Although this would be nice during debugging or making a small project, I wouldn't trust it in an Enterprise environment. But luckely there is a way to shutdown the auto-discovery with one little line of XML (metadata-complete=true).

In conclusion, there are some good ideas in the Servlet 3 spec, but also some things I really don't like.

So what would be my suggestion? Something like this probably:

@ServletMapping(“/foo”, "/bar") //Only meta-data in annotations, with the naming consistant with @FilterMapping
public class MyServlet extends HttpServlet {

     @Override //keep strong typing!
     public void doGet(HttpServletRequest req, HttpServletResponse res) {
          ...
     }
}

From http://www.redcode.nl/blog16.html
 

The Java Zone is brought to you in partnership with AppDynamics. AppDynamics helps you gain the fundamentals behind application performance, and implement best practices so you can proactively analyze and act on performance problems as they arise, and more specifically with your Java applications. Start a Free Trial.

Topics:

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}