The answer lies in a difference between Servlet spec 2.5 and Servlet spec 3.0.
In Servlet spec 2.5, the order in which listeners are called is defined by the order of their declaration in the deployment descriptor (web.xml):
SRV.10.3.3 Listener Registration.
The Web container creates an
instance of each listener class and registers it for event
notifications prior to the processing of the first request by the
application. The Web container registers the listener instances
according to the interfaces they implement and the order in which
they appear in the deployment descriptor. During Web application
execution, listeners are invoked in the order of their registration.
In Servlet spec 3.0, the order in which listeners are called is defined by the element <absolute-ordering> in the deployment descriptor (web.xml):
8.2.3 Assembling the descriptor from web.xml, webfragment.xml and annotations.
...
c. Prior to this release of the specification,
context listeners were invoked in random order.
This is wrong IMHO, as stated above in the version 2.5 spec. :-)
As of Servlet 3.0,
the listeners are invoked in the order in which they are declared in
the web.xml as specified below:
i. Implementations of
javax.servlet.ServletContextListener are invoked at their
contextInitialized method in the order in which they have been
declared, and at their contextDestroyed method in reverse order.
This doesn't work at all like you'd expect and is the source of my trouble, confusion and a lost weekend. ;-)
It's NOT the same ordering as before (2.5 spec)!
But there is more... (the AHA moment is near!)
8.2.2 Ordering of web.xml and web-fragment.xml
Since the specification allows the application configuration resources
to be composed of multiple configuration files (web.xml and
web-fragment.xml), discovered and loaded from several different
places in the application, the question of ordering must be
addressed.
...
Two cases must be considered to allow application configuration
resources to express their ordering preferences.
1. Absolute ordering: an <absolute-ordering> element in the web.xml. a. In this case, ordering preferences that would have been handled by
case 2 below must be ignored.
2. Relative ordering: an <ordering> element within the web-fragment.xml. a. A web-fragment.xml may have an <ordering>
element. If so, this element must contain zero or one <before>
element and zero or one <after> element. The meaning of these elements
is explained below.
So, in my case, I had two options:
- Stick with version 2.5 : This works well on Tomcat 6 and 7, but is only moving problems to the future.
Migrate to version 3.0 of the spec and adjust my deployment descriptor accordingly:
- Update the version and schema in the web-app element, of course:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
- Adding a <absolute-ordering> element that defines the order in which the listeners should be processed:
<absolute-ordering> <name>bootstrap</name><name>ws</name><others/></absolute-ordering>
<listener id="bootstrap">
<listener-class>lu.estiedi.ws.WebAppBootstrap</listener-class>
</listener>
<listener id="ws">
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
Note the <others/> element : if it's not present, then the listeners that are not named will not be processed.
EDIT:
This doesn't actually solve the problem.
It went away yesterday at home, but this morning at work the solution didn't work. :-(
It looks like Metro is using a service provider ServletContainerInitializer, which are called before the Listeners.
If this is the way it's supposed to work, then the PosConstruct method is always called before the contextInitialized on Listeners.
Where do we initialise our application then, before the web services are created?