Where should I place clean up code inside a web application? - java

I have the following problem:
I need to run some clean up code from various of classes loaded as part of a web application in Tomcat.
Cleanup code ranges from shutting down executors to database clean-up code.
I tried and found out (and learned afterwards that this is documented as such) that:
All servlets and filters will have been destroyed before any
ServletContextListeners are notified of context destruction.
So this rules out running the clean up code in any ServletContextListeners.
I put the clean up code in the destroy method of a Servlet, but realized that if the client does not require its use it will never be loaded and as a result the clean up code in the destroy method will never run.
So now I am stuck.
Where is the best place to put clean up code in a web application since e.g. if I put it in a servlet I can not ensure that the client will use that and if I put it in a listener it is too late?

If you have the option to configure your servlet to load on startup, that would get around the problem as stated.
See What does the servlet <load-on-startup> value signify for an example and some discussion.

Related

How to listen for a JAX-RS undeployment

I am running a JAX-RS application that needs to do some clean up once the application is shut down. I installed a shutdown hook for this purpose and it works fine. However, in unit tests, the shut down hook is (of course) not triggered since the JVM is not shut down in between two calls. This I want to fix and only use the shut down hook as a last resort. I imagine, the same would happen if I only undeploy the application from a servlet container without explicitly triggering a shut down. Also, I imagine that I might have created a memory leak in the case the application container continues running with my shut down hook still registered?
The question: Is there a possibility to listen for the server / servlet responsible for my JAX-RS application to be destroyed? I was thinking about something like the Servlet#destroy method.
I am looking for something like: new ResourceConfig().register(new MyShutDownListener()) or something I can do in a ShutDownBinder? Any ideas?
Well, I found the org.glassfish.jersey.server.spi.ContainerLifecycleListener interface. It seems as if this interface found its way into Jersey in v2.3 while my built was using v2.1. I now upgraded Jersey and use it happily. (This is however a Jersey interface, it does not have a sibling in JAX-RS.)
If this is not an option for a future reader of this answer, I found another solution with using GrizzlyWebContainerFactory which allows me to use define my own servlet for starting up the application. This solution was however way more verbose.

How to make Tomcat wait until web application finishes?

I have a Java web application, packaged as a "war" and deployed in Tomcat. The application uses Jersey to implement REST web services.
This application sometimes updates a text (XML) file. I guess that if Tomcat is stopped while the application is still updating this file, the file may be corrupted. In order to prevent the file corruption I would like Tomcat to wait until the file is closed before the exit. Now I wonder how to implement it.
So, my question is how to make Tomcat wait until a web application finishes.
Have a look at the ServletContextListener is particular the context Destroyed method.
Notification that the servlet context is about to be shut down.
void contextDestroyed(ServletContextEvent sce)
I'd take a different approach in your case (this may not be an answer to your question, but a proposal for your case).
Write the new xml file in a temporal one (conf.xml.tmp), so you still have the original one (conf.xml) untouched.
Once finished generating the xml, just move the newly generated one (conf.xml.tmp) on top off the original(conf.xml).
(You can also make a copy of the original for backup purposes).
This way, if tomcat stops while processing the xml generation you will always have a working xml.
The key here is that moving a file in the same disk is somehow an "atomic" operation, it will be done or not, but it will be not done half done.
Hope it helps
You can modify your shutdown script to take care of this. Make sure that file is in consistent state and then call shutdown.
You can check if file write is under process then sleep the script for say 5 min and then call shutdown.sh/shutdown.bat script.
Apart from this you can also do at java level; but i will prefer controlling it externally. This way you can modify it independent of your core application.

Convert Java Servlet to Standalone Java Application

