We have a requirement where in we need to monitor remote JVM details via JMX using a simple servlet application. So things done till now in a standalone application is
ServletContext
A ServletContext represents your entire web app as running in the Servlet container. The context is established before the first HTTP request is processed by the servlet, as promised by the Servlet spec. While a HttpSession represents each user’s work session (technically, a thread through your servlet code), a ServletContext
represents the scope across all those users.
To hook into the set-up and tear-down of the servlet context, implement a ServletContextListener. Tip: Auto-deploy your listener by marking it with @WebListener annotation. That interface requires a pair of methods, each called when your web app is being set-up before the first Servlet request is handled and when your web app is being torn-down.
Tip: That tear-down method is a good place to shut down your ScheduledExecutorService
. The threads associated with your executor service may survive after your web app ends. You likely do not want that to happen.
See this Question: How to get and set a global object in Java servlet context
See also this nice summary of Servlet scope by BalusC.
You can access the current servlet’s ServletContext
by first accessing its ServletConfig.
// … in your Servlet, such as its request handler methods like `doGet` …
ServletContext sc = this.getServletConfig().getServletContext() ;
And how about in a ServletContextListener
, how do we access the servlet context? When either of the two methods on the listener is called, a ServletContextEvent is passed. From there call ServletContextEvent::getServletContext().
So where to store your web app’s global variables such as your ScheduledExecutorService? The servlet context has a built in map of String
to Object. These are called “attributes”. Call setAttribute( String , Object ) to store an attribute mapping. So make up a name for your ScheduledExecutorService
to use a key into this map.
ScheduledExecutorService sec = … ; // Instantiated somewhere in your code.
…
String key = "myScheduledExecutorServiceForXYZ" ;
sc.setAttribute( key , sec ); // Storing the executor service as a generic `Object` for use later.
Later you can fetch your ScheduledExecutorService
in the same manner. You will need to cast from Object
to the known class, in this case ScheduledExecutorService
.
Object o = sc.getAttribute( key ); // Fetch the `ScheduledExecutorService` from the servlet context’s built-in map of attributes.
// Cast to known class. If in doubt, test first with [`instanceOf`][11].
ScheduledExecutorService sec = ( ScheduledExecutorService ) o ;
You can ask for a list of all stored attribute names by calling ServletContext::getAttributeNames.
Here is a diagram of mine to get an idea of the hierarchy of scope in a Servlet environment. Note how each layer of scope has its set of attributes, its own map of String
to Object
. As you go down the diagram, each set of attributes has a shorter lifespan.
If on java ee 7, try using the javax.enterprise.concurrent.ManagedScheduledExecutorService
Then you can do a resource injection and start the task with code similiar to below.
@Resource
ManagedScheduledExecutorService mses;
public void startTask() {
mses.scheduleAtFixedRate(runnable, 10, 10, SECONDS);
}
In Java EE 6 you could have a servlet create/remove using the timerservice API