users@javaee-spec.java.net

[javaee-spec users] [jsr342-experts] Re: transactional interceptors and lifecycle methods

From: Bill Shannon <bill.shannon_at_oracle.com>
Date: Tue, 12 Mar 2013 12:46:43 -0700

As I understand it, interceptor bindings don't depend on whether the
interceptor is intercepting regular methods with @AroundInvoke or
is intercepting lifecycle methods with @PostConstruct/_at_PreDestroy.
(Maybe it's an error to bind an interceptor to a postConstruct
method if it doesn't include a @PostConstruct interceptor?
Similarly @AroundInvoke?)

The @Transactional interceptor will be implemented to intercept
whichever methods it needs to intercept based on what we decide here.

Pete Muir wrote on 03/12/13 02:00:
> Note that it is NOT normal to be able to bind an around-invoke interceptor to a lifecycle callback on a target class. This would be non-standard functionality for the @Transactional interceptor.
>
> On 11 Mar 2013, at 17:35, Bill Shannon <bill.shannon_at_oracle.com> wrote:
>
>> We recently discovered an issue with the interaction between the
>> new @Transactional interceptors and the @PostConstruct method.
>> Should @PostContruct (and @PreDestroy) methods be transactional,
>> and if so how should the transaction type be controlled?
>>
>> We'd like your feedback on this issue before Friday, March 15.
>>
>> We've come up with four options for how this could work:
>>
>> 1. @PostConstruct is not transactional by default, but @Transactional
>> is allowed.
>>
>> @Transactional(MANDATORY)
>> public class MyBean {
>> @PostConstruct
>> public void postConstruct() {
>> // run with no transaction
>> }
>>
>> public void myMethod() {
>> // uses @Transactional(MANDATORY)
>> }
>> }
>>
>> @Transactional(MANDATORY)
>> public class MyOtherBean {
>> @PostConstruct
>> @Transactional(REQUIRES_NEW)
>> public void postConstruct() {
>> // run with a new transaction
>> }
>>
>> public void myMethod() {
>> // uses @Transactional(MANDATORY)
>> }
>> }
>>
>> 2. @PostConstruct is like any other method and inherits the class-level
>> transaction attribute, but the developer must override the class-level
>> attribute in some cases.
>>
>> @Transactional(MANDATORY)
>> public class MyBean {
>> @PostConstruct
>> public void postConstruct() {
>> // FAILS because there can be no existing transaction context
>> }
>>
>> public void myMethod() {
>> // uses @Transactional(MANDATORY)
>> }
>> }
>>
>> @Transactional(MANDATORY)
>> public class MyOtherBean {
>> @PostConstruct
>> @Transactional(REQUIRES_NEW)
>> public void postConstruct() {
>> // run with a new transaction
>> }
>>
>> public void myMethod() {
>> // uses @Transactional(MANDATORY)
>> }
>> }
>>
>> 3. @PostConstruct is like any other method and inherits the class-level
>> transaction attribute, but methods (like lifecycle callbacks) for
>> which there can be no preexisting transaction context are handled as
>> if they were REQUIRES_NEW when the MANDATORY attribute is specified
>> (i.e., the attribute value handling here is special-cased).
>>
>> @Transactional(MANDATORY)
>> public class MyBean {
>> @PostConstruct
>> public void postConstruct() {
>> // runs with a new transaction
>> }
>>
>> public void myMethod() {
>> // uses @Transactional(MANDATORY)
>> }
>> }
>>
>> @Transactional(MANDATORY)
>> public class MyOtherBean {
>> @PostConstruct
>> @Transactional(REQUIRES_NEW)
>> public void postConstruct() {
>> // run with a new transaction, same as above
>> }
>>
>> public void myMethod() {
>> // uses @Transactional(MANDATORY)
>> }
>> }
>>
>> 4. @PostConstruct can never be transactional. UserTransaction can be
>> used explicitly in the @PostConstruct method if needed.
>>
>> @Transactional(MANDATORY)
>> public class MyBean {
>> @PostConstruct
>> public void postConstruct() {
>> // runs with no transaction context
>> }
>>
>> public void myMethod() {
>> // uses @Transactional(MANDATORY)
>> }
>> }
>>
>> @Transactional(MANDATORY)
>> public class MyOtherBean {
>> @PostConstruct
>> @Transactional(REQUIRES_NEW)
>> public void postConstruct() {
>> // @Transactional is either ignored or causes runtime failure
>> }
>>
>> public void myMethod() {
>> // uses @Transactional(MANDATORY)
>> }
>> }
>>
>>
>> #1 is most similar to stateful session beans in the current version of
>> the EJB spec. When the ability to have transactional @PostConstruct
>> methods on stateful session beans was added to the EJB spec, it
>> couldn't be done by default due to compatibility.
>>
>> #3 is consistent with Singletons in the current version of the EJB spec.
>>
>> #4 is most similar to previous versions of the EJB spec.
>>
>> We're currently leaning towards #3, since it seems consistent with other
>> interceptor use, but good arguments can be made for any of these choices.
>> We really need your feedback.
>>
>> Let us know which choice you prefer before Friday, March 15.
>>
>> Thanks.
>