Servlet, Programmatic Registration of Web Components

[Updated: Jan 14, 2017, Created: Jan 22, 2016]

To provide enhanced pluggability, Servlet 3.0 provides support for the programmatic declaration and registration of servlet, filter and listener components via new methods added to ServletContext. We can call these methods from within ServletContextListener#contextInitialized method or ServletContainerInitializer#onStartup method. We can summarized these new methods of ServletContext as follows:

Methods General Description Methods
Registration of components via addXXX(). Each method on right side has multiple overloaded form. Each overloaded method needs name argument (except for Listener methods) of the component along with class name or class type or instance of the component. Each overloaded group either return ServletRegistration.Dynamic or FilterRegistration.Dynamic, (except for listeners, they return void). The returned Registration object can be used for further configuration. addServlet(...)
addFilter(...)
addListener(...)
Creating instance of the component via createXXX(). We need to provide class type as argument to each method. These methods may be called before calling above addXXX method. createServlet(...)
createFilter(...)
createListener(...)
Getting Registration object via getXXXRegistration(). Doesn't apply to listeners. If servlet/filter has not been register in web.xml or via annotations, this call throws UnsupportedOperationException in ServletContextListener#contextInitialized. getServletRegistration(...) getFilterRegistration(...)

Use cases of Programmatic Configuration

This feature enable framework designer to add the framework specific web components during startup without asking end user on application side to provide same configurations deployment descriptor and add them manually. For example frameworks like JSF and Spring are already using ServletContainerInitializer approach for that (see source code of FacesInitializer and SpringServletContainerInitializer. The developers just need to add the framework jar dependencies and create some POJOs (using framework specific annotation or implementing some interfaces) to use the framework. They even don't have to provide /META-INF/services/javax.servlet.ServletContainerInitializer as this file already resides inside the framework jar.

The same configuration can be done in a ServletContextListener residing inside the framework jar, but disadvantage is, that will not work if the application's web.xml file has been decidedly configured metadata-complete="true" to improve performance. Setting this flag causes the container not to scan JARs for annotations. Also ServletContainerInitializer approach (SPI) is more standard way to go as it's built into Java SE.

ServletContextListener#contextInitialized should do programmatic configuration on application level only. Based on some dynamic conditional parameters we can decide to plug/register some web components selectively.


Example

This example will focus on adding servlet via ServletContextListener#contextInitialized. Assuming a servlet application can be hosted from different geographical locations. Based on different locale we can decide to choose a particular servlet to add to the container.

  1. Prepare project
    • Create web application using maven-archetype-webapp, steps here.
    • Delete web.xml, we don't need it at all.
    • In pom.xml add dependency of javax.servlet-api:3.0.1
    • In pom.xml add tomcat7-maven-plugin to run it as embedded server.
  2. Create a context listener class AppContextListener, annotated with @WebListener.
  3. Create two servlet classes DefaultAppController and OffshoreAppController without any annotations.
  4. Now we are going to run our web application from root folder:
    mvn clean tomcat7:run-war
  5. Put following url in your browser:
    http://localhost:8080/servlet-programmatic-registration/app/
    If you are in USA, you should see this output on the page
    DefaultAppController
    If you are using Windows, you can change your computer locale as described here and run the app again


Example Project

Dependencies and Technologies Used :

  • Java Servlet API 3.0.1
  • JDK 1.8
  • Maven 3.0.4

Servlet Programmatic Registration Select All Download
  • servlet-programmatic-registration
    • src
      • main
        • java
          • com.logicbig.servlet
        • webapp

See Also