The specification is very clear about this (even if sometimes it is said in a strange way
).
Explanation During webapp life, the listeners are invoked in the order they are declared in the DD; no mistery there. If you have a list of listeners like the following one (S is for Session
whateverListener, C is for Context
whateverListener) :
C_Listener1S_Listener1S_Listener2C_Listener2S_Listener3 then when an event occurs, the container goes through this list,
in this order, and calls matching listeners. Again, no mistery.
At application shutdown, the story changes. To explain what happens, let's imagine a small algorithm the container uses to reorder listeners, in order to be able to do the same processing as during webapp life ( go down the list and call each matching listener).
1. Container inverts the list order. The list becomes :
S_Listener3C_Listener2S_Listener2C_Listener1S_Listener1 2. Container sorts the list, assuming SListeners stands for 1, and CListeners stands for 2. The list becomes :
S_Listener3S_Listener2S_Listener1C_Listener2C_Listener1 Now the process is the same as during webapp life, and ensure webapp shutdown is safe.
Why such a process ? For some classes in the servlet API, you have been told that they have container callback methods to manage their lifecycle (init, destroy). The reason for init method is to allow correct initialization before any request is served. The reason for destroy method is to allow the developer to free any resources the app can hold before the object is garbage collected.
The container always ensure that every components gets a chance to say goodbye and clean up its resources before getting rid of them. The same happens for webapp lifecycle.
The init and destroy methods of Servlet or Filter class can be compared to the Listeners' methods of the webapp. They ensure that : a session object has a chance to initialize itself before being used, and has a chance to say good bye before dying. The webapp itself has its init/destroy with the ServletContextListener.
Keeping this opening/closing enforcing policy, (like an XML parser would check for order of opening/closing tabs) the container closes nested components before the components holding them.
A webapp can be seen as a Context, and a session belongs to a context. With the
philosophy I explained, it comes that before closing the webapp, the container closes any nested components, hence closes the Session before the webapp.
Logically, Listeners are called when the corresponding components are closed, and as we saw Session are closed before webapp, so SessionListeners are called BEFORE ContextListeners.
A bit long, but I hope it's clear.