7/03/2011

Servlet init method vs PostConstruct method

There are 2 initialization methods in servlet:

(1), init(ServletConfig config) methods defined in javax.servlet.Servlet interface. Servlet init method has been there since the first version of Servlet. This method was later (around Servlet 2.3) overloaded in javax.servlet.GeneircServlet for convenience. According to the above javadoc, the servlet container calls the init method exactly once after instantiating the servlet.

(2), PostConstruct method, as defined in javax.annotation.PostConstruct, was introduced in Java EE 5 to all component types, including all web components (Servlet 2.5). Similarly, @PostConstruct (or post-construct, if declared in deployment descriptors) methods are to be invoked only once after the component class is instantiated and before it is put into service.

But these two servlet methods are not exactly the same.

The name of Servlet init method is set in the interface, and it must be public. PostConstruct method is more flexible: it can be private, package default, protected, or public, and can be named anything.

I could not find docs specifying the invocation order and relationship of the two methods. But it turns out the order is:

servlet class constructor --> PostConstruct --> init and init(ServletConfig)
So inside PostConstruct method at the second step, ServletConfig has not been initialized, and neither is ServletContext. Calling getServletConfig() in PostConstruct returns null. Calling getServletContext() results in IllegalStateException in most servers (GlassFish 3, Tomcat 7 and JBoss 6), but returns null in Resin 4.

Apparently there are overlappings and subtle differences between PostConstruct and servlet init methods. I guess ideally we could merge them into one. If there is no PostConstruct method in servlet class, init() will be considered as its PostConstruct method; if developers want to specify a PostConstruct method, it has to be the same as init() method, basically adding the redundant @PostConstruct to init(). This is roughly how ejbCreate and PostConstruct is handled in EJB 3.

What about web apps that already have both PostConstruct and init methods? In order to accommodate them, the next desirable approach is to allow both, but clearly specify their relationship, making clear getServletConfig() and getServletContext() both return valid values inside the both methods.

The same applies to PreDestroy and servlet destroy method, to a lesser extent.

No comments: