shutdown hook for java web application - java

I need to save some data preferrably when the java web application is stopped, or when tomcat is stopped. how can this be done?
Edit:
any drawback if I use the jvm shutdown hook?

Use a class that implements ServletContextListener in your web.xml:
<web-app>
<!-- Usual stuff here -->
<listener>
<listener-class>com.mycompany.MyClass</listener-class>
</listener>
</web-app>

Why do you want to do it specifically during shutdown? And do you really need to save it (as in "is it absolutely critical?") or would you like to (as in "would be nice but I'll live without it")?
The distinction is important - no matter what method you try (servlet / context listener as suggested by other answers or JVM shutdown hook) there are no guarantees that it will actually be invoked.
Servlet / context listener destroy events would only be triggered during normal (graceful) container shutdown OR during application reload. JVM shutdown hook would be triggered during process interruption as well; however killing a process (or cutting out the power) would obviously trigger neither.

As an addition to leonm's answer:
If you use Spring, you can use Spring's "lifecycle management" to achieve a similar effect. For example, you can annotate a method in a bean with #PreDestroy to have it invoked automatically on container shutdown. That way, you don't need to put anything into the web.xml.
See Spring beans factory lifecycle.

I suggest using ehcache to cache this information. If you use ehcache's persistent store, then when you start Tomcat again, the cached data will still be available.
In effect, this delegates the issue to ehcache, which is optimised for these types of problems.

Related

Springboot: need to be informed/notified when Web-Server is Up

I am writing a Springboot application embedding Tomcat as a Web Server.
At startup, some of my threads are ready (and so start doing their job) before Tomcat is. For many contraints I have, I want that these threads do nothing before Tomcat is ready
But I don't know how to decided to block/unblock my threads; to do so, I need to be informed of the Tomcat status. Is there:
a way to ask: isWebServerStarted()?
or a way to be notified asynchronously by a message saying: WEB_SERVER_IS_STARTED?
Thank you for help
FYI, I don't want to declare a kind of "private ReST endpoint" that my
application could try to reach in order to guess whether the webserver
is ready
Go with a ServletContextListener. Annotate your class with #WebListener and tell spring configuration about this listener by adding #ServletComponentScan annotation.

When exactly a servlet is destroyed?

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.

How do I run arbitrary code when a Java HTTP Servlet session ends?

Our application requires that we serialize some of the user's session data to the filesystem if their session expires. We would serialize it as is coming in but that would be too expensive due to the nature of our application.
If we can figure out a way to hook some sort of 'onSessionEnd' method we could run the cleanup code then.
You need to setup a HttpSessionListener for your application.
There is a method on the interface called onSessionDestroy that shall be called when the session ends and you can perform serialization right then.
To setup the listener, you add into web.xml:
<listener>
<listener-class>com.example.app.session.MySessionListener</listener-class>
</listener>

java web-application initialization and shutdown

I'm trying to implements initialization and shutdown of a webapp. That includes initialization and shutdown of:
Hibernate (v3.6);
C3P0 (v0.9.1.2);
EHCache (v2.3.0);
Quartz (1.8.4);
Other tasks specific to my webapp;
Using Tomcat 5.5.30 and Java 6. My idea is to avoid resource leaking, mostly because of the redeploy of the webapp in the development environment.
How should I implement this?
Usually for Web initialization and shutdown, you will write a ServletContextListener.
The steps to do this are:
Write a class that implements javax.Servlet.ServletContextListener
Add a tag to web.xml deployment descriptor to register the class you've just created
Deploy your application
When you deploy your application, contextInitialized method will be called. You can place all initialization you want here. On application shutdown contextDestroyed method will be called.
Its also possible to use the HTTP Servlet instead but the listener is a better option.
You have to extend a class with HttpServlet and setting the following stuff to your web.xml:
<servlet>
<servlet-name>StartupServlet</servlet-name>
<servlet-class>your.package.servlets.StartupServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
The class can overwrite the init and the destroy method.
But still you want to manage your resources in such a way that they do not leak if the application crashes and normal shutdown routines are not called.

Clean up after servlet if init() failed

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.

Categories