[ 
https://issues.apache.org/jira/browse/TOMEE-4727?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Markus Jung updated TOMEE-4727:
-------------------------------
    Description: 
{{RepositoryInvocationHandler.executeInTransaction}} only starts its own 
transaction when {{TransactionManager.getStatus()}} returns 
{{STATUS_NO_TRANSACTION}}, and joins the thread's transaction in every other 
state.

A CDI {{@Observes(during = TransactionPhase.AFTER_SUCCESS)}} observer runs in 
the transaction's {{afterCompletion}} callback, where the committed transaction 
is still bound to the thread with status {{STATUS_COMMITTED}}. A repository 
call from such an observer joins the finished transaction and fails:

{code}jakarta.data.exceptions.DataException: Transaction 
org.apache.geronimo.transaction.manager.TransactionImpl@3d803bed is not active
        at 
org.apache.webbeans.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:377)
        at 
org.apache.webbeans.ee.event.TransactionalEventNotifier$AfterCompletionSuccess.afterCompletion(TransactionalEventNotifier.java:208)
        at 
org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:335)
        ...
{code}

[Jakarta Data 1.0, section 7.3 "Jakarta 
Transactions"|https://jakarta.ee/specifications/data/1.0/jakarta-data-1.0#_jakarta_transactions]
 requires a repository operation to join the global transaction only when

bq. a global transaction is active on the thread of execution in which a 
repository operation is called

[CDI 4.1, section 9.5.3 "Observer method invocation 
context"|https://jakarta.ee/specifications/cdi/4.1/jakarta-cdi-spec-4.1#observer_method_invocation_context]
 allows such observers and leaves their transaction context open:

bq. if the observer method is any other kind of transactional observer method, 
it is called in an unspecified transaction context, but with the same lifecycle 
contexts as the transaction that just completed.

Fix: join only a {{STATUS_ACTIVE}} or {{STATUS_MARKED_ROLLBACK}} transaction; 
in any other state suspend the bound transaction, run the operation in a new 
one, and resume the bound transaction afterwards.

  was:
{{RepositoryInvocationHandler.executeInTransaction}} only starts its own 
transaction when {{TransactionManager.getStatus()}} returns 
{{STATUS_NO_TRANSACTION}}, and joins the thread's transaction in every other 
state.

A CDI {{@Observes(during = TransactionPhase.AFTER_SUCCESS)}} observer runs in 
the transaction's {{afterCompletion}} callback, where the committed transaction 
is still bound to the thread with status {{STATUS_COMMITTED}}. A repository 
call from such an observer joins the finished transaction and fails:

{code}jakarta.data.exceptions.DataException: Transaction 
org.apache.geronimo.transaction.manager.TransactionImpl@3d803bed is not active
        at 
org.apache.webbeans.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:377)
        at 
org.apache.webbeans.ee.event.TransactionalEventNotifier$AfterCompletionSuccess.afterCompletion(TransactionalEventNotifier.java:208)
        at 
org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:335)
        ...
{code}

Jakarta Data 1.0, section 7.3 "Jakarta Transactions" 
(https://jakarta.ee/specifications/data/1.0/jakarta-data-1.0#_jakarta\_transactions),
 requires a repository operation to join the global transaction only when

bq. a global transaction is active on the thread of execution in which a 
repository operation is called

CDI 4.1, section 9.5.3 "Observer method invocation context" 
(https://jakarta.ee/specifications/cdi/4.1/jakarta-cdi-spec-4.1#observer\_method\_invocation\_context),
 allows such observers and leaves their transaction context open:

bq. if the observer method is any other kind of transactional observer method, 
it is called in an unspecified transaction context, but with the same lifecycle 
contexts as the transaction that just completed.

Fix: join only a {{STATUS_ACTIVE}} or {{STATUS_MARKED_ROLLBACK}} transaction; 
in any other state suspend the bound transaction, run the operation in a new 
one, and resume the bound transaction afterwards.


> Jakarta Data repository fails when called from an AFTER_SUCCESS transactional 
> observer
> --------------------------------------------------------------------------------------
>
>                 Key: TOMEE-4727
>                 URL: https://issues.apache.org/jira/browse/TOMEE-4727
>             Project: TomEE
>          Issue Type: Bug
>            Reporter: Markus Jung
>            Priority: Major
>
> {{RepositoryInvocationHandler.executeInTransaction}} only starts its own 
> transaction when {{TransactionManager.getStatus()}} returns 
> {{STATUS_NO_TRANSACTION}}, and joins the thread's transaction in every other 
> state.
> A CDI {{@Observes(during = TransactionPhase.AFTER_SUCCESS)}} observer runs in 
> the transaction's {{afterCompletion}} callback, where the committed 
> transaction is still bound to the thread with status {{STATUS_COMMITTED}}. A 
> repository call from such an observer joins the finished transaction and 
> fails:
> {code}jakarta.data.exceptions.DataException: Transaction 
> org.apache.geronimo.transaction.manager.TransactionImpl@3d803bed is not active
>       at 
> org.apache.webbeans.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:377)
>       at 
> org.apache.webbeans.ee.event.TransactionalEventNotifier$AfterCompletionSuccess.afterCompletion(TransactionalEventNotifier.java:208)
>       at 
> org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:335)
>       ...
> {code}
> [Jakarta Data 1.0, section 7.3 "Jakarta 
> Transactions"|https://jakarta.ee/specifications/data/1.0/jakarta-data-1.0#_jakarta_transactions]
>  requires a repository operation to join the global transaction only when
> bq. a global transaction is active on the thread of execution in which a 
> repository operation is called
> [CDI 4.1, section 9.5.3 "Observer method invocation 
> context"|https://jakarta.ee/specifications/cdi/4.1/jakarta-cdi-spec-4.1#observer_method_invocation_context]
>  allows such observers and leaves their transaction context open:
> bq. if the observer method is any other kind of transactional observer 
> method, it is called in an unspecified transaction context, but with the same 
> lifecycle contexts as the transaction that just completed.
> Fix: join only a {{STATUS_ACTIVE}} or {{STATUS_MARKED_ROLLBACK}} transaction; 
> in any other state suspend the bound transaction, run the operation in a new 
> one, and resume the bound transaction afterwards.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to