Timer is creating multiple timer instances
Asked Answered
S

1

7

This a real simple issue I guess but I am not able to figure why it happens so though. I have an implementation of an EJB timer which uses @Singleton annotation i.e. a singleton timer.

I have set it to run after every 5 mins. The code looks something like this :

@Singleton
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class Scheduler {
    private static final double timerVar = Math.random() * 33;

    static Logger logger = Logger.getLogger("Scheduler");

    @Schedule(second = "*", minute = "*/5", hour = "*", persistent = true)
    public void doWork() {
        logger.log(Level.INFO, "timer value for this session : " + timerVar);
    } 
}

When the process runs it executed 10 scheduler instances simultaneously in a gap of 1 sec i.e.

(EJB default - 1)
(EJB default - 2)
(EJB default - 3)
(EJB default - 4)

and so on. When I put a lengthy operation within the code, the (EJB default - 1) is not complete and when (EJB default - 2) tries to execute it gives me an error saying:

JBAS014373: EJB 3.1 PFD2 4.8.5.5.1 concurrent access timeout on org.jboss.invocation.InterceptorContext$Invocation@1b83ad52 - could not obtain lock within 5000 MILLISECONDS

First, how can I avoid multiple EJB scheduler instances to be executed at a time? Second, what is the deal with "could not obtain lock within 5000MILLISECONDS" and how can I avoid it?

For the timeout error I get, I found there are a lot of tickets in JBOSS queue as mentioned here.


EDIT

Added the code in the latest comment so it's readable:

@Tushar-46835, could you expound upon your solution, maybe show us the snippet of what you did? – rtcarlson Oct 2 '14 at 20:12

@rtcarlson : Here is the code snippet which fixed my issues:

 @Resource 
 TimerService timerService; 

 @Schedule(persistent = false, minute = "/30", hour = "") 
 public void checkQueueState() { 
     dt    = new DataAccessFactory(); 
     excvo = dt.canExecute(); 
     dt    = null; 
     available = excvo.isExecuteReady(); 
     if (available) { 
         timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false)); 
     } 
 } 

 @Timeout 
 private void generateReport(Timer timer) {
     logger.info("!!--timeout invoked here " + new Date()); 
 }
Shipboard answered 20/2, 2014 at 1:16 Comment(0)
L
6

First, how can I avoid multiple EJB scheduler instances to be executed at a time?

You are creating persistent timers. So after specified interval, it will be creating new ones & enqueueing them, waiting for the previous one to finish its execution.

I presume, after you restart, all enqueued timers have timed-out & multiple instances will be created by the server as they are persistent.

Second, what is the deal with "could not obtain lock within 5000MILLISECONDS" and how can I avoid it?

It's singleton, all method have lock-type write by default, so only one thread will be executiing at a time. Therefore others will get timeout exception/ could not obtain lock etc. as you said, there is a long running process.

Longeron answered 20/2, 2014 at 6:45 Comment(2)
@Tushar-46835, could you expound upon your solution, maybe show us the snippet of what you did?Aubervilliers
@Aubervilliers : Here is the code snippet which fixed my issues: Resource TimerService timerService; Schedule(persistent = false, minute = "/30", hour = "") public void checkQueueState() { dt = new DataAccessFactory(); excvo = dt.canExecute(); dt = null; available = excvo.isExecuteReady(); if (available) { timerService.createSingleActionTimer(new Date(), new TimerConfig( null, false)); } } Timeout private void generateReport(Timer timer) { logger.info("!!--timeout invoked here " + new Date()); }Shipboard

© 2022 - 2024 — McMap. All rights reserved.