I'm using Java and I want to keep a servlet continuously running in my application, but I'm not getting how to do it. My servlet has a method which gives counts of the user from a database on a daily basis as well as the total count of the users from the whole database. So I want to keep the servlet continuously running for that.
-
What do you mean, "continuously running"? – skaffman Jan 14 '11 at 12:41
-
1what do you mean by continously running? It will run as long as your app server runs – fmucar Jan 14 '11 at 12:41
-
2I don't understand why it has to run continuously... if someone wants the 'user count' then they call your servlet method and you give it to them? – trojanfoe Jan 14 '11 at 12:44
-
@trojanfoe Actually i want the usercount on daily basis,so for that i will have to run the servlet manually everyday so instead of doing that i want to run the servlet contineously.so i wont need to run the servlet everyday. – pritsag Jan 14 '11 at 12:59
-
@pritsag Servlets are not the way to solve this problem - if you want 'stats' collected throughout the day then use some other technology. – trojanfoe Jan 14 '11 at 13:07
-
@skaffman,@faith Actually to get the count i will have to run the servlet manually everyday as database will be updated everyday as users will be created everyday.so instead of running servlet manually everyday i want to keep the servlet running. – pritsag Jan 14 '11 at 13:07
-
1@pritsag: A servlet is there to serve user requests, not to run batch jobs. – skaffman Jan 14 '11 at 13:08
-
@trojanfoe can u suggest me the other technologies ? – pritsag Jan 14 '11 at 13:16
-
@pritsag If the database is accessible from the client then a simple Java program using JDBC (running from the client itself) might be appropriate. Other than that you could try a scripting language (perl, python, etc.). If the database is not accessible from the client then you need to create a batch architecture on the server that perhaps stores its results on the database itself - you then then use a Servlet to allow clients access these stats. – trojanfoe Jan 14 '11 at 13:34
5 Answers
Your problem is that you misunderstand the purpose of the servlet. It's intented to act on HTTP requests, nothing more. You want just a background task which runs once on daily basis.
EJB available? Use @Schedule
If your environment happen to support EJB (i.e. a real Java EE server such as WildFly, JBoss, TomEE, Payara, GlassFish, etc), then use @Schedule
instead. Here are some examples:
@Singleton
public class BackgroundJobManager {
@Schedule(hour="0", minute="0", second="0", persistent=false)
public void someDailyJob() {
// Do your job here which should run every start of day.
}
@Schedule(hour="*/1", minute="0", second="0", persistent=false)
public void someHourlyJob() {
// Do your job here which should run every hour of day.
}
@Schedule(hour="*", minute="*/15", second="0", persistent=false)
public void someQuarterlyJob() {
// Do your job here which should run every 15 minute of hour.
}
@Schedule(hour="*", minute="*", second="*/5", persistent=false)
public void someFiveSecondelyJob() {
// Do your job here which should run every 5 seconds.
}
}
Yes, that's really all. The container will automatically pickup and manage it.
EJB unavailable? Use ScheduledExecutorService
If your environment doesn't support EJB (i.e. you're not using not a real Java EE server, but a barebones servletcontainer such as Tomcat, Jetty, etc), then use ScheduledExecutorService
. This can be initiated by a ServletContextListener
. Here's a kickoff example:
@WebListener
public class BackgroundJobManager implements ServletContextListener {
private ScheduledExecutorService scheduler;
@Override
public void contextInitialized(ServletContextEvent event) {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);
scheduler.scheduleAtFixedRate(new SomeHourlyJob(), 0, 1, TimeUnit.HOURS);
scheduler.scheduleAtFixedRate(new SomeQuarterlyJob(), 0, 15, TimeUnit.MINUTES);
scheduler.scheduleAtFixedRate(new SomeFiveSecondelyJob(), 0, 5, TimeUnit.SECONDS);
}
@Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
Where the job classes look like this:
public class SomeDailyJob implements Runnable {
@Override
public void run() {
// Do your daily job here.
}
}
public class SomeHourlyJob implements Runnable {
@Override
public void run() {
// Do your hourly job here.
}
}
public class SomeQuarterlyJob implements Runnable {
@Override
public void run() {
// Do your quarterly job here.
}
}
public class SomeFiveSecondelyJob implements Runnable {
@Override
public void run() {
// Do your quarterly job here.
}
}
Do not ever think about using java.util.Timer
/java.lang.Thread
in a Java EE / Servlet based environment
Last but not least, never directly use java.util.Timer
and/or java.lang.Thread
in Java EE. This is recipe for trouble. An elaborate explanation can be found in this JSF-related answer on the same question: Spawning threads in a JSF managed bean for scheduled tasks using a timer.

