Message-driven beans may declare only the NotSupported or Required transaction attribute. The other transaction attributes don't make sense in message-driven beans because they apply to client-initiated transactions.
Lets take Required type. If the client is calling a MDB from a transaction context, then the MDB would also be in the same transaction context. What about the other types? Please explain if I am wrong.
MDB are called asynchronously. The client sends a message to a Queue or Topic and forgets about it. Then, at some moment in time, the message is delivered to the MDB. As far as the MDB is concerned, there is no client (so no transactional and no security context): there's only a message destination from where it reads asynchronous messages.
This is why you can only use REQUIRED or NOT_SUPPORTED. The other transaction attributes only have a meaning when there's the client's transaction context (this includes an unspecified transaction context).
Message-driven beans may declare only the NotSupported or Required transaction attribute. The other transaction attributes don't make sense in message-driven beans because they apply to client-initiated transactions. The Supports, RequiresNew, Mandatory, and Never attributes are all relative to the transaction context of the client. For example, the Mandatory attribute requires the client to have a transaction in progress before calling the enterprise bean. This is meaningless for a message-driven bean, which is decoupled from the client.
The NotSupported transaction attribute indicates that the message will be processed without a transaction. The Required transaction attribute indicates that the message will be processed with a container-initiated transaction.
Can someone put some more light on this topic. Because (probably I'm wrong.., but)..., I think that: Required is also relative to the transaction context of the client (at least as much as RequiredNew). So what's the difference here ?
"Required - If the client is running within a transaction and invokes the enterprise bean's method, the method executes within the client's transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method."
"RequiredNew - If the client is running within a transaction and invokes the enterprise bean's method, the container takes the following steps:
1. Suspends the client's transaction 2. Starts a new transaction 3. Delegates the call to the method 4. Resumes the client's transaction after the method completes
If the client is not associated with a transaction, the container starts a new transaction before running the method. "
So.., for me it's starnge that I can use Required.., but not RequiredNew. [ December 11, 2008: Message edited by: p xgodsa ]
I can't fathom the logic either. I've read the 'self-evident' paragraph in EJB 3 by Burke and Monson-Haefel many times but am none the wiser.
While I understand that the client transaction context cannot be passed to the MDB, that doesn't seem to be sufficient to allow logic to be applied to deduce that NotSupported and Required are the only options.
NotSupported makes sense given that its transaction scope is not propagated to the target EJB, in this case an MDB.
Supports requires the transaction scope, if one exists, to be propagated - so that can be ruled out.
Required doesn't make sense because if a transaction is active the target EJB executes in this scope - and surely this requires that the transaction scope be propagated?
RequiresNew would seem to be a candidate given that it creates a new transaction scoped to the MDB method, irrespective of the state of the client transaction. But this is not a candidate so my logic somewhere is wrong.
Mandatory can be ruled out on tx ctx propagation grounds.
Never - no tx ctx propagation but still need to know if the client is part of a tx to throw an exception - but isn't this done by the container? Even so, ruled out because it would only ever result in an exception being thrown.
So, NotSupported and RequiresNew seem reasonable to me, but that's wrong (unless there's a typo in the book?)
From the perspective of an MDB, it either runs in a transaction or it doesn't.
Given that the MDB cannot have the caller's transaction context passed into it, the former situation implies REQUIRES_NEW and the latter situation implies NOT_SUPPORTED
Well, as we already know what is the difference between a RequiresNew and Required ill try to give an explanation that i think is reasonable enough.
So, our question is that - why are we allowed to use a Required, but not a RequiresNew. Well, to think of it carefully, the problem should boil down as to why the RequiresNew does not makes more sense in the context of an MDB than the Required.
When we specify theh RequiresNew, it comes with an implicit understanding that if the client has a transaction, it needs to be suspended. i.e. the existence of a client is almost always assumed in the case of RequiresNew. Its as if we are saying-- hey client, just take a break, and dont disturb me while i am acting on my world dominance plan. Ill inform you to do your boring stuff when i am done!
Whereas, in the case of Required, all that we are trying to tell the runtime environment is that my MDB should have a transaction associated with it. There is no assumption of the existence of a client. Hence, Required seems like a more direct way of telling the container to start a transaction than RequresNew. Its like there is no boring stuff that needs to be done. I dont have to halt any client from hogging the processor with his boring and mundane tasks!
An MDB is a free bird, and is only restricted to the world in which he lives(which might contain many other MDB's with world dominance plans ;>).
After all, it certainly does not make sense to tell the container to start a new transaction, because that is something that will always happen in the case of an MDB while using Container Managed Transactions. So, allowing both, the RequiresNew and Required seems to be redundant.
Required just feels like a more direct way, even though in the case of an MDB, it does the same thing as RequiresNew. I guess that the spec developers just decided to choose one of Required and RequiresNew, and Required seemed to make more sense to them. Or maybe the container implementors have some optimization tricks up their sleeves in the case of Required thats why the people who made the spec chose Required.
I might be completely wrong. But i hope that i am not. ;>
What other explanations do you people have? I cant think of anything else more reasonable.
That does seem very reasonable, and was a line of argument I was pursuing myself until I read what the Burke/Haefel EJB3 book had to say about NotSupported - the incoming transaction is suspended! So, if it can do that for NotSupported it ought to be able to do that also for RequiresNew. Even worse, for Required, if the client is part of a transaction, the MDB is automatically included in its transaction scope.
Although the MDB is totally decoupled from the message sender, the container presumably has access to the transaction context - and this is where the answer lies I suspect but i haven't managed to find out much about what actually goes on here.
Ryan's right, what it comes down to is implementing the requirements in the most common sense way. Getting the job done with the tools available that is the most suitable fit (not necessarily the most perfect fit!).
REQUIRED is there over REQUIRES_NEW because if an MDB wants to run in a transactional environment, it doesn't have to be so strictly enforced. An MDB will create a transaction if it wants one in the REQUIRED transaction type. Since there is no likelihood of the method being called in an existing transactional context, there's no point having the option there to suspend an existing transaction like in REQUIRES_NEW. As Ryan said it's redundant. So REQUIRED fits the job *good enough* without going overboard.
On the other side of the coin, we use NOT_SUPPORTED in case we want the ability to run the MDB method out of a transactional context. We don't want to use NEVER though because it's really strict (we don't need to throw an EJBException if for some magical reason a transaction exists). NOT_SUPPORTED gives us the functionality we want in the most relaxed, *good enough* way. It's just coincidence that if a transaction exists when called with NOT_SUPPORTED that "the caller's method is suspended".
It seems to me that an MDB either wants to run in a transaction or it doesn't. Given an MDB's disconnect from any existing transactional context, REQUIRED fulfills the former and NOT_SUPPORTED fulfills the latter. That black and white view seems reasonable, but getting to it was obscured by the distracting (and apparently irrelevant) notions of suspending transactions.
Won't you please? Please won't you be my neighbor? - Fred Rogers. Tiny ad:
Free, earth friendly heat - from the CodeRanch trailboss