In my earlier post I gave an overview of the things that are being worked upon in Servlet 3.0. This post focuses on one of the areas that the expert group has been working on - pluggability.

 

Pluggability

There are a lot of frameworks / libraries that are built on top of the servlet container. Most frameworks today require you to configure a servlet, filter or listener in the application's web.xml in addition to including it as a dependency in the WEB-INF/lib directory. Today in a servlet container the application has one monolithic web.xml that defines all the deployment artifacts for the application, including the dependencies of the application on the framework components. In it's current state, a developer must go through the documentation of each framework that it depends on and declare the appropriate servlets, filters, Listeners, etc. The goal is to make it possible to use frameworks without having to worry about any additional configuration. 

To overcome this issue in servlet 3.0 we are adding a new feature that allows having more than one web.xml, or as it is being referred in the specification as web fragments. A framework can define it's own web.xml that declares the necessary components for the framework that is then included for use in the web applicaton. At deployment the container is responsible for discovering the web.xml fragments and processing them. A new element is being added to the schema for web applications - web-fragment that can define servlets, filters listeners. Below is a simple example of such a fragment.

<web-fragment>
  <servlet>
    <servlet-name>welcome</servlet-name>
    <servlet-class>
      WelcomeServlet
    </servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>welcome</servlet-name>
    <url-pattern>/Welcome</url-pattern>
  </servlet-mapping>
...
</web-fragment>

The above fragment would be included in the META-INF directory of the framework jar file. 

In addition to changes to modularize the web.xml there are also annotations being defined to declare servlets (@Servlet), filters (@ServletFilter) and the annotations have all the attributes defined to make web.xml optional. These attributes contain information like url-mapping, init-params and other information that would typically be defined in the deployment descriptor. 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.

Along with the changes mentioned above there are few new APIs to also allow programmatic addition of Servlets and Filters at start up time of an application. API changes for adding configuration are added to the ServletContext class and are listed here below:

ServletContext: 
    addServlet 
    addServletMapping 
    addFilter 
    addFilterMapping 
Below is an example that shows how the APIs defined in ServletContext can be used. 
@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/*"});
    }
}
@ServletContextListener
public class MyListener {
    public void contextInitialized (ServletContextEvent sce) {
        ServletContext sc = sce.getServletContext();
        sc.addFilter("myFilter", 
                     "Sample Filter", 
                     "foo.bar.MyFilter", 
                      null);

        sc.addFilterMapping("myFilter", 
                             new String[] {"/urlpattern/*"},