- 1,082,665
- 372
- 3,610
- 3,555
-
9@BalucS Thank you sir,your solution helped me and I learned about ScheduledExecutorService which was new to me as i m new to java.Thank you once again. – pritsag Jan 15 '11 at 07:36
-
-
1@Ashwin *web.xml* is a [Deployment Descriptor](https://en.wikipedia.org/wiki/Deployment_descriptor). The class *UpdateCount* is not related with deployment, so it doesn't have to be put in *web.xml* – informatik01 Aug 12 '13 at 00:15
-
12One crucial issue with a `ScheduledExecutorService`: Be sure to **capture *all* exceptions** in your executor. If an exception escapes from your `run` method, the executor silently stops executing. This is a feature not a bug. Read the doc and study up with some googling. – Basil Bourque Oct 18 '14 at 17:50
-
Question: This task `scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);` at what time will start? at 00:00 or every 24h from the moment the webApp will deploy in the server? – yaylitzis Sep 23 '16 at 11:20
-
@yaylitzis: just consult Javadoc: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html#scheduleAtFixedRate(java.lang.Runnable,%20long,%20long,%20java.util.concurrent.TimeUnit) (check 2nd argument) – BalusC Sep 23 '16 at 11:53
-
Just to be sure.. with `long initialDelay = 0` and `long period=1` this means at 00.00 every day right? – yaylitzis Sep 23 '16 at 11:57
-
@BalusC, what about `org.springframework.scheduling.concurrent.ScheduledExecutorTask`? – ACV Jul 03 '17 at 11:36
-
I've followed through the code in your answer and used it to create a `ServletContextListener`, using the same principles to wrap the only instance of a `ScheduledExecutorService` that exists in my EE app. (There are no other places in the code in which I've used `Thread`, `Runnable` or `ScheduledExecutorService`.) However, stopping/undeploying the application still results in an error message of `SEVERE: The web application [/MyApp] appears to have started a thread named [pool-4-thread-1] but has failed to stop it. This is very likely to create a memory leak.` I don't know why that happens. – Agi Hammerthief Jun 26 '18 at 09:12
-
Following on from my prior comment: Creating a `ThreadFactory` that sets the thread to be a daemon (`Thread t = Executors.defaultThreadFactory().newThread(runnable); t.setDaemon(true);`) and then using the created `ThreadFactory` as an argument to `Executors.newSingleThreadScheduledExecutor()` solves the issue for me. (The only I/O work done by the task in question is to read from a small JSON file. It uses `javax.mail` to send an email based on configuration in that file.) I'm not expecting the application to be stopped/reloaded for about a month. I don't forsee an issue with using a daemon. – Agi Hammerthief Jun 26 '18 at 12:15
-
1@Agi: that will happen if `scheduler.shutdownNow()` is not correctly invoked as per the example. If this is not invoked, then the schedule thread will indeed keep running. – BalusC Jun 26 '18 at 15:12
-
@BalusC I noticed the scheduler is `private` in your `ServletContextListener`. So if we want to use it outside of the `ServletContextListener`, should we initialize another scheduler object with `Executors.newSingleThreadScheduledExecutor`? Or should we just make the variable in the `ServletContextListener` public? – theyuv Mar 09 '19 at 14:39
I would suggest using a library like quartz in order to run the task at regular intervals. What does the servlet really do ? It sends you a report ?

- 749
- 4
- 9
-
yes ,it gives me the count of the user created per day and also the count of the total users in my database . – pritsag Jan 14 '11 at 13:09
-
1huuu? Can you describe the FULL architecture of your system. I'm lost. – Twister Jan 14 '11 at 13:17
-
@Twister i m new to java and in learning phase sir and really dont konw much about the servlets. – pritsag Jan 14 '11 at 13:21
-
The problem is not about servlet. What is the application your are talking about ? (ps : it is a bad idea to delete your comments, especially comments I answered to) – Twister Jan 14 '11 at 13:22
-
@twister when user will hit the application,he will get all details like how much users are created today,how much users are craeted till now etc.and i want to run the servlet run in background contineously so that the user could get the updates.I kno this is not the proper explation.(ps:i know it was a bad idea.sorry for that .) – pritsag Jan 14 '11 at 13:26
-
@pritsag You may attach user date/time of creation to user account in your database and count it on the fly when user hit a button on the web page. This is more powerful and flexible since you can decide which interval you what to count. However, if you really want a cron-like system, e.g. every day, every hour, etc., you may use quartz to run a task on a certain interval. – gigadot Jan 14 '11 at 13:38
-
@gigadot thanks for your kind reply sir.actually i have implemented the method in servlet which is giving me the count perfectly.but the thing now i want is actually instaed of running the servlet on daily basis i want to keep it running continweously so that whenever the request for updates about the count is sent, the response will be sent to user. – pritsag Jan 14 '11 at 13:49
-
@pritsag I think I now understand what you want. You don't understand the purpose of servlet and how it works. that's not your fault. I suggest you read answer by @BalusC carefully. That's what you need. – gigadot Jan 14 '11 at 14:02
Implement two classes and call startTask()
in main
.
public void startTask()
{
// Create a Runnable
Runnable task = new Runnable() {
public void run() {
while (true) {
runTask();
}
}
};
// Run the task in a background thread
Thread backgroundThread = new Thread(task);
// Terminate the running thread if the application exits
backgroundThread.setDaemon(true);
// Start the thread
backgroundThread.start();
}
public void runTask()
{
try {
// do something...
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

- 6,210
- 4
- 39
- 44

- 176
- 1
- 7
-
3This is definitely NOT the way to do it in a web application - look at the answer above by @BalusC instead - he is correct here and I would say you can trust all of his answers. – Yoshiya May 21 '18 at 13:46
In a production system that may have multiple non-jee containers running. Use anot enterprise scheduler like Quartz scheduler which can be configured to use a database for task maamgememt.

- 989
- 17
- 40