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.
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.
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. –
Trahurn 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? –
Breastfeed long initialDelay = 0
and long period=1
this means at 00.00 every day right? –
Breastfeed org.springframework.scheduling.concurrent.ScheduledExecutorTask
? –
Faustena 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. –
Forney 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. –
Forney scheduler.shutdownNow()
is not correctly invoked as per the example. If this is not invoked, then the schedule thread will indeed keep running. –
Sakai 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 ?
You can use cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php
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();
}
}
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.
© 2022 - 2024 — McMap. All rights reserved.