Managed Scheduled Executor Service vs EJB Timer
Join the DZone community and get the full member experience.
Join For FreeOver the past years, I always used EJB Timer Service to implement scheduled tasks in my Java Enterprise applications. Since Java EE7, the ManagedScheduledExecutorService
is a new pattern to implement a scheduler service. The ManagedScheduledExecutorService
is part of the SE ScheduledExecutorService
and provides methods for submitting delayed or periodic tasks for execution.
Implementing a ManagedScheduledExecutorService
is quite simple. See the following example:
xxxxxxxxxx
public class MyScheduler {
ManagedScheduledExecutorService scheduler;
MyService myService;
public void init() {
this.scheduler.scheduleAtFixedRate(this::run, 500, 500,
TimeUnit.MILLISECONDS);
}
public void run() {
myService.processSomething();
}
}
In compare to a EJB Timer it seems to be quite simple to use this pattern. But the ManagedScheduledExecutorService
is more a lightweight scheduling framework, and it does not support features like transaction support, full lifecycle operations (create, read, cancel timers), which are supported by EJB Timers. In addition, EJB Timers can be persisted and so survive server crash and restart. And in fact I personally run into a problem with execution exceptions during a redeployment scenario in Wildfly a few days ago. So is a EJB Timer an outdated technology just because it’s an EJB?
The Advantage and Restrictions of EJB Timers
In the early beginning of my Java EE career I learned that EJB timers are persisted an managed by the ejb container on the application server level. This ensures that the timer is executed correctly without conflicts in scenarios with multiple threads.
This means even in a clustered environment, a persistent EJB timer runs only in one cluster member which might not necessarily be the same cluster member it was created in. Since we are today mostly talking about horizontally scalable applications spread across multiple servers, this seems to be a restriction. And this was also my first thought when I switched from EJB Timer to ManagedScheduledExecutorService
.
But on the other hand, that’s the common expectation for a timer at a specific point to fire only at one of the nodes in order to avoid duplication. For example, you might probably do not want to send out meeting notices twice from different nodes. So the idea that a persisted EJB Timer runs only in one instance even in a large cluster environment can be an important feature and not a restriction.
Non-Persistent EJB Timers
Since EJB 3.1 specification there is a variant of non-persistent EJB Timers. Non-persistent timers have similar semantics and behavior as the origin persistent timers, but without the overhead of a data store. This means they have a different life cycle and are easier to use than persistent timers. Non-persistent timers are active only while the application server is active and are not maintained across application server crashes, shutdowns and restarts.
But in contrast to the ManagedScheduledExecutorService
the non-persistent EJB Timer is transactional during the creation and cancellation which can be important for many scenarios. If a timer is created within a transaction and that transaction is later rolled back, the creation of the timer is rolled back as well. Similar rules apply to the cancellation of a timer.
This is an example how a EJB Timer can be implemented:
xxxxxxxxxx
public class MyTimerService {
MyService myService;
second="*/1", minute="*",hour="*", persistent=false) (
public void doWork(){
myService.processSomething();
}
}
In a clustered environment a non-persistent timer runs in each cluster member that it was created in. And a automatic non-persistent timers run in each cluster member that contains the EJB. So this means the non-persistent EJB Timer scales horizontal within a clustered environment – e.g. a Kubernetes cluster. More details about the EJB Timer variants can be found here.
Conclusion
So we have seen how ManagedScheduledExecutorService
and EJB Timers can be used to implement scheduled tasks in Jakarta EE. In my personal opinion you should use EJB timers if you are running on a Jakarta EE stack. The EJB Timer provides you with more features and is even scalable as the more lightweight ManagedScheduledExecutorService
. This is just my personal opinion. Choose the technology that best fits your app.
Opinions expressed by DZone contributors are their own.
Comments