Skip to content

[tomee-10.x] TOMEE-4731 - Do not resume a transaction when there is none or the TransactionManager is gone - #3122

Merged
jungm merged 1 commit into
tomee-10.xfrom
TOMEE-4731-10.x
Oct 24, 2026
Merged

jungm merged 1 commit into
tomee-10.xfrom
TOMEE-4731-10.x

Conversation

@rzo1

@rzo1 rzo1 commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

https://issues.apache.org/jira/browse/TOMEE-4731 (backport of the fix on main to tomee-10.x)

Threads created by ManagedThreadFactoryImpl (e.g. the workers of the default ManagedExecutorService) run their whole life inside the default context service, which clears the transaction context. The restorer created on entering that context always called OpenEJB.getTransactionManager().resume(..) on exit, even if suspend() had returned null. When such a thread terminates after the container has been shut down, the TransactionManager is gone and every pool thread dies with:

java.lang.NullPointerException: Cannot invoke "jakarta.transaction.TransactionManager.resume(jakarta.transaction.Transaction)" because the return value of "org.apache.openejb.OpenEJB.getTransactionManager()" is null
    at org.apache.openejb.threads.impl.TxThreadContextProvider$TxThreadContextRestorer.endContext(TxThreadContextProvider.java:79)

Changes

  • TxThreadContextClearingSnapshot.begin() returns the no-op restorer if no transaction was suspended.
  • TxThreadContextRestorer.endContext() skips resume (logging a warning) if a suspended transaction cannot be resumed because the TransactionManager is no longer available.
  • Behaviour while the container is running is unchanged: a suspended transaction is still resumed.

Tests

TxThreadContextProviderTest: no-op restorer without a transaction, a suspended transaction is resumed, no failure once the TransactionManager is gone, and a regression test for a managed thread terminating after shutdown. Three of the four fail without the fix (two with exactly the NPE above); the fourth guards the existing resume behaviour.

…ansactionManager is gone

Threads created by ManagedThreadFactoryImpl run their whole life inside the
default context service, which clears the transaction context. The restorer
created when entering that context always called
OpenEJB.getTransactionManager().resume(..) on exit, even if suspend() had
returned null. When such a thread terminated after the container had been
shut down the TransactionManager was gone and the thread died with a
NullPointerException.

The clearing snapshot now returns the no-op restorer if no transaction was
suspended, and the restorer skips resume (logging a warning) if the
TransactionManager is no longer available.
@rzo1
rzo1 requested a review from jungm October 22, 2026 07:58
@jungm
jungm merged commit 8eef035 into tomee-10.x Oct 24, 2026
1 check passed
@jungm
jungm deleted the TOMEE-4731-10.x branch October 24, 2026 07:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants