jta-spec
  1. jta-spec
  2. JTA_SPEC-7

TransactionScoped annotation for CDI bean scope/lifecycle

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Labels:
      None

      Description

      As taken from http://issues.jboss.org/browse/CDI-121 :

      Add TransctionalScoped as a standard scope to define beans whose lifecycle is the same as a given transaction.
      This scope should start automatically when a transaction starts (but lazily when actually needed).

      More details forthcoming in the next couple days...

        Issue Links

          Activity

          Hide
          paul_parkinson added a comment -

          Below is the latest draft of the javadoc for the TransactionScoped annotation that will be added in JTA 1.2 for JavaEE 7. The spec will be updated to cover this annotation as well.
          There are currently two open issues:

          1. Do we want to keep the scope open until after Synchronization.afterCompletion completes? There is no transaction available in afterCompletion, but developers may need to do tidy-up on the TransactionScoped beans that will no longer be available. If users include a @PreDestroy method to do cleanup after the transaction has completed the spec needs to be clear that the transaction has completed when the @PreDestroy method is called.

          2. Is the transaction scope itself volatile and not recoverable? It would seem so. Do we make the chosen behaviour explicit in the spec?

          package javax.transaction;

          import java.lang.annotation.ElementType;
          import java.lang.annotation.Retention;
          import java.lang.annotation.Target;

          import javax.enterprise.context.NormalScope;

          /**

          • Annotation used to indicate a bean is to be scoped to the current active
          • JTA transaction.
            *
          • The transaction scope is active when the return from a call to
          • UserTransaction.getStatus or TransactionManager.getStatus is one of the
          • following states:
          • Status.STATUS_ACTIVE
          • Status.STATUS_MARKED_ROLLBACK
          • Status.STATUS_PREPARED,
          • Status.STATUS_UNKNOWN,
          • Status.STATUS_PREPARING,
          • Status.STATUS_COMMITTING,
          • Status.STATUS_ROLLING_BACK
            *
          • The transaction context is destroyed after any
          • Synchronization.beforeCompletion methods are called and
          • after completion calls have been made on enlisted resources.
          • Synchronization.afterCompletion calls may occur before the transaction
          • context is destroyed, however, there is no guarantee. [this is an open issue]
            *
          • A javax.enterprise.context.ContextNotActiveException will be thrown if an
          • object with this annotation is used when the transaction context is not
          • active.
          • The object with this annotation is associated with the JTA transaction where
          • it is first used and this association is retained through any transaction
          • suspend or resume calls as well as any beforeCompletion Synchronization
          • calls until the transaction is completed.
          • The way in which the JTA transaction is begun and completed
          • (eg BMT, CMT, etc.) is of no consequence.
          • The contextual references used across different JTA transactions are
          • distinct.
            */
            @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
            @Target( {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}

            )
            @NormalScope(passivating=true)
            public @interface TransactionScoped {
            }

          Show
          paul_parkinson added a comment - Below is the latest draft of the javadoc for the TransactionScoped annotation that will be added in JTA 1.2 for JavaEE 7. The spec will be updated to cover this annotation as well. There are currently two open issues: 1. Do we want to keep the scope open until after Synchronization.afterCompletion completes? There is no transaction available in afterCompletion, but developers may need to do tidy-up on the TransactionScoped beans that will no longer be available. If users include a @PreDestroy method to do cleanup after the transaction has completed the spec needs to be clear that the transaction has completed when the @PreDestroy method is called. 2. Is the transaction scope itself volatile and not recoverable? It would seem so. Do we make the chosen behaviour explicit in the spec? package javax.transaction; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import javax.enterprise.context.NormalScope; /** Annotation used to indicate a bean is to be scoped to the current active JTA transaction. * The transaction scope is active when the return from a call to UserTransaction.getStatus or TransactionManager.getStatus is one of the following states: Status.STATUS_ACTIVE Status.STATUS_MARKED_ROLLBACK Status.STATUS_PREPARED, Status.STATUS_UNKNOWN, Status.STATUS_PREPARING, Status.STATUS_COMMITTING, Status.STATUS_ROLLING_BACK * The transaction context is destroyed after any Synchronization.beforeCompletion methods are called and after completion calls have been made on enlisted resources. Synchronization.afterCompletion calls may occur before the transaction context is destroyed, however, there is no guarantee. [this is an open issue] * A javax.enterprise.context.ContextNotActiveException will be thrown if an object with this annotation is used when the transaction context is not active. The object with this annotation is associated with the JTA transaction where it is first used and this association is retained through any transaction suspend or resume calls as well as any beforeCompletion Synchronization calls until the transaction is completed. The way in which the JTA transaction is begun and completed (eg BMT, CMT, etc.) is of no consequence. The contextual references used across different JTA transactions are distinct. */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target( {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD} ) @NormalScope(passivating=true) public @interface TransactionScoped { }
          Hide
          paul_parkinson added a comment -

          Hi,

          Below is a rough first run of JTA 1.2 section 3.8 TransactionScoped Annotation, http://java.net/jira/browse/JTA_SPEC-7 .

          These two issues remain open:

          1. Do we want to keep the scope open until after Synchronization.afterCompletion completes? There is no transaction available in afterCompletion, but developers may need to do tidy-up on the TransactionScoped beans that will no longer be available. If users include a @PreDestroy method to do cleanup after the transaction has completed the spec needs to be clear that the transaction has completed when the @PreDestroy method is called.

          2. Is the transaction scope itself volatile and not recoverable? It would seem so. Do we make the chosen behaviour explicit in the spec?

          Thank you for any feedback on these open issues as well as any feedback on the spec draft in general (eg suggestions as far as the example presented) as we need to close this down in the next couple weeks.

          Thanks,
          Paul

          3.8 TransactionScoped Annotation

          The javax.transaction.TransactionScoped annotation provides the ability to specify a standard scope to define beans whose lifecycle are scoped to the currently active JTA transaction.

          The transaction scope is active when the return from a call to UserTransaction.getStatus or TransactionManager.getStatus is one of the following states:
          Status.STATUS_ACTIVE
          Status.STATUS_MARKED_ROLLBACK
          Status.STATUS_PREPARED
          Status.STATUS_UNKNOWN
          Status.STATUS_PREPARING
          Status.STATUS_COMMITTING
          Status.STATUS_ROLLING_BACK

          The transaction context is destroyed after any Synchronization.beforeCompletion methods are called and afterCompletion calls have been made on enlisted resources. Synchronization.afterCompletion calls may occur before the transaction context is destroyed, however, there is no guarantee.

          A javax.enterprise.context.ContextNotActiveException will be thrown if an object with this annotation is used when the transaction context is not active. The object with this annotation is associated with the JTA transaction where it is first used and this association is retained through any transaction suspend or resume calls as well as any beforeCompletion Synchronization calls until the transaction is completed. The way in which the JTA transaction is begun and completed (eg BMT, CMT, etc.) is of no consequence. The contextual references used across different JTA transactions are distinct. The following example test cases illustrate the expected behavior:

          TransactionScoped annotated CDI managed bean:

          @TransactionScoped

          public class TestCDITransactionScopeBean {

          public void test()

          { //... }

          }

          Test Class:

          UserTransaction userTransaction;

          TransactionManager transactionManager;

          @Inject

          TestCIDTransactionScopeBean TestCIDTransactionScopeBean;

          public void testTxAssociationChange() throws Exception {

          userTransaction.begin(); //tx1 begun

          testTxAssociationChangeBean.test(); //testTxAssociationChangeBean instance has tx1 association

          Transaction transaction = transactionManager.suspend(); //tx1 suspended

          //assert testTxAssociationChangeBean still associated with tx1 and that no transaction scope is active.

          userTransaction.begin(); //tx2 begun

          testTxAssociationChangeBean.test(); //assert new testTxAssociationChangeBean instance has tx2 association

          userTransaction.commit(); //tx2 committed, assert no transaction scope is active

          transactionManager.resume(tx); //tx1 resumed

          testTxAssociationChangeBean.test();

          //assert testTxAssociationChangeBean is original tx1 instance and not still referencing committed/tx2 tx

          userTransaction.commit(); //tx1 commit, assert no transaction scope is active

          try

          { testTxAssociationChangeBean.test(); fail(“should have thrown ContextNotActiveException”); }

          catch (ContextNotActiveException ContextNotActiveException)

          { // do nothing intentionally }

          }

          “Java Transaction API Reference” on page 30 has a full description of this annotation

          [...]

          /**

          • Annotation used to indicate a bean is to be scoped to the currently active
          • JTA transaction.
            *
          • The transaction scope is active when the return from a call to
          • <code>UserTransaction.getStatus</code> or
          • <code>TransactionManager.getStatus</code>
          • is one of the following states:
          • <li>Status.STATUS_ACTIVE</li>
          • <li>Status.STATUS_MARKED_ROLLBACK</li>
          • <li>Status.STATUS_PREPARED</li>
          • <li>Status.STATUS_UNKNOWN</li>
          • <li>Status.STATUS_PREPARING</li>
          • <li>Status.STATUS_COMMITTING</li>
          • <li>Status.STATUS_ROLLING_BACK</li>
            *
          • The transaction context is destroyed after any
          • <code>Synchronization.beforeCompletion</code> methods are called and
          • afterCompletion calls have been made on enlisted resources.
          • <code>Synchronization.afterCompletion</code> calls may occur before
          • the transaction context is destroyed, however, there is no guarantee.
            *
          • A <code>javax.enterprise.context.ContextNotActiveException</code>
          • will be thrown if an object with this annotation is used when the
          • transaction context is not active.
          • The object with this annotation is associated with the JTA transaction where
          • it is first used and this association is retained through any transaction
          • suspend or resume calls as well as any beforeCompletion Synchronization
          • calls until the transaction is completed.
          • The way in which the JTA transaction is begun and completed
          • (eg BMT, CMT, etc.) is of no consequence.
          • The contextual references used across different JTA transactions are
          • distinct.
            *
          • @since JTA1.2
            */
            @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
            @Target( {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}

            )
            @NormalScope(passivating=true)
            public @interface TransactionScoped {
            }

          Show
          paul_parkinson added a comment - Hi, Below is a rough first run of JTA 1.2 section 3.8 TransactionScoped Annotation, http://java.net/jira/browse/JTA_SPEC-7 . These two issues remain open: 1. Do we want to keep the scope open until after Synchronization.afterCompletion completes? There is no transaction available in afterCompletion, but developers may need to do tidy-up on the TransactionScoped beans that will no longer be available. If users include a @PreDestroy method to do cleanup after the transaction has completed the spec needs to be clear that the transaction has completed when the @PreDestroy method is called. 2. Is the transaction scope itself volatile and not recoverable? It would seem so. Do we make the chosen behaviour explicit in the spec? Thank you for any feedback on these open issues as well as any feedback on the spec draft in general (eg suggestions as far as the example presented) as we need to close this down in the next couple weeks. Thanks, Paul 3.8 TransactionScoped Annotation The javax.transaction.TransactionScoped annotation provides the ability to specify a standard scope to define beans whose lifecycle are scoped to the currently active JTA transaction. The transaction scope is active when the return from a call to UserTransaction.getStatus or TransactionManager.getStatus is one of the following states: Status.STATUS_ACTIVE Status.STATUS_MARKED_ROLLBACK Status.STATUS_PREPARED Status.STATUS_UNKNOWN Status.STATUS_PREPARING Status.STATUS_COMMITTING Status.STATUS_ROLLING_BACK The transaction context is destroyed after any Synchronization.beforeCompletion methods are called and afterCompletion calls have been made on enlisted resources. Synchronization.afterCompletion calls may occur before the transaction context is destroyed, however, there is no guarantee. A javax.enterprise.context.ContextNotActiveException will be thrown if an object with this annotation is used when the transaction context is not active. The object with this annotation is associated with the JTA transaction where it is first used and this association is retained through any transaction suspend or resume calls as well as any beforeCompletion Synchronization calls until the transaction is completed. The way in which the JTA transaction is begun and completed (eg BMT, CMT, etc.) is of no consequence. The contextual references used across different JTA transactions are distinct. The following example test cases illustrate the expected behavior: TransactionScoped annotated CDI managed bean: @TransactionScoped public class TestCDITransactionScopeBean { public void test() { //... } } Test Class: UserTransaction userTransaction; TransactionManager transactionManager; @Inject TestCIDTransactionScopeBean TestCIDTransactionScopeBean; public void testTxAssociationChange() throws Exception { userTransaction.begin(); //tx1 begun testTxAssociationChangeBean.test(); //testTxAssociationChangeBean instance has tx1 association Transaction transaction = transactionManager.suspend(); //tx1 suspended //assert testTxAssociationChangeBean still associated with tx1 and that no transaction scope is active. userTransaction.begin(); //tx2 begun testTxAssociationChangeBean.test(); //assert new testTxAssociationChangeBean instance has tx2 association userTransaction.commit(); //tx2 committed, assert no transaction scope is active transactionManager.resume(tx); //tx1 resumed testTxAssociationChangeBean.test(); //assert testTxAssociationChangeBean is original tx1 instance and not still referencing committed/tx2 tx userTransaction.commit(); //tx1 commit, assert no transaction scope is active try { testTxAssociationChangeBean.test(); fail(“should have thrown ContextNotActiveException”); } catch (ContextNotActiveException ContextNotActiveException) { // do nothing intentionally } } “Java Transaction API Reference” on page 30 has a full description of this annotation [...] /** Annotation used to indicate a bean is to be scoped to the currently active JTA transaction. * The transaction scope is active when the return from a call to <code>UserTransaction.getStatus</code> or <code>TransactionManager.getStatus</code> is one of the following states: <li>Status.STATUS_ACTIVE</li> <li>Status.STATUS_MARKED_ROLLBACK</li> <li>Status.STATUS_PREPARED</li> <li>Status.STATUS_UNKNOWN</li> <li>Status.STATUS_PREPARING</li> <li>Status.STATUS_COMMITTING</li> <li>Status.STATUS_ROLLING_BACK</li> * The transaction context is destroyed after any <code>Synchronization.beforeCompletion</code> methods are called and afterCompletion calls have been made on enlisted resources. <code>Synchronization.afterCompletion</code> calls may occur before the transaction context is destroyed, however, there is no guarantee. * A <code>javax.enterprise.context.ContextNotActiveException</code> will be thrown if an object with this annotation is used when the transaction context is not active. The object with this annotation is associated with the JTA transaction where it is first used and this association is retained through any transaction suspend or resume calls as well as any beforeCompletion Synchronization calls until the transaction is completed. The way in which the JTA transaction is begun and completed (eg BMT, CMT, etc.) is of no consequence. The contextual references used across different JTA transactions are distinct. * @since JTA1.2 */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target( {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD} ) @NormalScope(passivating=true) public @interface TransactionScoped { }
          Hide
          marina vatkina added a comment -

          Paul,

          PreDestroy in Singletons most probably and in SFSBs may, run in their own transaction.

          Show
          marina vatkina added a comment - Paul, PreDestroy in Singletons most probably and in SFSBs may, run in their own transaction.
          Hide
          irobins added a comment -

          Two comments:

          1) The pseudo code should say:
          @Inject
          TestCDITransactionScopeBean testTxAssociationChangeBean;

          2) Given the statement:
          "A <code>javax.enterprise.context.ContextNotActiveException</code>
          will be thrown if an object with this annotation is used when the
          transaction context is not active."

          it would be useful to expand the example to illustrate how to perform the assert in:
          Transaction transaction = transactionManager.suspend(); //tx1 suspended
          //assert testTxAssociationChangeBean still associated with tx1 and that no transaction scope is active.

          Show
          irobins added a comment - Two comments: 1) The pseudo code should say: @Inject TestCDITransactionScopeBean testTxAssociationChangeBean; 2) Given the statement: "A <code>javax.enterprise.context.ContextNotActiveException</code> will be thrown if an object with this annotation is used when the transaction context is not active." it would be useful to expand the example to illustrate how to perform the assert in: Transaction transaction = transactionManager.suspend(); //tx1 suspended //assert testTxAssociationChangeBean still associated with tx1 and that no transaction scope is active.
          Hide
          paul_parkinson added a comment -

          speced in JTA 1.2 and implemented in RI

          Show
          paul_parkinson added a comment - speced in JTA 1.2 and implemented in RI

            People

            • Assignee:
              Unassigned
              Reporter:
              paul_parkinson
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: