Wednesday, 2 April 2014

Servlet API - Part 2

In the earlier part, we have discussed Servlet API 2.5. There are 3 more versions of Servlet API before 2.5 but the differences is too minor to mentioned. If you want to know in details, please search for the change log of Servlet API.

The next version after 2.5 is Servlet API 3.0 (the latest at the time of writing is 3.1). There is a reason for the big jump in version number. Servlet API 3.0 is a total revamp, which totally change the way the web application was developed. This article will discuss the changes of Servlet API 3.x versus earlier versions.

Background

Deployment Descriptor

When J2EE was first developed, it combined of Java components plus deployment descriptor. The goal is to make application configurable by changing deployment descriptor file. In deed, it offers flexibility for developers to modify application behaviour without code change in production environment. However, this feature was overrated. Let take a look at web.xml file. How often do we need to change servlet mapping, adding filter or even changing security constraint?

Moreover, the deployment descriptor file is long and tedious to write. It was proposed to have dedicated person to maintain the file but this wish never came true. Most of the time, developers end up creating deployment descriptor file and even creating deployment script.

This time also observed the trend of single application being developed by multiple teams. Sharing a single deployment descriptor is harder to developer feature in parallel.

The rise of RoR and Annotation

As we already know, good developers are innovative and lazy. They always manage to find way to make development easier, faster and better. There are major events happened in this time that marked the changing of mindset in industry.

At first, it witnessed the success of Ruby on Rail framework. This framework was built with Convention over Configuration principle. It help to greatly reduce the effort of configuring webapp.

Secondly, Java 5 introduction brought developers the choice to use annotation. At first, it was not so cleared how annotation suppose to change the way application was developed but very soon, the community find a great use of it. Annotation can be included in the runtime (RetentionPolicy.RUNTIME) and it can be used together with Java reflection to define how the component suppose to be used.

Alternative ways to build web application

To avoid complexity of Servlet API, developers often make use of MVC and IOC framework to build web application. For example, if a developer build a J2EE web application, he/she should adopt an architect diagram similar to this:


Rather, most of them choose an alternative solution


Comparing these two designs. the below is much  simpler to create, provide that the Service can be injected automatically and the annotation or convention can be used to identify mapping between HTTP request and the service method serving it.

Slowly, J2EE lost its popularity and Sun knew that they need to change.

Servlet API 3.0 & 3.1

Servlet API 3.x adopts proven ideas of the Java community and pull out a very sophisticated solution. If you look from the bird eye view, it look pretty much similar to existing frameworks in the market. It actually built on the same idea.

Our team has been one of the early adopters when Java EE 6 arrived but later switched back to Spring framework due to memory leak issue with Glassfish. One of our senior developer took only 3 days to completed the switch for a application built by 6 developers in 1 year. It should not be that fast if the two technologies stacks are not similar.

Servlet API is not supposed to be used alone, it always comes with Context and Dependency Injection.

Let take a look in details of the changes

Annotation

Servlet API 3.x do not abort any concept from Servlet 2.x, Rather, it allows the entity to be declared by annotation in stead of using deployment descriptor. For example, here it how we declare a Servlet by annotation:

@WebServlet(name="Servlet", urlPatterns={"/anyUrl"})
public class AnnotatedServlet extends HttpServlet {  
}

It is definitely simpler than writing XML in deployment descriptor. When Servlet API 3.0 was introduced, Servlet can be POJO, but later, it was switched back to inheriting HttpServlet. It gave a clear signal that Java is and will still be conservative. It will not move that far like Rails by totally removing URL mapping.

Even after using annotation, Servlet API still has a major difference with Spring MVC. The annotation @RequestMapping in Spring MVC can be placed on both Controllers and methods. It is convenient when you want to your Controller to serve multiple URLs (think of it when you want to implement Rest API). 

In contrast, Servlet only support HTTP methods like doGet, doPost,... It means that you still need to add a bit more effort to implements Restful API or stick with Java Server Face. As JSF page is rendered in server, it knows how to access Servlet methods without going through URL Mapping

Context and Dependency Injection

CDI has never been part of Servlet API but I cannot resist the temptation to talk about it. Servlet API will not be that helpful if you cannot use Dependency Injection to inject the beans to Servlet. If you use Spring MVC, the Bean is pretty much stateless and singleton. It does not relate directly with User Session. If you need to access user session, you need to add session support from a security framework or simply pass the values in as method parameters. 

In contrast, EJB has the stateful bean. Container supposes to serve the same stateful bean for all requests from same user, which make it effectively user session. EJB also support stateless bean but they are not singleton. Normally, container serve stateless bean from stateless pool. 

This difference will affect how you want to design your application. As the world is moving toward stateless session for scalability, I would prefer to use cookie-based session rather than server side session. In this case, stateful bean provide little value. Fortunately, we still have Request scope bean for this purpose. 

The word 'Context' from CDI come from the fact that you can define the scope for beans when injecting it. There are fours scopes: @RequestScoped, @SessionScoped, @ApplicationScoped, and @ConversationScoped. As we can see, most of the scopes are only meaningful in Web context.

Asynchronous Support

Servlet API 3.x did a good job by introducing Asynchronous support. As I have discussed in one of my earlier articles, asynchronous in Servlet API 3.x has nothing to do with Asynchronous HTTP request. It aims to solve different problems. 

Container comes with HTTP thread pool. Each thread serve one request at one time. However, as explained here, sometimes the server cannot serve the request quickly enough due to some inputs waiting. In this scenario, we want to free HTTP thread so that it can serve other requests. 

The new model is to let the current HTTP thread exit, waiting for result to be available and use another HTTP thread to render response. As the information necessary to render response are passed to Servlet methods as parameters (which means data are stored in stack memory), it cannot be shared among 2 HTTP threads. This was overcome by storing shared data in AsyncContext.

Deployment Descriptor

Introducing annotation does not block you from using deployment descriptor. However, deployment descriptor in Servlet API 3.x is very flexible. It even can be split to modules. Each jar files can have their own modular deployment descriptor file store inside META-INF folder. The modular deployment descriptor will only be detected at runtime. This make the modules pluggable.

Both annotation scanning and web fragment scanning can be turned on or off in web.xml.

Programmatic Addition   

Servlet API 3.x allows you to add Servlet, Filter and Listener programmatic. This features came as a surprise because no open-source framework in the market offer any equivalent. Unfortunately, I cannot comment much on this feature as I have not gone through any use case for it.

Conclusions

Servlet API 3.x also provide some other minor improvements that I will not dig further in the scope of this articles. However, with what have been covered, I hope readers can have a basic understanding about Servlet API 3.x