views:

175

answers:

3

I have an Initializer class that implements the ServletContextListener interface. In its contextInitialized() method, I initialize some global classes that have to be destroyed, otherwise the servlet cannot be unloaded.

However, when the servlet's init() method throws a ServletException, the contextDestroyed() method never gets called --> resources are not release --> servlet does not get unloaded by Tomcat (it remains in "running" state even though its init method never finished).

My question is this - how do I cleanup the resources in this case?

Bonus: why does the servlet even get to "running" state? I understand from the documentation that it's not supposed to be running unless the init() method finishes successfully.

Edit - I think this is because each status line displayed in Tomcat Manager represents an entire war, and not a servlet. A war may contain several servlets, with some succeeding to start and others not. The Initializer is called when the container starts, and its destroy is called only when the entire container is dropped. This leads to a related question - is there a similar built-in way to monitor the state of individual servlets?

(I'm aware I can write custom code to monitor the servlet, either via JMX, or not, but that's out of the scope of this question).

+1  A: 

In real world the init() should never fail. If it fails, then it is a programming error which the developer is supposed to fix. The appserver webcontainer has nothing to do with it. The servlet will simply be kept unavailable.

BalusC
It's a configuration / deployment error, not a programming error. How can I monitor the status of servlets then?
ripper234
Configuration errors are still your responsibility. Monitoring can just be done by reading logs.
BalusC
I fail to see how this is relevant. Part of what our Operations guy is monitoring is the container status. We thought that it represents _servlet_ status, but apperantly it does not. The only question that remains is whether Tomcat is supposed to stop the container if all the servlets in it failed to start.
ripper234
The answer to that is no.
BalusC
A: 

What container are you running?

Tomcat for example does support JMX. You can always write your own JMX-beans.

Bas
Tomcat, as i stated in the question. I know I can write custom (JMX or not) code to monitor this, but that's outside the scope of this question - I wanted to know if there's a ready made solution.
ripper234
+1  A: 

As far as I can tell there's absolutely no way to do so without an external request. ServletContextListener gives you the correct signal (when all servlets have been initialized - successfully or not), but you can't enumerate all servlets in the context to test their status because the relevant ServletContext methods were deprecated and now return an empty enumerator.

In short, the only way to do this is via a nonstandard API; in particular, it's almost trivial to do this with Tomcat's JMX API, which is the course I'd recommend.

Tomer Gabel