I posted this kind of question several times, but never got precise answers unfortunately. Now this has become a rather urgent problem for me.
I got an MDB consuming messages from a topic.
The MDB consumes the message, does some database reads and writes and then commits.
All of this (consumption of the message, database transactions) is done within one transaction (did I understand transacted MDBs right ?)
1) imagine I call a stateless session bean from the MDB within this transaction. The stateless session bean exposes a method doing some database writes. Will these writes get lost if the transaction of the MDB does not commit ? (I need this for logging and errorhandling)
2) an exception is thrown within the MDB. Is it possible to handle it and to execute some methods when this happens ? I understood that if an exception occurs then a) the beans transaction is completely rolled back, b) the bean dies immediately. Is it possible to enable exception handling within the MDB, via the remove method perhaps ? I would need to have the name of the exception, the cause, and write it down to a database. Is this possible ? How ?
Best regards, Jubin Zawar
I'm not an expert on MDBs but I think you need to read the section in the EJB2.0 spec about Message Driven Beans to clarify some important points:
1. A message driven bean cannot join a transaction from a caller, it always starts its own (when container managed and the onMessage method is demarced as required). Therefore, the commit scope of your session bean will be different to that of the message driven bean.
2. A MDB cannot throw application exceptions to callers.
What I would do (and have done) with a JMS message is set a reply to destination in the message I send to the MDB using Message.setJMSReplyTo. If you need to send state information back to your Session bean your MDB can retrieve the destination using Message.getJMSReplyTo and send state information back. Your session bean can then read from the reply queue and perform the relevant work e.g. call rollback.
It sounds to me like you might want to consider using a stateless session bean instead of a message driven bean if you need this synchronous type behaviour. I think MDBs more suit an asynchronous application.
Hope this helps,
Hello, thanks for your reply.
From what I understood (and specifications are most of the time far from being clear, I m sorry to say this, but maybe I lack intelligence ;)), the following is true :
- a MDB deployed with container managed transaction "Required" will consume the message and execute everything within the onMessage method in one transaction. If any exception occurs, then the complete transactoin is rolled back and the message remains on the topic from which it consumed.
- the MDB must NOT throw application exceptions. Well, so if I need to roll everything that happened since the start of the onMessage method back, I need to use setRollbackOnly(). Am I right ?
I know that transactional context is not passed along. I hope that for the two points above I am right.
If these 2 affirmations are true, then the question is :
- imagine I call a stateless session bean from within the onMessage method, with the transaction attribute set to "Required", which induces the behaviour described above : then : is the work of the stateless session bean rolled back if I roll back the onMessage transaction ? If yes, this is GOOD for me : because I need to log messages, and thats all I call the stateless session bean for.
Ahhh, sorry I thought you were calling the MDB from the session bean when you are infact calling the session bean from the MDB. My mistake!
Sure, the transaction started in the MDB can be propogated to the session bean if the transaction properties for the session bean is demarced as such in the deployment descriptor.
FYI, some people prefer using JMS over EJBs for distributed logging because they get better performance. I'm sure that there are a multitude of issues to address though :) Commonly a problem to consider here is that you need to provide transactional and non transaction interfaces because sometimes you want to log even when the transaction fails (e.g. you want to log a failure) and sometimes you do not (e.g. you are logging an audit trail and if the transaction fails then it would be a mistake to have logged).
Hi Simon again,
a little question remains :
since I do everything in my MDB within a try/catch block, I ask myself :
will that what is specified in the "catch" block be run if an exception occurs ?
having run the commands in the catch block, will the transaction be rolled back in the scenario I described, or will I have to do this manually by setrollbackonly() ?
Hmmm, I would check the spec on this, but from what I understand the following will occur:
1. Rollback in session bean will result in a RemoteException being thrown to MDB.
2. Rollback in session bean will result in rollback of MDB if both share the same global transaction (which depends on the transaction settings for your beans). The question for you is - how is the session bean rolled back. Sometimes you need to specifically do the rollback yourself, othertimes the resource enlisted from your session bean will do the rollback.
Whenever I have questions like these my method is usually:
1. Read the spec
2. Write a little test case to find out if my interpretation of the spec was correct (it has been wrong in the past, especially when it comes to this transaction stuff - its pretty tough!).
BTW, WLS5.1 does not conform to the EJB spec so be careful! (WLS6.0 does).
Actually, now that I think about this more, I seem to remember that rollbacks do not automatically result in exceptions (althought they did in WLS5.1) because we rely on the return from a session bean call to tell clients about problems. So please check this very carefully.
reply to earlier post
When replied to that one, I didnt realise that you had re-posted again.
To answer your question: What happens to your MDB depends entirely on what TYPE of exception is thrown.
Having said that, I think that I may not have completely answered the sticky part of your question regarding the possibility of catching a system exception.