In applications, one sometimes needs to run some processes before and after the application’s run. Whereas in an application server you have full access to the web application lifecycle through the javax.servlet.ServletContextListener interface, there is no such thing in a plain old Java application.
Doing things before is easy enough since you have access to the application’s entry point in the form of the public void main(String[] args)
method.
But how do you things after?
Where is (are) your application’s exit point(s)?
First, there are some different reasons for an application to stop:
- The application has finished its job (a not too unlikely occurence),
- An external signal was sent to end the JVM (CTRL+C),
System.exit()
was called in the code,- An uncatched exception was thrown.
Whatever the cause, one should be able to do some operations including:
- closing the connection to a database,
- closing the datastore if one uses a persistence framework (Hibernate, TopLink),
- releasing other resources,
- closing streams,
- and, last but not least , logging a message at the end of the application.
A word on the last one: you should always add a log telling the successful finish of your application. In this case, no problem. But on the contrary, if you don’t, you will always try to figure how the application ended.
Back to the problem at hand:
how do you do such things? The java.lang.Runtime class has a static method addShutdownHook() that accepts a Thread
as a parameter.
This thread is started when one of the previous event happens.
There are limitations of course. Such threads:
- are called in no specified order meaning the sequence of the hooks should not be depended upon! This is some serious limitation, think about it.
- must be runned since the system will only allow a fixed amount of time to execute it.
The following snippet just logs the normal ending of an application:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
// Replace this by a call to your favorite log framework
System.out.println("Application finished");
}
}
Another option is to use frameworks entirely dedicated to batch processing. I recommend having a look at Spring Batch. I recently used it in my last project and though it is a little heavyweight for what I had to do, it maps entirely what a batch application must do (just wait for version 2.0 to go out since the API changes a bit too much for my taste).