Reputation: 215
we have multiple instances of JBoss-Server in a clustered environment. For background tasks there is a global queue available, that manages all jobs registered at it. For this queue there is a simple listener (MDB) on each node, manages the incoming messages. This listener does a manual lookup (no injection) for a singleton bean and starts a pre defined method. Everything works fine so far, but the method in the singleton bean uses some other (no singleton services) that are not available under some circumstances. For example if a node will be restarted and there are left messages in the queue (not processed yet) the messages will be picked up by the listener and all further beans are null, so the job produces a NPE. Is it possible to define a delay time in JMS-Listener after messages will be picked up or is it possible to define an "application completely deployed" hook in there? The DependsOn-Annotation does not work, because of the usage of non singletons.
A possibility can be to set the MDB-property "DeliveryActive" to false and start the bean after full deployment. Is there a simple, working way to do this programatically (not in jmx-console)? Any manuals for this I found, redirects me to a manual jndi lookup. I think it have to be possible to inject the Bean per annotation and call startDelivery()? Is there a good place to do this in application?
Another hint takes me to the initialise in order property in application.xml, because the problem might be connected to JBoss Deployment order (some EJBs will be later available than the listener), but there seems to be a bug in JBoss 6.0 and upgrading to 6.1. is not an option. Maybe there is a walkthrough for this?
I hope that the problem is well enough explained, otherwise please ask for further informations.
Thanks in advance, Danny
Additional informations:
The Listener:
@MessageDriven(activationConfig =
{
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "/queue/SchedulerQueue")
})
public class SchedulerQueueListener implements MessageListener {
...
@Override
public void onMessage(Message message) {
...
service = (IScheduledWorkerService) new InitialContext().lookup(jndiName);
EJobResult eJobResult = service.executeJob(message);
...
}
A sample worker:
@Singleton
@LocalBinding(jndiBinding = SampleJobWorkerService.JNDI_NAME)
public class SampleJobWorkerService implements IScheduledWorkerService {
...
@EJB(name = "SampleEJB/local")
private ISampleEJB sampleEjb;
...
@Override
public EJobResult executeJob(Message message) {
int state = sampleEjb.doSomething(message.getLongProperty(A_PROPERTY));
}
In this case the sampleEjb - member will be null sometimes
Upvotes: 3
Views: 3627
Reputation: 10361
I am in the same trouble at the moment.
I propose you use EJB 3 startup bean annotation @Startup
on your singleton bean to invoke the startDelivery
method on your Message listeners.
Upvotes: 0
Reputation: 11602
As a workaround, instead of calling EJB's directly from MDB, you can create a timer with a timeout with some delay. Therefore there will be some delay in execution.
In Timer's timeout method, then you can call singleton EJB, which in case will call other non-singleton EJB's.
JBoss specific : Can try setting the property in the message object before sending.
msg.setLongProperty("JMS_JBOSS_SCHEDULED_DELIVERY", (current + delay));
Other alternative is _JBM_SCHED_DELIVERY
.
Edit :
For 1st part, you can have JTA transaction, which may span across JMS & EJB. Therefore failover & other things may be handled accordingly.
You can also increase the redelivery delay for the message object.
<address-setting match="jms.queue.someQueue">
<redelivery-delay>5000</redelivery-delay>
</address-setting>
Upvotes: 1