I have a method annotated with @Schedule that is called by the container once in a while.
@Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
public void myTimerMethod() throws Exception {
...
}
Problem is on certain conditions i want to this method to throw an exception to cause the ongoing transaction to rollback. But if I do this more than two times the timer will be expunged and not called any more!
INFO: EJB5119:Expunging timer ['68@@1359143163781@@server@@domain1' 'TimedObject = MyBean' 'Application = My-War' 'BEING_DELIVERED' 'PERIODIC' 'Container ID = 89072805830524936' 'Fri Jan 25 21:49:30 CET 2013' '0' '*/5 # * # * # * # * # * # * # null # null # null # true # myTimerMethod # 0' ] after [2] failed deliveries
I know i can configure timer rescheduling in domain.xml using
<domains>
...
<configs>
<config>
...
<ejb-container session-store="${com.sun.aas.instanceRoot}/session-store">
<ejb-timer-service>
<property name="reschedule-failed-timer" value="true"></property>
</ejb-timer-service>
</ejb-container>
...
</config>
</configs>
...
</domains>
But my question is, can I have this setting configured when i deploy my application?
Can't find it in:
glassfish-resources.xml
glassfish-ejb-jar.xml
glassfish-web.xml
Is there some way to do it programmatically maybe?
(My rationale behind behind putting server-configuration like this in config files rather than configuring the server is so my app should be possible to install directly on a fresh installation of glassfish)
I'd use a different approach.
Instead of throwing an exception directly from the scheduled method, try to introduce a level of indirection as in:
...
@Inject RealWorkHere realImplementation;
@Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
public void myTimerMethod(){
try{
realImplementation.myTimerMethodImpl()
}catch (Exception x){
// hopefully log it somewhere
}
}
...
where RealWorkHere
is the bean with the actual implementation as in:
@Stateless
public class RealWorkHere{
@TransactionAttribute(REQUIRES_NEW)
public void myTimerMethod() throws Exception {
}
}
This comes with the benefit of:
The current Glassfish up to version 4 expunges a timer if during the execution of the timeout callback method an application exception occurs.
The application exception causes a rollback of the current transaction. In such a situation Glassfish retries the error free execution of the timeout callback method once again. If a rollback again occurs Glassfish expunges the timer.
I filed an issue in the Glassfish issue tracker not to expunge the timer in case of an excpetion. Glassfish seems to be the only application server who expunges a timer in case of an application exception. See glassfish #20749: Glassfish expunges timer even if callback method keeps its contract for more details. May you would like to vote for my issue.
I also filed an issue on the EJB specification to clarify how the EJB container should behave in such situations. See ejb-spec #111: Please clearify the behaviour of an container if an application exception is thrown during the execution of a timer callback method for more details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With