How to run a background task in a servlet based web application? How to run a background task in a servlet based web application? multithreading multithreading

How to run a background task in a servlet based web application?


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:

@Singletonpublic 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:

@WebListenerpublic 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.


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 ?


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();    }}