In the previous post we looked at Servlet 3.0 spec's ability to allow Servlets and filters to be defined in jars outside the deployment descriptor. In this post I am going to look at a different feature - declaring Servlets and Filters at runtime.
The first step was to create a servlet class:
Servlet specs provide us with the ability to add definitions dynamically.
The first step is to add a ServletContext Listener.
Is this feature useful ?
To be honest I cant think of a general use case in application development where I would like to configure a servlet or a filter in this manner. Maybe for some frameworks where depending on some configuration parameters we set up the servlets and filters.
The first step was to create a servlet class:
publicclass TestServlet extends HttpServlet {I also defined a filter class:
@Override
protectedvoid doGet(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
resp.getOutputStream()
.write("<html><body>Request received</body></html>".getBytes());
}
}
publicclass TestFilter implements Filter {These two components haven't been defined in the web.xml. If we run the servlet app now, then neither of the above classes will work. With Servlet 3.0 we have a new feature - Pluggability.
@Override
publicvoid init(FilterConfig arg0) throws ServletException {
System.out.println("TestFilter initialized");
}
@Override
publicvoid doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throwsIOException, ServletException {
System.out.println("request received in TestFilter");
filterChain.doFilter(servletRequest, servletResponse);
return;
}
@Override
publicvoid destroy() {
System.out.println("LocalFilter destroyed");
}
}
Servlet specs provide us with the ability to add definitions dynamically.
The first step is to add a ServletContext Listener.
<listener>Now to look into my Listener class:
<listener-class>
com.listener.PluggabilityListener
</listener-class>
</listener>
publicclass PluggabilityListener implements ServletContextListener {
@Override
publicvoid contextDestroyed(ServletContextEvent arg0) {
}
@Override
publicvoid contextInitialized(ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
javax.servlet.ServletRegistration.Dynamic dynamicServlet
= sc.addServlet("myServlet", TestServlet.class);On initialization of the Servlet context, the contextInitialized method is called. Here we addServlet method of the ServletContext class. The parameters are the servlet name (one we use in web.xml) and the servlet class. The method returns an instance of Dynamic class. This instance can be used to initialize init parameters, set loadOnStartUp value among other features. Here we have used it to set the mappings for the servlet. In this case we have added mappings for "*.do" and "/pages/*" Similar is the code for Filter. With Filter we can add mapping identical to the Servlet. This is done with the addMappingForServletNames method. The first parameter is the Dispatcher type which has been set to Request. On starting the server:
dynamicServlet.addMapping("*.do","/pages/*");
EnumSet<DispatcherType> enumset = EnumSet.of(DispatcherType.REQUEST);
javax.servlet.FilterRegistration.Dynamic dynamicFilter =
sc.addFilter("myServlet", TestFilter.class);
dynamicFilter.addMappingForServletNames(enumset,true,"myServlet");
dynamicFilter.addMappingForUrlPatterns(null, true, "*.jsp");
}
}
TestFilter initializedI decided to test the code. On hitting Url "http://localhost:8080/WebFragments/pages/hy" both the filter and the servlet were invoked. Same is the case for "http://localhost:8080/WebFragments/p.do" If I test for "http://localhost:8080/WebFragments/index.jsp", the request was received only by the filter.
INFO: Server startup in 654 ms
Is this feature useful ?
To be honest I cant think of a general use case in application development where I would like to configure a servlet or a filter in this manner. Maybe for some frameworks where depending on some configuration parameters we set up the servlets and filters.