Anyone developing a J2EE application probably faced the challenge of setting some fixed interval timers that need to be up upon application startup. This, in fact involves two challenges:
First one: J2EE provides no means of startup notification on EJB-Jars.
Second: EJB timers are persistent (they survive server restarts) and if you don’t cancel them upon application shutdown you’ll end up having lots of those timers.
So, wouldn’t it be fine if we had some mechanism of having a notification sent down from AppServer to our application in a timed manner? It’d be even better if we had some mechanism to specify the intervals using Unix Cron format.
Happily there is a simple solution: Quartz Resource Adapter from JBoss licensed as LGPL (as stated on its ra.xml) that makes it safely usable on commercial products. It comes packaged as a rar file on JBoss deploy directory as it seems to be used for JBoss internal purposes but nothing (or almost nothing) prevents you from using it into another AppServer.
By almost nothing I meant that as it is packaged on JBoss there is one quirk:
QuartzResourceAdapter.endpointActivation method does one trick to detect whether the endpoint configured is a stateless or stateful endpoint that renders it unusable on WebSphere for example (WebSphere prevents you from calling MessageEndpointFactory.createEndpoint from the Thread that invoked endpointActivation) and I am sincerely not sure whether this is something the spec enforces. I’ll paste the trick below:
// allocate instance of endpoint to figure out its endpoint interface
Class clazz = QuartzJob.class;
MessageEndpoint tmpMe = endpointFactory.createEndpoint(null);
if (tmpMe instanceof StatefulJob) clazz = StatefulQuartzJob.class;
tmpMe.release();
And the best thing is that this trick can be safely replaced by two markup ActivationSpec classes, so we end up having the following code:
// figure out endpoint interface through activationspec (WAS denies endpoint creation on main thread)
Class clazz = null;
if (spec instanceof QuartzStatelessActivationSpec) {
clazz = QuartzJob.class;
}
else {
clazz = StatefulQuartzJob.class;
}
And the two markup classes:
package org.jboss.resource.adapter.quartz.inflow;
public class QuartzStatefulActivationSpec extends QuartzActivationSpec {
}
package org.jboss.resource.adapter.quartz.inflow;
public class QuartzStatelessActivationSpec extends QuartzActivationSpec {
}
And the ra.xml file for the RAR package gets changed from:
<messagelistener>
<messagelistener-type>org.quartz.Job</messagelistener-type>
<activationspec>
<activationspec-class>org.jboss.resource.adapter.quartz.inflow.QuartzActivationSpec</activationspec-class>
<required-config-property>
<config-property-name>cronTrigger</config-property-name>
</required-config-property>
</activationspec>
</messagelistener>
<messagelistener>
<messagelistener-type>org.quartz.StatefulJob</messagelistener-type>
<activationspec>
<activationspec-class>org.jboss.resource.adapter.quartz.inflow.QuartzActivationSpec</activationspec-class>
<required-config-property>
<config-property-name>cronTrigger</config-property-name>
</required-config-property>
</activationspec>
</messagelistener>
To:
<messagelistener>
<messagelistener-type>org.quartz.Job</messagelistener-type>
<activationspec>
<activationspec-class>org.jboss.resource.adapter.quartz.inflow.QuartzStatelessActivationSpec</activationspec-class>
<required-config-property>
<config-property-name>cronTrigger</config-property-name>
</required-config-property>
</activationspec>
</messagelistener>
<messagelistener>
<messagelistener-type>org.quartz.StatefulJob</messagelistener-type>
<activationspec>
<activationspec-class>org.jboss.resource.adapter.quartz.inflow.QuartzStatefulActivationSpec</activationspec-class>
<required-config-property>
<config-property-name>cronTrigger</config-property-name>
</required-config-property>
</activationspec>
</messagelistener>
Apart from this you’ll have to include jboss-common.jar (found on $JBOSS_HOME\lib) into the quartz-ra.rar file in the same level as quartz-ra.jar and quartz.jar.
Now you are done to install it into your application server and finally create your Activation Specs.
I am providing a PDF with Patched Quartz Resource Adapter for anyone willing to test on your preferred J2EE server and I also posted a message on JBoss AS Development forum to check whether they are interested in incorporating these changes.
Updates: It seems like this is going to get integrated into JBoss AS main code. I’ve submitted the patch as requested.