2

I am using an EJB automatic timer service with @schedule annotation. However I need help with the following.

I need a singleton time service (execution on only one node in a cluster) but don't want to execute missed timers during server restart or crash.

I read many articles but everyone is mentioning about persistent timers to achieve the singleton behavior in a cluster environment.

My code:

@Singleton
@Startup
public class DataService {
     @Schedule(second="*/10", minute="*", hour="*", persistent=false)
     public void xxxFetch() {
         // business logic
     }
}

Is there a way to achieve Singleton service with non-persistent timers?

Sumanth
  • 595
  • 3
  • 14
  • 39

1 Answers1

2

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.

areus
  • 2,880
  • 2
  • 7
  • 17
  • any alternatives like using ManagedScheduledExecutorService? – Sumanth Jan 23 '21 at 16:36
  • with a `ManagedSheduledExecutorService` you can achieve the same behaviour of a Non persistent timer created programatically with `TimerService`. But IMO it offers no advantage, quite the opposite: create a timer is transactional while sheduling a task is not. – areus Jan 26 '21 at 11:28
  • I've added info about a wildfly feature that can serve your needs: HA singleton deployments – areus Jan 26 '21 at 11:38
  • HA singleton deployments is for entire ear/war file. How can we achieve singleton service for a single service within EAR? – Sumanth Jan 27 '21 at 17:56
  • According to the wildfly doc, you can't. "This descriptor may be applied to any deployment type, e.g. JAR, WAR, EAR, etc., with the exception of a subdeployment within an EAR." You need to extract your EJB in a separate JAR, and deploy that JAR as a singleton. – areus Jan 28 '21 at 12:25