jsr342-experts@javaee-spec.java.net

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

From: Pete Muir <pmuir_at_bleepbleep.org.uk>
Date: Tue, 12 Mar 2013 19:52:37 +0000

On 12 Mar 2013, at 19:46, Bill Shannon <bill.shannon_at_oracle.com> wrote:

> 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?)

Implicitly I guess the spec allows you to do this, but I don't think it's very clear. I would like to add at least an example to the interceptors spec to show how you do this. Could you outline what you think the interceptor definition will look like in this case?

>
> 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.
>>
>