I have implemented a messagedriven bean with "state" information. State is stored in database. The bean listens to a topic with a message selector.
When created, the bean locks its state information in the database for reading and writing. If it finds its state information locked, then it "knows" that another instance of it is already there, and operating. If this is the case, the bean shall die.
When capturing the message in its "onMessage" method, it performs some actions :
it posts some messages.
it updates some informations in databases.
When it dies, it releases to locks to its state information, so that other instances can be created and lock the state information in the database. Nothing else happens in ejbRemove().
My problem :
I want all of this to occur atomarily.
Meaning : if only ONE exception occurs while creating, or processing the message:
1) none of the message postings occur
2) none of the database updates in the onmessage method occur.
3) IMPORTANT : the message "retrieved" from the topic REMAINS THERE SO THAT ANOTHER INSTANCE OF THIS BEAN CAN RETRY TO PROCESS IT LATER !!!!
4) the locks placed on state information in the database are released.
How do I do this best ?
Best regards, Jubin Zawar
Do EVERYTHING in onMessage, do not split it across the ejbCreate/onMessage/ejbRemove methods.
This is the only way to make this occur atomically.
If you also want your ejb(db) updates to be coordinated with the jms message removal, then you must use an XA enabled JMS provider, that can co-exist with your application server (for example Websphere and IBM MQ/JMS can coordinate and participate in XA distributed transactions).
I m glad about your response.
Well I managed to place everything in the onMessage method now :
"CustomerMDB" listens on topic "Market" for messages containing "Customer" in the message-property "Receiver-Classes".
onMessage() now does the following :
- reads message-property "Customer-ID" to know which customer the CustomerMDB represents.
- reads from table "customer-offices" : if the appropriate record is showing "instance activated", then it must die and the message must remain in the topic for consumption !
- updates table "customer-offices" with "instance activated"
- does some message postings to the topic.
- does some other database reads and updates
- updates appropriate record in table "customer-offices" with "no instance activated".
Well, from what I understood from your reply :
An exception is thrown :
1) updates to databases will NOT be rolled back if an exception occurs within this ?!
2) consumption of the message will be "rolled back", so that another instance may consume this message later.
3) message postings done within onMessage will also be rolled back.
Am I right here ? The problem is : we cant afford commercial products to support this. I hoped this was supported by standard EJB2.0 Servers and JMSServices. We will be using JBoss for this project at first.
4) what happens if the MDB issues a message to the topic it had consumed from ? will this be rolled back ? will this be possible at all ?
5) what happens if the MDB issues a message to the topic it had consumed from, and this message may be a message to itself. Does this open up any conflicts ?
Best regards, Jubin