I have a legacy Java servlet that is currently running in a Tomcat container. I want to run it outside the container, as a standalone Java application. The primary intention in doing so is because the new role in which this application will be deployed, involves only computation, and no servicing of requests.
How should I go about modifying the servlet code? Will pulling out the servlet's init() code into the main() method of a new class help?
Extract the functionality you want from the servlet to other classes, so that the servlet is only the web interface to the functionality.
Those other classes should ideally not use anything in javax.servlet.*.
Then create a separate class with a main method that uses those other classes, in an appropriate way.
I would transform the servlet class into a main class, as you mentioned. The main method of the new class will create an instance of main class, execute init method to initialise if (potentially using the arguments received from the command line). Then invoke the service method inside a try/catch/finally block and invoke the destroy method of the servlet inside the finally block. Of course, your new service method will be invoked without parameters and will not contain any references to the servlet api.
yes.
The servlet implements the interface to interact with the Tomcat servlet container. If there are no settings read from the servlet context (path names, configuration paramters) you can extract the logic into a main class.
You will need to make sure you do not rely on the request/response scheme in your services. Usually if only one process runs code is much easier to write than in concurrent scenarios. But one cannot be sure there will be no such effect (for example caches that are now request based will not be emptied in standalone).
also remove any servlet api dependencies in your code. It will not work and is no longer required.
good luck!
You have to do that carefully. It may happen that some filters are doing necessary work not seen within the servlet
Assuming your case is rather simple and a GET or POST just triggers the code, it should be easy to convert into a classical java application.
Just call the former init part and the code from doGet or doPost respectly.
You need to figure out a couple of things first, the functionality in the servlet will probably react to some of the url's parameters.
first figure out what the computational part is and what parameters it expects,
once you understand that, figuring out what to put in your standalone application will be trivial.
another approach is to embed Jetty in your main application and let that run your servlet,
this will leave your servlet code untouched reducing the risk of introducing bugs

DeleteOnExit jvm shutdown

I currently have a tomcat webapp that needs files deleted when the JVM is being shutdown. I created a custom ContextLoaderListener to handle the contextDestroyed event. Inside of here I call deleteOnExit on the appropriate files. However, ever since jdk 1.6.0_14 I am unable to deleteOnExit. Googling indicates that there was a change that is somewhat expected, but I haven't seen a work around for this. Anyone have any ideas?
Below code does NOT work.
for(File f : myFileList)
try{
f.deleteOnExit()
} finally {
f.delete()
}
I don't think you're going to be happy with the results of cleaning up files as part of an orderly shutdown process. For example, if your process crashes or is stopped with "kill -9", then your cleanup code will not run.
A more reliable approach is to set up the environment during start up / initialization. If you segregate the files for this application in a specific directory, then this is easy: just empty the directory in question.
Exactly where the "empty directory" call belongs, depends on your application. For example, if you wrote a servlet, then use the init method. Or, if you use Spring, then they provide various initialization hooks such as an init-method.

Loading a class file immediately AFTER startup [duplicate]

This question already has an answer here:
Using special auto start servlet to initialize on startup and share application data
(1 answer)
Closed 7 years ago.
We have a few war files deployed inside an ear file. Some of the war files have a class that caches static data from our PLM system in singletons. Since some of the classes take several minutes to load we use the load-on-startup in the web.xml to load them ahead of time. This all works fine until we attempt to re-deploy the application on our production servers. (WebLogic 10.3) We get an exception from our PLM API about a dll already being loaded. Our PLM vendor has confirmed that this is a problem and stated that they don't support using the load-on-startup. This is also a huge problem on our development boxes where we have redeploy the app all the time. Most of us, when we're not working on one of the apps that uses a cache, have them commented out. Obviously we can't do that for the production servers. Right now we transfer the ear to the production server, deploy it in the console, wait for it to crash, shut the app server instance down and then start it up again.
We need to find a way around this...
One suggestion was to create a servlet that we can call after the server boots that will load the various caches. While this will work I'm looking for something a bit cleaner. Is there anyway to detect once the server started and then fire off the methods?
Thanks.
We had a similar problem with a third party JDBC driver that loaded a native DLL. When redeploying the app the driver would crash saying the DLL was already loaded. The solution (if one can call it that) was to move the driver from deploy into lib. This way the driver was global to the app server and didn't need to be reloaded when the app was redeployed.
What about using a servlet container lifecycle listener, such as ServletContextListener?
Example on how to use.
EDIT: Sorry, after re-reading your question I don't think this will work. You want something that will load only once per server life, not application life. The ServletContextListener's methods will be called each time the app is deployed, just like a load-on-startup servlet (which it seems you are using). My suggestion will do the exact same thing in a different way.
I would try Chris Nava's suggestion.
EDIT2: It looks like tomcat has some lifecycle listener(s) available to it also. It looks like documentation is sparse, but this potentially would allow you to do something on server startup specifically only once.
EDIT3: Yes, a tomcat lifecycle listener is the way to go. This link explains pretty well how to set one up. Should be fairly straight forward. If you ignore the part about adding the Transaction to tomcat, it goes over pretty thoroughly how to add a lifecycle listener.

Categories

Resources