Given:
- A JMS message queue.
- A timer service which puts messages to that queue periodically (from a database).
- A JEE6 message-driven bean which reads from the queue.
- The timer service and the message-driven bean are part of different deployment units.
Problem:
The message-driven bean cannot be undeployed, without breaking the workflow state, as long as messages are work in process. Because of that, we stop the timer service first and wait until all messages are finished.
Is there a way to automate that behavior? Or is it possible to prevent undeployment if the timer service is still running? We are currently using JBoss 4.2.3.
Non-Solutions:
- Refactoring the deployment units, because it would involve several departments.
- I know that a system crash won't be covered and that a bulletproof solution should include a recovery strategy.
Each deployed MDB has a JMX management interface MBean. The ObjectName of this MBean varies according to deployment (and might also be different between versions of JBoss). I am using JBoss 4.3 and the ObjectName format is:
If your timer service is a JBoss ServiceMBean, you can make your MDB depend on the timer by using the JBoss @Depends("the timer service ObjectName") annotation. This will force the timer service to start before the MDB starts (so preferably, make the timer service have some post start delay) but more importantly, I believe the reverse will occur on undeploy and the timer service should stop first, then the MDB.
If that works, it takes care of ordering, but I don't think you can force the MDB not undeploy while the timer is running. The details of your application might not support this, but one way you might consider resolving this issue is to use the JBoss Quartz JCA Inflow Adapter which will essentially bind the timer and message processor into one (it's like an MDB, but it receives timer events rather than messages), ridding you of having to wrestle with dependencies between two components.
================================ Attempt #2 ================================
Ok, so you want to prevent the MDB from stopping while the feeding queue has a depth of more than zero. This approach should work for you, although it is highly specific to JBoss.
The bottom line is that while your attribute change listener is being called, message will continue to be processed. When the attribute change listener returns, the MDB stop will continue.
If your JMS implementation is the local in-VM JBoss Messaging, the queue message count will be available in the queue's management MBean. For any other setup, you may need to make a proprietary JMS API call to get the queue's message count, or, using a more brute force approach, you can simply request a JMS QueueBrowser and count the number of messages.