Resin 4.0 introduced Early Access Servlet 3.0 support and, in version 4.0.2, we’ve solidified the implementation. Among many interesting features, Servlet 3.0 introduces annotations that make deploying Servlets, Filters and Listeners of all types easier. This short tutorial opens with the introduction of annotations of javax.servlet.annotation package, shows how to use WebListener, WebServlet, WebFilter and WebInitParam annotations and closes with an example demonstrating a use of IOC (javax.inject package) in a Servlet.
This tutorial covers the following annotations:
- @WebListener
- @WebServlet
- @WebFilter
- @WebInitParam
WebListener, WebServlet and WebFilter annotations are placed on classes implementing respectively Listeners, Servlets and Filters. The WebInitParam annotation is used with WebServlet and WebFilter annotations specifying Servlet and Filter initialization parameters.
In order to provide support for these annotations, the mechanics of WebApp loading had to become a bit smarter.
Application Loading Phase
When an application loads, all classes comprising the application are examined for presence of the annotations. When these annotations are found on a particular class, the container registers instances of the classes as Listeners, Servlets, or Filters.
Registering a Listener using @WebListener
The WebListener annotation is used to register the following types of listeners
- Context Listener (javax.servlet.ServletContextListener)
- Context Attribute Listener (javax.servlet.ServletContextAttributeListener)
- Servlet Request Listener (javax.servlet.ServletRequestListener)
- Servlet Request Attribute Listener (javax.servlet.ServletRequestAttributeListener)
- Http Session Listener (javax.servlet.http.HttpSessionListener)
- Http Session Attribute Listener (javax.servlet.http.HttpSessionAttributeListener)
@WebListener is the easiest to use.
Example:
Registering ServletContextListeners.
package example; import javax.servlet.annotation.WebListener; import javax.servlet.ServletContextListener; @WebListener public class FooApplicationLifeCycleListener implements ServletContextListener { public void contextInitialized(ServletContextEvent event) { //do on application init } public void contextDestroyed(ServletContextEvent event) { //do on application destroy } }
The type of listener is deduced from the list of interfaces that the class or its super class implements. If the class annotated with WebListener does not implement any of the listeners an error message will be logged.
Registering a Servlet using @WebServlet annotation
@WebServlet annotation is used to register a Servlet with a container. Below is the complete list of attributes that annotation encapsulates.
- name
- description
- value
- urlPatterns
- initParams
- loadOnStartup
- asyncSupported
- smallIcon
- largeIcon
The attributes are simply bits of data that prior to Servlet 3.0 would go into <servlet> or <servlet-mapping> tags of web.xml. Now they can be specified in java code.
Note: the spec mandates either value or urlPatterns attribute be specififed.
Example:
package example; import javax.io.*; import javax.servlet.*; import javax.servlet.annotation.*; @WebServlet(value="/hello", name="hello-servlet") public class HelloServlet extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws IOException, ServletException { res.getWriter().println("Hello World!"); } }
Resin autocompiles java files found inside WEB-INF/classes directory, so the code can be pasted right into WEB-INF/classes/examples/HelloServlet.java. Accessing http://localhost:8080/{app-name}/hello should render text
Hello World!
Using @WebInitParam with @WebServlet
The @WebInitParam annotation provides a means of specifying initialization parameters for servlets and filters.
The annotation defines the following attributes:
- name
- value
- description
Example:
package example; import javax.io.*; import javax.servlet.*; import javax.servlet.annotation.*; @WebServlet(value="/hello", initParams = { @WebInitParam(name="foo", value="Hello "), @WebInitParam(name="bar", value=" World!") }) public class HelloServlet extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws IOException, ServletException { PrintWriter out = res.getWriter(); out.println(getInitParameter("foo")); out.println(getInitParameter("bar"); } }
Accessing the servlet at http://locahost:8080/${app-name}/hello should render
Hello World!
Registering a Filter with @WebFilter annotation
The @WebFilter annotation has the following attributes
- filterName
- description
- displayName
- initParams
- servletNames
- value
- urlPatterns
- dispatcherTypes
- asyncSupported
As mandated by the spec Resin expects that value, urlPatterns or servletNames will be specified.
Example:
package example; import java.io.*; import javax.servlet.*; @WebFilter (value="/hello", initParams=({ @WebInitParam(name="message", value="Servlet says: ") })) public TestFilter implements Filter { private FilterConfig _filterConfig; public void init(FilterConfig filterConfig) throws ServletException { _filterConfig = filterConfig; } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException { PrintWriter out = res.getWriter(); out.print(_filterConfig.getInitParameter("message")); } public void destroy() { // destroy } }
Metadata specified in WebFilter are available via FilterConfig object, so the output of http://localhost:8080/${app-name}/hello should render text
Servlet says: Hello World!
Integrating with javax.inject.*;
Resin supports the javax.inject.* - IoC spec package - as part of CanDI. Using Servlet 3.0 and IoC annotations allows avoiding XML configuration entirely, with an exception of a beans.xml file which is used as a marker enabling the annotations specified in javax.inject package.
Below is a short example demonstrating the use of the @javax.inject.Inject annotation in a Servlet defined with @WebServlet.
Example:
file: WEB-INF/classes/META-INF/beans.xml
<beans xmlns="http://java.sun.com/xml/ns/javaee"/>
file: WEB-INF/classes/example/MyBean.java
package example; public class MyBean { public String getMessage() { return "Hello World!"; } }
file: /WEB-INF/classes/example/HelloServlet.java
package example; import java.io.*; import javax.inject.Inject; import javax.servlet.*; import javax.servlet.annotation.*; @WebServlet(value="/hello") public class HelloServlet extends GenericServlet { @Inject MyBean _myBean; public void service(ServletRequest req, ServletResponse res) throws IOException, ServletException { res.getWriter().println(_myBean.getMessage()); } }
Servlet 3.0 also adds oft-requested standardization for file upload functionality. I will try to follow up with an entry on how to use this new functionality along with the supporting @MultipartConf annotation soon.