This link says that earlier versions of Tomcat (before 7.0.54) "renews its threads" thru ThreadPoolExecutor.run().
Why doesn't the init() method of contained Servlets seem to get called again?
A Servlet is initialized only once, either at web application startup or upon first use.
The same instance will then be used to serve all incoming requests, if necessary even multiple requests at the same time (unless you use the deprecated option to synchronize access, but even then there will be just a single instance, and a queue of requests for it).
Related
I have a ServletContextListener which performs some database management functions when my Java EE application starts. This runs in my application before JPA and other pieces of the application are started/loaded. If the database maintenance fails I am logging the errors. If the database maintenance fails the application will not function properly and I would like to halt the application.
How can I gracefully and correctly stop the application from ServletContextListener.contextInitialized?
Solution given by Viven below is close but not quite. When I throw a RuntimeException Glassfish is left in an inconsistent state where its admin console is not accessible but some process is still running and keeping port 3700 (IIOP?) open which then prevents a restart.
In your listener, catch any exceptions and use servlet context attributes to store flags or other useful information about the error. You should probably also log something to indicate that the app is non-functional.
At this point, your options may be dictated by the architecture of your app. If all requests are handled by a single controller/dispatcher servlet, it might make sense to have its init method check the context attributes and throw an UnavailableException. Just be aware that the exception only applies to the specific servlet throwing it. This makes the approach less manageable if your app contains many servlets or allows direct access to other resources.
Another option would be to create a filter that intercepts every request, checks the context attributes and then throws an exception. Other variations are certainly possible.
If your ServletContextListener throws an exception, the webapp won't load correctly and the application server may block all subsequent request (and respond with a 500 error).
It isn't exactly preventing the application to start, nor stopping the application, but it prevents any further usage of the app and could be useful in your case.
After proper verification in the spec, this behaviour isn't mandatory in the specification. The server may (not must) return 500 errors. This solution has to be used carefully, therefore.
See this Answer for a quote from the Servlet spec.
I'm checking a Java Servlet tutorial, but I miss the information of when exactly the servlet is destroyed by the server?
and what if I want to destroy manually an unused Servlet to conserve a memory for other tasks!
Because as I know every server has its limit in memory and hosting unused servlets is wasting of resources and application quality,
Thank you to clarify this point because the application performance is one of the most important issue to care about during the development process!
There is only one instance of the Servlet on each node in multi-clustered environment or you can say there is only one instance of each Servlet on each JVM machine.
Servlet is initialized on application startup or at the first time when the servlet is invoked.
when exactly the servlet is destroyed by the server?
All the Servlet instances are destroyed when server is shutting down or on application disposal.
I want to destroy manually an unused Servlet to conserve a memory for other tasks!
You can't destroy the Servlet manually and Servlet is just like worker not for data container. In most of the cases Servlet doesn't contain any instance members to avoid multi-threading issues.
The Servlet specification does not say when a servlet must be shut down and destroyed, other than that it must be done before the container completes a normal shutdown. A container is otherwise permitted to remove an idle instance from service at its own discretion, as long as it is prepared to fire up a new instance later if one is needed.
The specification does not define a mechanism for forcing a servlet instance to be unloaded. It having been unloaded, reclaiming its resources (mostly memory) is the job of the garbage collector, and when that happens is difficult to influence.
Overall, these are exactly the kind of details that you choose Java technology to avoid worrying about. If you insist on worrying about them anyway then look to the documentation of your chosen servlet container -- if there is a supported way to do what you are after then you will find it documented there. Such a thing would be container-specific.
The container decides when to unload the servlet , this sequence releases any resources it is holding so that it can reacquire it if the servlet is loaded again.
the unloading sequence calls a servlet's destroy() method when the servlet is set to be unloaded. The destroy() method houses the clean up actions written by the servlet developer. In practice it should free any resources it has acquired that will not be garbage collected at this step. The destroy() method should also give the servlet a chance to write out its unsaved cached information or any persistent information that should be read during the next call to init().
if we call destroy() on servlet then it doesn't mean that our servlet will be unloaded. You can simply call the destroy method alone without unloading the servlet. However when the container decides to unload the servlet instance from memory then container runs destruction mechanism and destroy method is one of steps of the destruction mechanism.
The web container calls the destroy method when it needs to remove the servlet such as at time of stopping server or undeploying the project.
According to the java docs, it says that If SingleThreadModel is used there are two ways a servlet instance will be created and used
1. Create one servlet instance and make the service() method synchronized and thus allow only one thread to execute the service method.
2. Create a pool of servlets and serve the request by using one servlet instance from the pool for each request.
THe question which I want to ask is I have also read a new Servlet instance is created and destroyed for every request. Now which one is correct
Here's what the spec says (version 3.0, section 2.2):
For a servlet not hosted in a distributed environment (the default), the servlet container must use only one instance per servlet declaration. However, for a servlet implementing the SingleThreadModel interface, the servlet container may instantiate multiple instances to handle a heavy request load and serialize requests to a particular instance.
In the case where a servlet was deployed as part of an application marked in the deployment descriptor as distributable, a container may have only one instance per servlet declaration per Java Virtual Machine (JVMTM)1. However, if the servlet in a distributable application implements the SingleThreadModel interface, the container may instantiate multiple instances of that servlet in each JVM of the container.
Note that you should really not use the single thread model. Just make sure your servlet is thread-sae. A servlet is typically stateless, so you don't have anything to do to make it thread-safe.
From the docs for SingleThreadModel:
Ensures that servlets handle only one request at a time
This is in essence a way to make non thread-safe servlet code work. Note that the container is free to choose any of the two implementations to adhere to the spec:
Create a single instance of the servlet and ensure that it handles only one request at a time
Create a pool of servlet instances and hand over a request to an available servlet instance.
My application consists of 2 servlets,the major one loads the config files in init method and processes get/post requests,
if anything fails during config load, i need to stop the application.
as far i know, i couldnt be able to stop whole application context through some java code ,hence i'm throwing UnavailableException in Servlet.hence i wont be processing get/post request.
but the second servlet does some dynamic reload of configuration on demand.but irrespective of major servlet failed or succeed,it processes reloading requests.
can you suggest a way to check the status of major servlet (running,stopped).so that second servlet can take decision whether to accept reload request or not.
Just share some status variable, like AtomicBoolean between two servlets. By the way, it's more clear design to make both servlets just accept http requests, decode them and pass requests to corresponding business-logic objects. This way, servlets will contain only logic concerned with HTTP sending/receiving.
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).
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.
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.
What container are you running?
Tomcat for example does support JMX. You can always write your own JMX-beans.