-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#16455] java.lang.Error should rollback the JTA transaction
- Loading branch information
Showing
5 changed files
with
330 additions
and
11 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
.../narayana-jta/deployment/src/test/java/io/quarkus/narayana/interceptor/TestException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package io.quarkus.narayana.interceptor; | ||
|
||
public class TestException extends Exception { | ||
} |
60 changes: 60 additions & 0 deletions
60
...narayana-jta/deployment/src/test/java/io/quarkus/narayana/interceptor/TestXAResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package io.quarkus.narayana.interceptor; | ||
|
||
import javax.transaction.xa.XAException; | ||
import javax.transaction.xa.XAResource; | ||
import javax.transaction.xa.Xid; | ||
|
||
public class TestXAResource implements XAResource { | ||
final TxAssertionData txAssertionData; | ||
|
||
TestXAResource(TxAssertionData txAssertionData) { | ||
this.txAssertionData = txAssertionData; | ||
} | ||
|
||
@Override | ||
public void commit(Xid xid, boolean b) throws XAException { | ||
txAssertionData.addCommit(); | ||
} | ||
|
||
@Override | ||
public void end(Xid xid, int i) throws XAException { | ||
} | ||
|
||
@Override | ||
public void forget(Xid xid) throws XAException { | ||
} | ||
|
||
@Override | ||
public int getTransactionTimeout() throws XAException { | ||
return 0; | ||
} | ||
|
||
@Override | ||
public boolean isSameRM(XAResource xaResource) throws XAException { | ||
return false; | ||
} | ||
|
||
@Override | ||
public int prepare(Xid xid) throws XAException { | ||
return XA_OK; | ||
} | ||
|
||
@Override | ||
public Xid[] recover(int i) throws XAException { | ||
return new Xid[0]; | ||
} | ||
|
||
@Override | ||
public void rollback(Xid xid) throws XAException { | ||
txAssertionData.addRollback(); | ||
} | ||
|
||
@Override | ||
public boolean setTransactionTimeout(int i) throws XAException { | ||
return false; | ||
} | ||
|
||
@Override | ||
public void start(Xid xid, int i) throws XAException { | ||
} | ||
} |
210 changes: 210 additions & 0 deletions
210
...ayana-jta/deployment/src/test/java/io/quarkus/narayana/interceptor/TransactionalTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
package io.quarkus.narayana.interceptor; | ||
|
||
import javax.enterprise.context.ApplicationScoped; | ||
import javax.inject.Inject; | ||
import javax.transaction.RollbackException; | ||
import javax.transaction.Status; | ||
import javax.transaction.SystemException; | ||
import javax.transaction.TransactionManager; | ||
import javax.transaction.Transactional; | ||
import javax.transaction.UserTransaction; | ||
|
||
import org.jboss.shrinkwrap.api.ShrinkWrap; | ||
import org.jboss.shrinkwrap.api.spec.JavaArchive; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.Assertions; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.RegisterExtension; | ||
|
||
import io.quarkus.test.QuarkusUnitTest; | ||
|
||
public class TransactionalTest { | ||
|
||
@RegisterExtension | ||
static final QuarkusUnitTest config = new QuarkusUnitTest() | ||
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) | ||
.addClasses(TransactionalTest.TransactionalBean.class, TestXAResource.class, | ||
TxAssertionData.class, TestException.class)); | ||
|
||
@Inject | ||
private TransactionManager tm; | ||
|
||
@Inject | ||
private UserTransaction userTransaction; | ||
|
||
@Inject | ||
private TransactionalTest.TransactionalBean testTransactionalBean; | ||
|
||
@Inject | ||
private TxAssertionData txAssertionData; | ||
|
||
@AfterEach | ||
public void tearDown() { | ||
try { | ||
userTransaction.rollback(); | ||
} catch (Exception e) { | ||
// do nothing | ||
} finally { | ||
txAssertionData.reset(); | ||
} | ||
} | ||
|
||
@Test | ||
public void transactionalRequiresToCommit() throws Exception { | ||
assertTransactionInactive(); | ||
testTransactionalBean.executeTransactional(); | ||
assertTransactionInactive(); | ||
Assertions.assertEquals(1, txAssertionData.getCommit()); | ||
Assertions.assertEquals(0, txAssertionData.getRollback()); | ||
} | ||
|
||
@Test | ||
public void transactionalThrowRuntimeException() { | ||
assertTransactionInactive(); | ||
try { | ||
testTransactionalBean.executeTransactionalThrowException(RuntimeException.class); | ||
Assertions.fail("Expecting RuntimeException to be thrown and the execution does not reach this point"); | ||
} catch (Throwable expected) { | ||
} | ||
assertTransactionInactive(); | ||
Assertions.assertEquals(0, txAssertionData.getCommit()); | ||
Assertions.assertEquals(1, txAssertionData.getRollback()); | ||
} | ||
|
||
@Test | ||
public void transactionalThrowApplicationException() { | ||
assertTransactionInactive(); | ||
try { | ||
testTransactionalBean.executeTransactionalThrowException(TestException.class); | ||
Assertions.fail("Expecting TestException to be thrown and the execution does not reach this point"); | ||
} catch (Throwable expected) { | ||
} | ||
assertTransactionInactive(); | ||
Assertions.assertEquals(1, txAssertionData.getCommit()); | ||
Assertions.assertEquals(0, txAssertionData.getRollback()); | ||
} | ||
|
||
@Test | ||
public void transactionalThrowError() { | ||
assertTransactionInactive(); | ||
try { | ||
testTransactionalBean.executeTransactionalThrowException(Error.class); | ||
Assertions.fail("Expecting Error to be thrown and the execution does not reach this point"); | ||
} catch (Throwable expected) { | ||
} | ||
assertTransactionInactive(); | ||
Assertions.assertEquals(0, txAssertionData.getCommit()); | ||
Assertions.assertEquals(1, txAssertionData.getRollback()); | ||
} | ||
|
||
@Test | ||
public void transactionalThrowApplicationExceptionWithRollbackOn() { | ||
assertTransactionInactive(); | ||
try { | ||
testTransactionalBean.executeTransactionalRollbackOnException(TestException.class); | ||
Assertions.fail("Expecting TestException to be thrown and the execution does not reach this point"); | ||
} catch (Throwable expected) { | ||
} | ||
assertTransactionInactive(); | ||
Assertions.assertEquals(0, txAssertionData.getCommit()); | ||
Assertions.assertEquals(1, txAssertionData.getRollback()); | ||
} | ||
|
||
@Test | ||
public void transactionalThrowRuntimeExceptionWithDontRollbackOn() { | ||
assertTransactionInactive(); | ||
try { | ||
testTransactionalBean.executeTransactionalDontRollbackOnRuntimeException(RuntimeException.class); | ||
Assertions.fail("Expecting RuntimeException to be thrown and the execution does not reach this point"); | ||
} catch (Throwable expected) { | ||
} | ||
assertTransactionInactive(); | ||
Assertions.assertEquals(1, txAssertionData.getCommit()); | ||
Assertions.assertEquals(0, txAssertionData.getRollback()); | ||
} | ||
|
||
@Test | ||
public void transactionalThrowErrorWithDontRollbackOn() { | ||
assertTransactionInactive(); | ||
try { | ||
testTransactionalBean.executeTransactionalDontRollbackOnError(Error.class); | ||
Assertions.fail("Expecting Error to be thrown and the execution does not reach this point"); | ||
} catch (Throwable expected) { | ||
} | ||
assertTransactionInactive(); | ||
Assertions.assertEquals(1, txAssertionData.getCommit()); | ||
Assertions.assertEquals(0, txAssertionData.getRollback()); | ||
} | ||
|
||
@Test | ||
public void transactionalThrowApplicationExceptionDontRollbackOnPriority() { | ||
assertTransactionInactive(); | ||
try { | ||
testTransactionalBean.executeTransactionalRollbackOnPriority(TestException.class); | ||
Assertions.fail("Expecting TestException to be thrown and the execution does not reach this point"); | ||
} catch (Throwable expected) { | ||
} | ||
assertTransactionInactive(); | ||
Assertions.assertEquals(1, txAssertionData.getCommit()); | ||
Assertions.assertEquals(0, txAssertionData.getRollback()); | ||
} | ||
|
||
private void assertTransactionInactive() { | ||
try { | ||
if (tm.getTransaction() != null) { | ||
Assertions.assertNotEquals(Status.STATUS_ACTIVE, tm.getTransaction().getStatus()); | ||
} | ||
} catch (Exception e) { | ||
Assertions.fail(e.getMessage()); | ||
} | ||
} | ||
|
||
@ApplicationScoped | ||
static class TransactionalBean { | ||
@Inject | ||
private TransactionManager transactionManager; | ||
|
||
@Inject | ||
private TxAssertionData txAssertionData; | ||
|
||
private void enlist() throws SystemException, RollbackException { | ||
transactionManager.getTransaction() | ||
.enlistResource(new TestXAResource(txAssertionData)); | ||
} | ||
|
||
@Transactional | ||
public void executeTransactional() throws Exception { | ||
enlist(); | ||
} | ||
|
||
@Transactional | ||
public void executeTransactionalThrowException(Class<? extends Throwable> throwable) throws Throwable { | ||
enlist(); | ||
throw throwable.newInstance(); | ||
} | ||
|
||
@Transactional(rollbackOn = Exception.class) | ||
public void executeTransactionalRollbackOnException(Class<? extends Throwable> throwable) throws Throwable { | ||
enlist(); | ||
throw throwable.newInstance(); | ||
} | ||
|
||
@Transactional(dontRollbackOn = RuntimeException.class) | ||
public void executeTransactionalDontRollbackOnRuntimeException(Class<? extends Throwable> throwable) throws Throwable { | ||
enlist(); | ||
throw throwable.newInstance(); | ||
} | ||
|
||
@Transactional(dontRollbackOn = Error.class) | ||
public void executeTransactionalDontRollbackOnError(Class<? extends Throwable> throwable) throws Throwable { | ||
enlist(); | ||
throw throwable.newInstance(); | ||
} | ||
|
||
@Transactional(dontRollbackOn = Exception.class, rollbackOn = Exception.class) | ||
public void executeTransactionalRollbackOnPriority(Class<? extends Throwable> throwable) throws Throwable { | ||
enlist(); | ||
throw throwable.newInstance(); | ||
} | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
...arayana-jta/deployment/src/test/java/io/quarkus/narayana/interceptor/TxAssertionData.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package io.quarkus.narayana.interceptor; | ||
|
||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
import javax.enterprise.context.ApplicationScoped; | ||
|
||
@ApplicationScoped | ||
public class TxAssertionData { | ||
private AtomicInteger commitNumber = new AtomicInteger(); | ||
private AtomicInteger rollbackNumber = new AtomicInteger(); | ||
|
||
public void reset() { | ||
commitNumber.set(0); | ||
rollbackNumber.set(0); | ||
} | ||
|
||
public int addCommit() { | ||
return commitNumber.incrementAndGet(); | ||
} | ||
|
||
public int addRollback() { | ||
return rollbackNumber.incrementAndGet(); | ||
} | ||
|
||
public int getCommit() { | ||
return commitNumber.get(); | ||
} | ||
|
||
public int getRollback() { | ||
return rollbackNumber.get(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters