Skip to content

Commit

Permalink
Merge pull request #22202 from quarkusio/narayana-dont-rollback
Browse files Browse the repository at this point in the history
Narayana: support @DontRollback on exception type
  • Loading branch information
FroMage authored Jan 26, 2022
2 parents 75842a8 + 990b2a7 commit 6600a9f
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.quarkus.narayana.interceptor;

import io.quarkus.narayana.jta.Rollback;

// prevent a rollback to counter the default
@Rollback(false)
public class AnnotatedError extends Error {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.quarkus.narayana.interceptor;

import io.quarkus.narayana.jta.Rollback;

// force a rollback to counter the default
@Rollback
public class AnnotatedTestException extends Exception {
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class TransactionalTest {
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(TransactionalTest.TransactionalBean.class, TestXAResource.class,
TxAssertionData.class, TestException.class))
TxAssertionData.class, TestException.class, AnnotatedTestException.class, AnnotatedError.class))
.addClassLoaderEventListener(ClassLoaderLimiter.builder()
.neverLoadedRuntimeClassName("javax.xml.stream.XMLInputFactory").build());

Expand Down Expand Up @@ -98,6 +98,32 @@ public void transactionalThrowError() {
Assertions.assertEquals(1, txAssertionData.getRollback());
}

@Test
public void transactionalThrowAnnotatedApplicationException() {
assertTransactionInactive();
try {
testTransactionalBean.executeTransactionalThrowException(AnnotatedTestException.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 transactionalThrowAnnotatedError() {
assertTransactionInactive();
try {
testTransactionalBean.executeTransactionalThrowException(AnnotatedError.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 transactionalThrowApplicationExceptionWithRollbackOn() {
assertTransactionInactive();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.narayana.jta;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* If you annotate your exception with this annotation, the transactional interceptor will
* use the exception's instructions to force a rollback or not.
*
* FIXME: move to SPI so it can be used by TransactionalReactive
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Rollback {
/**
* Specify whether the annotated exception should cause a rollback or not. Defaults to true.
*
* @return true if the annotated exception should cause a rollback or not.
*/
boolean value() default true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.arjuna.ats.jta.logging.jtaLogger;

import io.quarkus.arc.runtime.InterceptorBindings;
import io.quarkus.narayana.jta.Rollback;
import io.quarkus.narayana.jta.runtime.CDIDelegatingTransactionManager;
import io.quarkus.narayana.jta.runtime.TransactionConfiguration;
import io.smallrye.mutiny.Multi;
Expand Down Expand Up @@ -323,7 +324,6 @@ private void checkConfiguration(InvocationContext ic) {

protected void handleExceptionNoThrow(InvocationContext ic, Throwable t, Transaction tx)
throws IllegalStateException, SystemException {

Transactional transactional = getTransactional(ic);

for (Class<?> dontRollbackOnClass : transactional.dontRollbackOn()) {
Expand All @@ -339,6 +339,15 @@ protected void handleExceptionNoThrow(InvocationContext ic, Throwable t, Transac
}
}

Rollback rollbackAnnotation = t.getClass().getAnnotation(Rollback.class);
if (rollbackAnnotation != null) {
if (rollbackAnnotation.value()) {
tx.setRollbackOnly();
}
// in both cases, behaviour is specified by the annotation
return;
}

// RuntimeException and Error are un-checked exceptions and rollback is expected
if (t instanceof RuntimeException || t instanceof Error) {
tx.setRollbackOnly();
Expand Down

0 comments on commit 6600a9f

Please sign in to comment.