2009 will be the year of JEE 6. Important specifications in the JEE 6 platform are Servlet and JavaServer Faces. JEE 6 will contain the Servlet 3.0 specification as well as the JSF 2.0 specification. Both are developed in the JCP. JSF 2.0 as JSR-314 (see: jcp.org/en/jsr/detail) led by Ed Burns (Sun) and Roger Kitain (Sun) with participation from almost every vendor in the Java Web Application space. Servlet 3.0 is JSR-315 headed by Rajiv Mordani (Sun); more detail on the JCP Site for Servlet 3.0.
During his presentation at Devoxx 2008, Martin Marinschek shed a lot of light on the most important features currently being specified in JSR-314 and JSF-315 for Servlet 3.0 and JSF 2.0. A few of the highlights in the Servlet 3.0 spec are discussed in this article; another article will go into JSF 2.0 details.
Servlet 3.0 – About to go in Public Review (next week, until presumably February 2009)
Sometime next week, the public review should start for the Servlet 3.0 specification. At the time of writing, the only spec draft available is the early draft. Martin gave the audience some additional insights from within the JSR committee, clear suggestions of what will be in the public review draft – and what may be added beyond that.
Pluggability
A long running issue with the Servlet specification: all resources – servlets, filters and listeners – have to be configured in a single central web.xml. If you use libraries in your application that come with their own servlet resources, you still need to configure them in that one web.xml file. No pre-configured Servlets can be plugged into your web application.
With Servlet 3.0 that will change. In two ways actually. One is that the Servlet container will hunt down the Classpath and in JAR-files for occurrences of META-LINK/web-fragment.xml. A web-fragment.xml is a file that contains the same kind of configuration details for servlets, listeners, context-parameters and filters that are in web.xml. The servlet container merges together all web-fragment.xml files that it locates and creates one big combined in-memory web.xml from them. So now libraries can come with pre-configured servlet artefacts, if they include a web-fragment.xml in the META-INF directory.
Note: a set of fairly complex though straightforward rules determine the order in which the files are interpreted and what settings take precedence of which other settings.
The second way is described below under Ease of Development.
There is actually a third way: run-time configuration of Servlets and Filters. A ServletContextListener that is invoked during context initialization can add Servlets and Filters to the context. The methods used for this on the ServletContext are addServlet and addFilter.
It seems that it would also be nice in this ServletContextListener to remove (block) the Filters and ServletMappings that are pushed into the web.xml from the various jar files my web application is using. I may not want all that preconfigured stuff. However, I certainly do not want to go round manipulating the jar-files and redesigning the web-fragment.xml files in those jar-files. Nor do I want to add fake filter and servlet mappings to the web.xml to override these jar based configuration.
I have seen no indication that such a programmatic ‘remove’ option is part of the specification. But perhaps it is or will be.
Ease of Development
There are annotations being defined to declare servlets (@WebServlet), filters (@ServletFilter) and Listeners (@WebServletContextListener). These annotations have all the attributes defined to replace configuration in the web.xml or web-fragment.xml. The attributes contain information like url-mapping, init-params and other information that would typically be defined in the deployment descriptor. For example the @WebServlet annotation has attributes Value (a single URL pattern), UrlPatterns (to use instead of Value), Name and to support the new asynchronous behavior: supportsAsynch and asynchTimeout.
This way Servlets, filters etc can be defined entirely using annotations and would be picked up from the WEB-INF/classes or WEB-INF/lib directory.
Note: the classes that are annotated with @WebServlet will still have to extend from HttpServlet. This is a change from the initial draft which also specified method level annotations to allow plain classes to act as Servlet by specifying through annotations which methods acted as doGet and doPost.
One nice thing to know: in Servlet 3.0 the ServletContext will be available on the Request object (getServletContext()).
Asynchronous Request/Response processing
The asynchronous processing of requests serves several purposes. The underlying issue that is addressed is thread-starvation: asynchronous processing minimizes the number of threads necessary for performing the processing required for the Web Application. This is important in at least two major use cases:
- the back end services accessed from the Servlet are slow (perhaps asynchronous themselves) – hanging on to the thread while the back end sits on its response maybe quickly become to costly. The support for asynchronous processing in Servlet 3.0 allows the Servlet to give up the thread and only to resume processing when the results are in
- the client (browser) is not satisfied with just the initial response returned upon reception of the request; it is interested in additional results from the server, that should be sent (pushed) to the client as they originate on the server. This would yield an active web client that without end user intervention keeps getting refreshed (a bit like a Chat client, RSS reader or Email client that all get notified and show alerts when new messages arrive). This latter functionality is known as Server Push or Comet-style web applications. They can be achieved today, but most implementations use long running requests that keep server threads occupied and therefore do not scale well.
Servlet 3.0 supports both use cases.
Simply put it works like this:
- a request is received
- an asynchronuous context is started for it and it is stored somewhere
- asynchronous processing could be started – such as calling a back end service using an Executor; when done, the processing would use the AsynchContext to write the response to the client or forward the request to another party such as a Servlet or JSP (that do not need to be asynchronous) for generating the response
- instead of some asynchrously started processing, the application can wait for events to occur that can lead to retrieving the Asynch Context and write some data to the Response.
At any rate, the initial servlet thread can be relinquished when the AsynchContext is created for the request.
It is up to the client to properly deal with the asynchronous response. Common issues to deal with are the time out of the client request and the irregularly receiving of response bits and pieces; the response may not be complete for a very long time, the server sending pieces of data to the response whenever events occur. Smart JavaScript AJAX processing needs to deal with these responses.
Martin discussed a nice use case – of Pizza Delivery Service:
Through Web Application, the customer orders a pizza. The request is received and dealt with asynchronously. That means an AsynchContext is initialized for the request, this context is stored in a (application scope) Map under the orderId key and an initial response could be written. New orders are dealt with in the same way.
The Cook also uses a Web Application, that shows the orders that should be processed. When the initial cook’s request was received, that too started an AsynchContext that was stored in the application scope. When a new order is received, the Cook’s AsynchContext is retrieved and the new order details are written to the Response. This will lead to an immediate update of the Cook’s Web UI – provided that his client side logic can handle the bits of information sent asynchronously.
With every step of the pizza preparation process – add tomato sauce, add cheese, add salami,… – the Cook could update the order details in the web application. These are sent to the server. The server can retrieve from the Map with customer AsynchContext objects the context for the Order’s Customer and write some details about the cooking process to the Response. This would update the Web Interface for the customer with the latest state of his pizza.
The Delivery department could likewise have started an Asynch Context when first logging in. When the pizza is ready for delivery, the context’s response object’s writer is retrieved and order and delivery details are written to it – asynchronously and near-instanteanously updating the Delivery Web Page.
Note: The customers, cook and delivery department to not hold threads locked. They only consume threads when information is exchanged.
The code required includes:
@WebServlet("/pizza" asyncSupported=true)public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) { ... // if some parameter is NewOrder (as opposed to CookingUpdate, ReadyForDelivery) AsyncContext aCtx = req.startAsync(req, res); // store aCtx in the application scope Map with Order context objects // perhaps write a first response (order successfullt received, now being processed) // get the Cook's Context object cookCtx.getResponse().getWriter().print(.... new order details....); }}
To finish an asynchronous request, we can call the complete() method on the AsynchContext. Another method on the context that we can use instead is the forward() to have the processing completed by another Servlet or JSP (that do not necessarily support asynch).
We can configure Listeners on the AsynchContext() that are called onComplete or onTimeout event.
Beyond the current spec
Martin Marinschek told that the final spec may also describe an API for file upload. Currently there is no standard for Servlet Based File Uploading. Everyone rolls his own or relies on the de facto standard Commons Fileupload.
Not yet part of the spec, but also under discussion is the ability to log in and log out programmatically. New APIs will be added to HTTPServletRequest
to enable this. The login
method of HTTPServletRequest
will allow the application or framework to force a container-mediated authentication. The logout
method of HTTPServletRequest
and HTTPSession
allows an application to reset the authentication state of the request.
JSF 2.0 – Currently in Public Review (until 26th January 2009)
See later blog article.
Resources
An early access implementation of some of the features are available in the GlassFish nightly build.
An introduction to Servlet 3.0 by Deepa Sobhana
Servlet 3.0 From the Source (Rajiv Mordani’s blog)
Servlet 3.0 Pluggability (Rajiv Mordani’s blog)
Asynchronous Support in Servlet 3.0 (Rajiv Mordani’s Blog)