Having implemented a ContextListener I can now happily deal with contextDestroyed events by closing down my connection pools and flushing my caches etc.
I was surprised recently when contextDestroyed was called at a time when my server was not being shut down - it seemed to be at some arbitrary time which I have not been able to track down.
Is there any defined event or set of circumstances that trigger contextDestroyed?
Should I ensure that everything I do when contextDestroyed is called is reversible? Do I need to make all my pools survive a destroyed/initialized cycle? Was I wrong to assume I would only get a contextDestroyed when Tomcat was being shut down or my war was being replaced?
Through a series of trial and error testing I have found that contextDestroyed() is called when;
The server is .WAR is being updated/removed.
The server is shutdown due to administrator intervention.
The server is shutdown due to a coding error. Something that would
terminate a non-server application termination.
If you are experiencing issue #3, as you are suggesting, I think the best possible course of action is to safely (be sure not to create an infinite loop) call contextInitialized() to ensure pools are recreated properly.
See: http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html
contextDestroyed(ServletContextEvent sce): Receives notification that
the ServletContext is about to be shut down.
I.e., it gets called when a web application gets unloaded (e.g., you remove or replace a .war file from the web-apps folder OR unload it using the Tomcat server-manager).
Related
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.
I am using ScheduledExecutorService for scheduling a thread. I wonder what happens when JBoss is shut down? Does it kill all the threads that are started within the server, including the the one I scheduled? Do I have to do it manually using ScheduledFuture, and cancel the thread when ServletContext is destroyed?
There are two methods:
java.util.concurrent.ExecutorService.shutdown()
java.util.concurrent.ExecutorService.shutdownNow()
JBoss won't call any of these unless you do it in method which will be called upon shutdown. For web applications you have the chance to do it in javax.servlet.ServletContextListener.contextDestroyed(ServletContextEvent).
Of course this is the JavaEE/Servlets way. You can hide it by using e.g. Spring Framework. By creating org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler you'll get shutting down for free (this class implements org.springframework.beans.factory.DisposableBean). See the details here.
I want to have some method run, only after my WAR has been deployed to JBoss.
The problem: Currently I am using #PostConstruct to load saved schedules from the DB. The problem is that I am creating instances of the Schedulers from this method, which in turn is starting the Quartz schedulers, which is stopping JBoss from completing the deploy.
If there are no schedules to load, my WAR deploys fine, but if there are schedules they are causing the deploy to fail, because JBoss is "waiting" for the schedules to actually complete.
Is there some way to delay the method call until after it is fully deployed?
Or alternatively, is it possible to make Async calls on the Server (from the Server code)?
Java EE specification heavily refrain any thread manipulation outside facility provided by the application server.
You shouldn't in any case use a container manged thread in an infinite loop; the container expect the thread to be returned. Thread creation can still be done without too much collateral damage (if you don't put several apps on the server as the container won't be able to manage the resources between all the applications) but the any container thread must be returned.
In the new Jboss 7 there is some Java EE scheduling facilities (#Scheduling and timer, with possible persistent timer). A quick search show some example how to run Quartz in JBoss 7: How to enable Quartz scheduling in Jboss AS 7.0?
In older JBoss more advanced integration exist (JCA integration is the only standard way to get finer thread management). Use google to find them.
Wouldn't the simple ServletContextListener solve the problem for you? Just implement whatever you need in contextInitialized method.
In JBoss 7, there is a management api.
Maybe you can use it to check if the server is started (with a singleton and a TimerService).
Sample code:
ModelControllerClient client = ModelControllerClient.Factory.create(InetAddress.getByName("localhost"), 9999);
ModelNode op = new ModelNode();
op.get(ClientConstants.OP).set("read-attribute");
op.get(ClientConstants.NAME).set("server-state");
ModelNode returnVal = client.execute(op);
if(StringUtils.equals(returnVal.get("result").toString(), "\"running\"")){
LOGGER.info("Server running, init start actions");
timer.cancel();
}else{
LOGGER.info("Server not running, wait");
}
I have a system written in java where I have multiple distinct objects each with different resources in use. Some have connections to activeMQ queues, some have network connections and others have open files. Some also contain running threads.
When a fatal error occurs anywhere in this system, I need to shut it down and correctly close all resources and stop all running threads.
My problem arises when the object that caused the error needs to start the shutdown process. This object does not know about the other objects that have open files and so on. So it can basically release all its resources and that is it.
I am looking for a clean way to achieve this without getting messy and passing multiple object references around the system.
Any insight is appreciated. Thank you.
Create a central Lifecycle object which all of these other objects in your application have a reference to, and which in turn has a reference to all of these other objects. In addition, each of these objects should implement a common interface such as
public interface ShutdownListener {
void onShutdown();
}
When one of the objects needs to start an orderly shutdown, it can call lifecycle.shutdown() which can in turn call object.onShutdown() on all of the objects registered with it, in order to give these objects a chance to close their resources.
This is basically the Observer pattern.
If you use a dependency-injection container such as Spring, this type of thing is built-in - your beans can extend a certain interface to be notified when the container is shutting down.
You may be able to use Shutdown hook for that. In it you can notify all related objects, which, of course, need to be registered somewhere.
A java virtual machine allows the registration of Shutdown Hooks. Your database connection pool, your file IO manager, your activeMQ queues manager can all independently register their own shutdown hooks that each close all their resources cleanly.
A shutdown hook is a Thread that requires a reference to the resource manager(s) it's responsible for shutting down. The run method of this thread will be executed when the application is terminated. Your application has access to register a shutdown hook anywhere as Runtime.getRuntime() is available as a static call, so no need to wire it into the areas of the application that need it (although it is advisable that you register such shutdown hooks at the time of the creation of each resource manager).
More information here.
http://download.oracle.com/javase/6/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)
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.