This behaviour is defined on the EJB 3.2 spec (sections 13.2.2, 13.2.3, 13.2.4 and 13.4.4).
There are two types of timers, automatically created timers (with annotations), or programmatically annotated timers (using the TimerService
). Both can be persistent or non persistent.
- Persistent timers (both automatically or programmatically created) will run in only one node.
- Non persistent automatically created timers will run on every node in the cluster.
- Non Persistent programmatically created timers will run only on the node they are created.
So to achieve a singleton service with non persistent timers, you need to set some kind of configuration, or trigger a request on one of the nodes so it programmatically creates the timer.
But be aware that if that node fails, the timer service will not execute.
The same behaviour can be achieved sheduling a task in a ManagedScheduledExecutorService
with the new Concurrency for Java EE
spec. But IMO it offers no advantage to programmatically creating a non persistent timer with the TimerService
. Quite the opposite: creating a timer is transactional operation, while sheduling a task it's not.
There is however a Wildfly functionality that can serve your needs: High Availability Singleton Deployments.
You can define a module as a Singleton Deployment. This module is deployed to a cluster, but it's only active on one node. If that node fails, the module is activated in another node.
So you can put your EJB
with either automatically or programmatically created timers in a singleton module, and you get both execution in one node, and high availability.