Skip to content

Commit

Permalink
[#16455] java.lang.Error should rollback the JTA transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
ochaloup committed Apr 12, 2021
1 parent f4b84a9 commit 04ff67a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.quarkus.narayana.jta.runtime;

/**
* An utility class which makes possible to throw any exception as a {@link RuntimeException}.
* It means to throw checked exception (subtype of Throwable or Exception) as un-checked exception.
* This considers the Java 8 inference rule that states that a {@code throws E} is inferred as {@code RuntimeException}.
*/
public class SneakyThrow {
private SneakyThrow() {
throw new IllegalStateException("utility class, do not create an instance");
}

/**
* This method can be used in {@code throw} statement
* such as: {@code throw sneakyThrow(exception);}.
*/
@SuppressWarnings("unchecked")
public static <E extends Throwable> void sneakyThrow(Throwable e) throws E {
throw (E) e;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import io.quarkus.arc.runtime.InterceptorBindings;
import io.quarkus.narayana.jta.runtime.CDIDelegatingTransactionManager;
import io.quarkus.narayana.jta.runtime.SneakyThrow;
import io.quarkus.narayana.jta.runtime.TransactionConfiguration;
import io.smallrye.mutiny.Multi;
import io.smallrye.reactive.converters.ReactiveTypeConverter;
Expand Down Expand Up @@ -125,9 +126,9 @@ protected Object invokeInOurTx(InvocationContext ic, TransactionManager tm, Runn

try {
ret = ic.proceed();
} catch (Exception e) {
} catch (Throwable t) {
throwing = true;
handleException(ic, e, tx);
handleException(ic, t, tx);
} finally {
// handle asynchronously if not throwing
if (!throwing && ret != null) {
Expand Down Expand Up @@ -250,8 +251,8 @@ protected Object invokeInCallerTx(InvocationContext ic, Transaction tx) throws E
try {
checkConfiguration(ic);
return ic.proceed();
} catch (Exception e) {
handleException(ic, e, tx);
} catch (Throwable t) {
handleException(ic, t, tx);
}
throw new RuntimeException("UNREACHABLE");
}
Expand All @@ -269,34 +270,35 @@ private void checkConfiguration(InvocationContext ic) {
}
}

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

Transactional transactional = getTransactional(ic);

for (Class<?> dontRollbackOnClass : transactional.dontRollbackOn()) {
if (dontRollbackOnClass.isAssignableFrom(e.getClass())) {
if (dontRollbackOnClass.isAssignableFrom(t.getClass())) {
return;
}
}

for (Class<?> rollbackOnClass : transactional.rollbackOn()) {
if (rollbackOnClass.isAssignableFrom(e.getClass())) {
if (rollbackOnClass.isAssignableFrom(t.getClass())) {
tx.setRollbackOnly();
return;
}
}

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

protected void handleException(InvocationContext ic, Exception e, Transaction tx) throws Exception {
protected void handleException(InvocationContext ic, Throwable t, Transaction tx) throws Exception {

handleExceptionNoThrow(ic, e, tx);
throw e;
handleExceptionNoThrow(ic, t, tx);
SneakyThrow.sneakyThrow(t);
}

protected void endTransaction(TransactionManager tm, Transaction tx, RunnableWithException afterEndTransaction)
Expand Down

0 comments on commit 04ff67a

Please sign in to comment.