[JBAS-1926] - Behavior of EJB Timer Service during exception
npahucki-novell Dec 14, 2005 1:23 PMI am looking at http://jira.jboss.com/jira/browse/JBAS-1926?page=all. I have been able to duplicate the issue described by using the following code in a session bean:
public void ejbTimeout(Timer timer) { System.out.println("*****GOT TIMING EVENT. TIMER=" + timer.toString()); if (!failedAlready) { failedAlready = true; m_sc.setRollbackOnly(); System.out.println("** INDICATING FAILURE..."); } else { try { System.out.print("** DOING TASK."); for(int i = 1; i<=10; i++) { Thread.sleep(1000); System.out.print(" " + i); } System.out.println(); } catch (InterruptedException e) { e.printStackTrace(); //TODO: handle this! } System.out.println("** DONE with timer 'processing'"); } }
The timer is created with:
Timer timer = ts.createTimer(1000,1000,"MyTestTimer");
When this (admittedly contrived) example is run you will see interleaved values for the variable 'i' in the for loop on the console as two threads are executing the ejbTimeout() method at the same time. One is the retry thread, the other is the regular interval timer thread which timedout while the the retry was running. Once the retry thread completes, you see the 'normal' interval timer output repeat immediately after the ejbTimeout() method completes (because the timeout is shorter than the time it takes the task to execute)
The EJB spec does not seem to specifically address this situation, only saying that if the ejbTimeout() transaction fails or is rolledback, that the timeout must be tried again.
From 22.4.2 in EJB 2.1 Spec:
If the Bean Provider invokes the setRollbackOnly method from within the ejbTimeout method, the container must rollback the transaction in which the ejbTimeout method is invoked. This has the effect of rescinding the timer expiration. The container must retry the timeout after the transaction rollback.
The spec does mention that the bean must be prepared for spurious callings of ejbTimeout() after calling cancel on the timer because of potential race conditions. On the other hand, we do prevent the timer from firing again if the time it takes to execute the ejbTimeout() method exceeds the timer's interval.
So, since this is somewhat of a gray area, what are people's feelings on the correct behavior here. Should we prevent the inerval timer from firing while a retry is in progress, or is this something where the bean provider should provide the logic to detect the same task running concurrently in the retry thread?
Thanks in advance for the feedback.