Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Failure: testJTATransactionUsedSeriallyWithOverlapAndCommitWithinLastStage NullPointerException #18813

Closed
njr-11 opened this issue Sep 30, 2021 · 0 comments · Fixed by #18814
Assignees
Labels
release bug This bug is present in a released version of Open Liberty release:210011 team:Zombie Apocalypse

Comments

@njr-11
Copy link
Contributor

njr-11 commented Sep 30, 2021

Describe the bug
An application uses a ManagedExecutor to attempt to propagate Transaction context of an active UserTransaction to an asynchronous completion stage that overlaps the UserTransaction. Normally, the completion stage would raise IllegalStateException to reject the condition where it exists on 2 threads at the same time. However, if the application code suspends or resolves the UserTransaction while the asynchronous completion stage is attempting to start, the transaction code that ought to raise the IllegalStateException can hit a timing window where NullPointerException occurs.

Here is the code from the automated test case where we saw the failure occur intermittently,

        CompletableFuture<Integer> stage;
        tx.begin();
        try {
            stage = txExecutor.supplyAsync(() -> {
                try (Connection con = defaultDataSource.getConnection(); Statement st = con.createStatement()) {
                    return st.executeUpdate("INSERT INTO MNCOUNTIES VALUES ('Freeborn', 30619)");
                } catch (SQLException x) {
                    throw new CompletionException(x);
                }
            }).thenApplyAsync(numUpdates -> {
                try (Connection con = defaultDataSource.getConnection(); Statement st = con.createStatement()) {
                    numUpdates += st.executeUpdate("INSERT INTO MNCOUNTIES VALUES ('Mower', 39386)");
                    tx.commit();
                    return numUpdates;
                } catch (Exception x) {
                    throw new CompletionException(x);
                }
            }).exceptionally(x -> {
                try {
                    tx.rollback();
                } catch (Exception x2) {
                    x2.printStackTrace();
                }
                if (x instanceof RuntimeException)
                    throw (RuntimeException) x;
                if (x instanceof Error)
                    throw (Error) x;
                throw new CompletionException(x);
            });
        } finally {
            tm.suspend();
        }

        try {
            stage.get(TIMEOUT_NS, TimeUnit.NANOSECONDS);
        } catch (ExecutionException x) {
            Throwable cause = x.getCause();
            if (cause instanceof IllegalStateException) // transaction used on 2 threads at once
                return; // successful, got the expected exception
            else
                throw x; // unexpected failure, such as the NullPointerException
        }

If there is a stack trace, please include the FULL stack trace (without any [internal classes] lines in it). To find the full stack trace, you may need to check in $WLP_OUTPUT_DIR/messages.log

java.util.concurrent.ExecutionException: java.lang.NullPointerException: Cannot invoke "java.lang.Thread.getId()" because the return value of "com.ibm.tx.jta.embeddable.impl.EmbeddableTransactionImpl.getThread()" is null
	at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395)
	at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2092)
	[internal class]
	at concurrent.mp.fat.tx.web.MPConcurrentTxTestServlet.testJTATransactionUsedSeriallyWithOverlapAndCommitWithinLastStage(MPConcurrentTxTestServlet.java:879)
	at concurrent.mp.fat.tx.web.MPConcurrentTxTestServlet.doGet(MPConcurrentTxTestServlet.java:136)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:686)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
        [internal classes]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at java.base/java.lang.Thread.run(Thread.java:853)
Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Thread.getId()" because the return value of "com.ibm.tx.jta.embeddable.impl.EmbeddableTransactionImpl.getThread()" is null
	[internal classes]

Steps to Reproduce
Run the scenario within the following automated test case until it eventually hits the timing window and fails,

com.ibm.ws.concurrent.mp.fat.MPConcurrentTxTest.testJTATransactionUsedSeriallyWithOverlapAndCommitWithinLastStage_MP_CONTEXT_PROP_10

Expected behavior
CompletableFuture.get must raise ExecutionException with chained IllegalStateException indicating that the transaction cannot be propagated to the asynchronous completion stage thread while the same transaction remains active on the main servlet thread.

Diagnostic information:

  • OpenLiberty Version: all versions including the mpContextPropagation-1.0 or 1.2 feature up through 21.0.0.10.
  • Affected feature(s) mpContextPropagation-1.0 and 1.2
  • Java Version: all
  • server.xml configuration
<feature>mpContextPropagation-1.0</feature>

or

<feature>mpContextPropagation-1.0</feature>

Additional context
Because the error occurs while reporting an application bug, applications are recommended to fix the application bug by ensuring that the UserTransaction has been suspended from the servlet thread before permitting the start of any dependent completion stages to which the same Transaction context is propagated.

@njr-11 njr-11 added team:Zombie Apocalypse release bug This bug is present in a released version of Open Liberty labels Sep 30, 2021
@njr-11 njr-11 self-assigned this Sep 30, 2021
njr-11 added a commit to njr-11/open-liberty that referenced this issue Sep 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release bug This bug is present in a released version of Open Liberty release:210011 team:Zombie Apocalypse
Projects
None yet
2 participants