I am using JSP/Servlet on Apache Tomcat. I have to run a method every 10 minutes. How can I achieve this?
As you're on Tomcat, which is just a barebones servletcontainer, you can't use EJB's @Schedule
for this which is recommended by Java EE specification. Your best bet is then the ScheduledExecutorService
from Java 1.5's java.util.concurrent
package. You can trigger this with help of a ServletContextListener
like follows:
@WebListener
public class BackgroundJobManager implements ServletContextListener {
private ScheduledExecutorService scheduler;
@Override
public void contextInitialized(ServletContextEvent event) {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new SomeTask(), 0, 10, TimeUnit.MINUTES);
}
@Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
where the SomeTask
class look like this:
public class SomeTask implements Runnable {
@Override
public void run() {
// Do your job here.
}
}
If you were actually using a real Java EE container with EJB support and all on em (like Glassfish, JBoss AS, TomEE, etc), then you could use a @Singleton
EJB with a @Schedule
method. This way the container will worry itself about pooling and destroying threads. All you need is then the following EJB:
@Singleton
public class SomeTask {
@Schedule(hour="*", minute="*/10", second="0", persistent=false)
public void run() {
// Do your job here.
}
}
Note that this way you can continue transparently using container managed transactions the usual way (@PersistenceContext
and so on), which isn't possible with ScheduledExecutorService
— you'd have to manually obtain the entity manager and manually start/commit/end transaction, but you would by default already not have another option on a barebones servletcontainer like Tomcat anyway.
Note that you should never use a Timer
in a supposedly "lifetime long" running Java EE web application. It has the following major problems which makes it unsuitable for use in Java EE (quoted from Java Concurrency in Practice):
Timer
is sensitive to changes in the system clock, ScheduledExecutorService
isn't.Timer
has only one execution thread, so long-running task can delay other tasks. ScheduledExecutorService
can be configured with any number of threads.TimerTask
kill that one thread, thus making Timer
dead, i.e. scheduled tasks will not run anymore (until you restart the server). ScheduledThreadExecutor
not only catches runtime exceptions, but it lets you handle them if you want. Task which threw exception will be canceled, but other tasks will continue to run.Read on ScheduledExecutorService it has to be initiated by a ServletContextListener
public class MyContext implements ServletContextListener
{
private ScheduledExecutorService sched;
@Override
public void contextInitialized(ServletContextEvent event)
{
sched = Executors.newSingleThreadScheduledExecutor();
sched.scheduleAtFixedRate(new MyTask(), 0, 10, TimeUnit.MINUTES);
}
@Override
public void contextDestroyed(ServletContextEvent event)
{
sched.shutdownNow();
}
}
Also, you may try using the Java Timer from a ServletContextListener but it's not recommended in a Java EE container since it takes away control of the Thread resources from the container. (the first option with ScheduledExecutorService is the way to go).
Timer timer = new Timer("MyTimer");
MyTask t = new MyTask();
//Second Parameter is the specified the Starting Time for your timer in
//MilliSeconds or Date
//Third Parameter is the specified the Period between consecutive
//calling for the method.
timer.schedule(t, 0, 1000*60*10);
And MyTask
that implements TimerTask
is a class that implements the Runnable
interface so you have to override the run method with your code:
class MyTask extends TimerTask
{
public void run()
{
// your code here
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With