users@javaee-spec.java.net

[javaee-spec users] Re: [jsr342-experts] EJBs and JTA transactional interceptors

From: Pete Muir <pmuir_at_bleepbleep.org.uk>
Date: Thu, 9 Feb 2012 06:06:40 +0000

Hi Bill,

After some debate, we feel that option (1) is the best option.

We don't like any options that change the way transaction work in EJBs, as this breaks the principle of least surprise, which pretty much rules out (5) and (6).

We also didn't like (3) and (4), again as we feel they will give surprising behaviour for users.
>
e.g. if the user specified @Transactional(NEVER) on an EJB this would always fail, as the EJB's default REQUIRED behaviour would mean that a TX would always be active. Stating that the user should just use @TransactionAttribute(SUPPORTS) to effectively disable CMT is not a good solution, as a user that understands why this is necessary will in all likelihood just use the @TransationAttribute annotations anyway. We haven't gained anything in terms of consistency - yes they can use @Transactional on their EJB but they must add the @TransactionAttribute(SUPPORTS) to their EJBs and not their managed beans. We also increase verbosity - they must add two annotations now.

There is also the potential for a lot of other weird behaviour, even when specifying @TransactionAttribute(SUPPORTS). For consider what happens if a method has @Transaction(REQUIRES_NEW) and an invocation is made on the method that is already associated with an existing transaction. The EJB CMT interceptor will think that the EJB's work is being done in the outer transaction, when in fact it is happening in the inside transaction that was started by the JTA interceptor. If this then throws an exception the outer exception will still be rolled back, even though the EJB did not actually do any work in this transaction.

We also need to consider the transaction behaviour of SFSB's, which basically have a transaction scoped lock that is released on TX commit, calling the SFSB's SessionSynchronization methods. In the case above the SFSB will be doing work in a different transaction to the one it is enlisted in.

This leaves options (1) and (2), and of these, we certainly prefer the fail fast option (1), of the two.

We ran through the scenarios when people use transactions on EJBs, and we feel that a large portion of the time (e.g. 80%) that people simply want their beans to be transactional (which EJBs are by default). This means that they will be using no annotation on their EJBs, and @Transactional on their managed beans. Whilst this *is* inconsistent, it's perhaps not as bad as the option first sounds, as it's not two different annotations needed.

Finally, were a vendor to invent a clever way to handle this, as an optional extension, we could incorporate this into a later rev of Java EE without breaking backwards compatibility, which is always a good thing (don't preclude unknown futures).

HTH

Pete (for JBoss)

On 30 Jan 2012, at 20:40, Bill Shannon wrote:

> We've been trying to figure out how the new JTA transactional interceptor
> support should interact with EJBs. Here's some options we've considered:
>
> 1. The new transaction annotations are not allowed to be used on EJBs.
> This error would be detected at deployment time.
>
> 2. The new transaction annotations have no effect when used on EJBs.
> This would likely be very surprising to users.
>
> 3. The EJB container does not understand the new transaction annotations
> at all and behaves the same with regard to the exceptions that are thrown
> as it would if the application were to throw the same exceptions in
> an EJB that was not annotated with the new transaction annotations.
> The exceptions the EJB container sees at point B above are handled
> the same as they would be if CDI were removed from the picture.
> The EJB container does exception wrapping and transaction rollback
> based only on its existing rules, including use of the existing
> EJB @ApplicationException annotation. At point A the application
> sees exceptions that might be wrapped in the normal EJB way.
>
> Note that the EJB container will be performing its normal CMT
> behavior, including the default transaction attribute of REQUIRES
> and the normal EJB exception wrapping behavior. If the EJB Bean
> wants to use the new JTA transaction annotations it will likely want
> to disable the EJB CMT support by specifying an EJB transaction
> attribute of SUPPORTS (which means the EJB container will never
> start a transaction itself and will pass through any existing
> transaction context).
>
> 4. Like #3, but the EJB container understands both the existing
> EJB @ApplicationException annotation as well as any new such
> annotation defined by JTA. This changes which exceptions will
> be wrapped before returning to the application, and what will
> happen to any transaction that the EJB container might have started.
>
> And like #3, the application will likely want to disable EJB CMT
> by specifying an EJB transaction attribute of SUPPORTS.
>
> 5. Like #4, but the EJB container also detects the use of the new
> JTA transaction annotations and changes the default CMT behavior
> to SUPPORTS.
>
> And like #4, the EJB container still does its normal exception wrapping.
>
> 6. Like #5, but the EJB container also changes the exception wrapping
> rules to match those of a standalone CDI bean using the new JTA
> transaction annotations (i.e., no exception wrapping at all).
>
>
>
> In cases #5 and #6, it's TBD what should happen if the bean uses both
> the EJB transaction annotations and the JTA transaction annotations.
> Given a possible implementation (see appendix), you can predict the
> effect, but it's almost certainly not what the user wants, and so
> likely should be treated as an error, probably detected at deployment
> time.
>
> The current EJB exception wrapping behavior is somewhat arcane. You
> could imagine a new EJB annotation @DontWrapExceptions that would
> disable this behavior. This could be used explicitly in cases
> #3 - #5 (it's implicit in case #6), or in other existing uses of EJB.
>
> Note that remote EJBs would need to continue to follow the existing
> rules for remote exceptions.
>
> Which option above do you prefer?
>
>
>
>
>
> --- Appendix (read only if you're confused)
>
> For the options #3 - #6, it's helpful to think about how
> this might be implemented. For example, consider an
> implementation where the EJB container asks CDI to instantiate
> the class that is the EJB bean. CDI performs injection on
> the bean and returns a wrapper or subclass of the bean that
> handles any interceptors declared for the bean. The EJB
> container then invokes methods on the bean using this object
> reference returned by CDI. The EJB container does no
> interceptor handling of its own. This may or may not be a
> reasonable or correct implementation approach, but for the
> purposes of the following, let's consider it. Here's a picture:
>
> app reference ----> EJB container ----> CDI ----> EJB bean
> A B