Skip to content

Commit

Permalink
Simplify the syntax of QuarkusTransaction.runner(...)
Browse files Browse the repository at this point in the history
  • Loading branch information
yrodiere committed Nov 4, 2022
1 parent bde9881 commit 3db2874
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 177 deletions.
6 changes: 3 additions & 3 deletions docs/src/main/asciidoc/transaction.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,12 @@ public class TransactionExample {
}
public void runnerExample() {
QuarkusTransaction.runner().requireNew().run(() -> {
QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).run(() -> {
//do work
});
int result = QuarkusTransaction.runner().requireNew()
int result = QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW)
.timeout(10)
.exceptionHandler((throwable) -> {
if (throwable instanceof SomeException) {
Expand All @@ -205,7 +205,7 @@ be automatically rolled back. This removes the need to explicitly catch exceptio
against inadvertent transaction leaks, however it does mean that this can only be used when the request scope is active. The second
example in the method calls begin with a timeout option, and then rolls back the transaction.

The second method shows the use of lambda scoped transactions with `QuarkusTransaction.runner()`;
The second method shows the use of lambda scoped transactions with `QuarkusTransaction.runner(...)`;
the first example just runs a `Runnable` within a new transaction,
the second calls a `Callable` with some specific options.
In particular the `exceptionHandler` method can be used to control if the transaction is rolled back or not on exception.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider;
import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.narayana.jta.TransactionSemantic;
import io.quarkus.test.QuarkusUnitTest;

public class UnsupportedPropertiesTest {
Expand Down Expand Up @@ -114,7 +115,7 @@ public void testPropertiesPropagatedToRuntimeInit() {
public void testInsertsOrdered() {
var listener = new BatchCountSpyingEventListener();

QuarkusTransaction.runner().requireNew().run(() -> {
QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).run(() -> {
em.unwrap(Session.class).addEventListeners(listener);

ParentEntity parent1 = new ParentEntity(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.narayana.jta.QuarkusTransactionException;
import io.quarkus.narayana.jta.TransactionExceptionResult;
import io.quarkus.narayana.jta.TransactionSemantic;
import io.quarkus.test.QuarkusUnitTest;

public class TransactionRunnerTest {
Expand All @@ -37,52 +38,57 @@ public class TransactionRunnerTest {
@Test
public void commit() {
var sync = new TestSync();
QuarkusTransaction.runner().requireNew().run(() -> register(sync));
QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).run(() -> register(sync));
assertEquals(Status.STATUS_COMMITTED, sync.completionStatus);

assertEquals(Status.STATUS_COMMITTED, QuarkusTransaction.runner().requireNew().call(this::register).completionStatus);
assertEquals(Status.STATUS_COMMITTED,
QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).call(this::register).completionStatus);
}

@Test
public void rollback() {
var sync1 = new TestSync();
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner().requireNew().run(() -> {
register(sync1);
QuarkusTransaction.rollback();
}));
assertThrows(QuarkusTransactionException.class,
() -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).run(() -> {
register(sync1);
QuarkusTransaction.rollback();
}));
assertEquals(Status.STATUS_ROLLEDBACK, sync1.completionStatus);

var sync2 = new TestSync();
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner().requireNew().call(() -> {
register(sync2);
QuarkusTransaction.rollback();
return null;
}));
assertThrows(QuarkusTransactionException.class,
() -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).call(() -> {
register(sync2);
QuarkusTransaction.rollback();
return null;
}));
assertEquals(Status.STATUS_ROLLEDBACK, sync2.completionStatus);
}

@Test
public void rollbackOnly() {
var sync1 = new TestSync();
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner().requireNew().run(() -> {
register(sync1);
QuarkusTransaction.setRollbackOnly();
}));
assertThrows(QuarkusTransactionException.class,
() -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).run(() -> {
register(sync1);
QuarkusTransaction.setRollbackOnly();
}));
assertEquals(Status.STATUS_ROLLEDBACK, sync1.completionStatus);

var sync2 = new TestSync();
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner().requireNew().call(() -> {
register(sync2);
QuarkusTransaction.setRollbackOnly();
return null;
}));
assertThrows(QuarkusTransactionException.class,
() -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).call(() -> {
register(sync2);
QuarkusTransaction.setRollbackOnly();
return null;
}));
assertEquals(Status.STATUS_ROLLEDBACK, sync2.completionStatus);
}

@Test
public void timeout() {
var sync1 = new TestSync();
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner().requireNew()
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW)
.timeout(1)
.run(() -> {
register(sync1);
Expand All @@ -95,7 +101,7 @@ public void timeout() {
assertEquals(Status.STATUS_ROLLEDBACK, sync1.completionStatus);

var sync2 = new TestSync();
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner().requireNew()
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW)
.timeout(1)
.call(() -> {
register(sync2);
Expand All @@ -112,23 +118,23 @@ public void timeout() {
@Test
public void exception() {
var sync1 = new TestSync();
assertThrows(MyRuntimeException.class, () -> QuarkusTransaction.runner().requireNew()
assertThrows(MyRuntimeException.class, () -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW)
.run(() -> {
register(sync1);
throw new MyRuntimeException();
}));
assertEquals(Status.STATUS_ROLLEDBACK, sync1.completionStatus);

var sync2 = new TestSync();
assertThrows(MyRuntimeException.class, () -> QuarkusTransaction.runner().requireNew()
assertThrows(MyRuntimeException.class, () -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW)
.call(() -> {
register(sync2);
throw new MyRuntimeException();
}));
assertEquals(Status.STATUS_ROLLEDBACK, sync2.completionStatus);

var sync3 = new TestSync();
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner().requireNew()
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW)
.call(() -> {
register(sync3);
throw new MyCheckedException();
Expand All @@ -139,7 +145,7 @@ public void exception() {
@Test
public void exceptionHandler() {
var sync1 = new TestSync();
assertThrows(MyRuntimeException.class, () -> QuarkusTransaction.runner().requireNew()
assertThrows(MyRuntimeException.class, () -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW)
.exceptionHandler((e) -> TransactionExceptionResult.COMMIT)
.run(() -> {
register(sync1);
Expand All @@ -148,7 +154,7 @@ public void exceptionHandler() {
assertEquals(Status.STATUS_COMMITTED, sync1.completionStatus);

var sync2 = new TestSync();
assertThrows(MyRuntimeException.class, () -> QuarkusTransaction.runner().requireNew()
assertThrows(MyRuntimeException.class, () -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW)
.exceptionHandler((e) -> TransactionExceptionResult.COMMIT)
.call(() -> {
register(sync2);
Expand All @@ -157,7 +163,7 @@ public void exceptionHandler() {
assertEquals(Status.STATUS_COMMITTED, sync2.completionStatus);

var sync3 = new TestSync();
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner().requireNew()
assertThrows(QuarkusTransactionException.class, () -> QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW)
.exceptionHandler((e) -> TransactionExceptionResult.COMMIT)
.call(() -> {
register(sync3);
Expand All @@ -171,13 +177,13 @@ public void exceptionHandler() {
public void suspendExisting() {
QuarkusTransaction.begin();
assertTrue(QuarkusTransaction.isActive());
QuarkusTransaction.runner().suspendExisting()
QuarkusTransaction.runner(TransactionSemantic.SUSPEND_EXISTING)
.run(() -> assertFalse(QuarkusTransaction.isActive()));
assertTrue(QuarkusTransaction.isActive());
QuarkusTransaction.rollback();

assertFalse(QuarkusTransaction.isActive());
QuarkusTransaction.runner().suspendExisting()
QuarkusTransaction.runner(TransactionSemantic.SUSPEND_EXISTING)
.run(() -> assertFalse(QuarkusTransaction.isActive()));
assertFalse(QuarkusTransaction.isActive());
}
Expand All @@ -187,13 +193,13 @@ public void suspendExisting() {
public void disallowExisting() {
assertFalse(QuarkusTransaction.isActive());
assertEquals(Status.STATUS_COMMITTED,
QuarkusTransaction.runner().disallowExisting().call(this::register).completionStatus);
QuarkusTransaction.runner(TransactionSemantic.DISALLOW_EXISTING).call(this::register).completionStatus);
assertFalse(QuarkusTransaction.isActive());

QuarkusTransaction.begin();
assertTrue(QuarkusTransaction.isActive());
assertThrows(QuarkusTransactionException.class,
() -> QuarkusTransaction.runner().disallowExisting().call(this::register));
() -> QuarkusTransaction.runner(TransactionSemantic.DISALLOW_EXISTING).call(this::register));
assertTrue(QuarkusTransaction.isActive());
QuarkusTransaction.rollback();
}
Expand All @@ -202,13 +208,14 @@ public void disallowExisting() {
@ActivateRequestContext
public void requireNew() throws SystemException {
assertFalse(QuarkusTransaction.isActive());
assertEquals(Status.STATUS_COMMITTED, QuarkusTransaction.runner().requireNew().call(this::register).completionStatus);
assertEquals(Status.STATUS_COMMITTED,
QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).call(this::register).completionStatus);
assertFalse(QuarkusTransaction.isActive());

QuarkusTransaction.begin();
assertTrue(QuarkusTransaction.isActive());
var tx = transactionManager.getTransaction();
assertEquals(Status.STATUS_COMMITTED, QuarkusTransaction.runner().requireNew().call(() -> {
assertEquals(Status.STATUS_COMMITTED, QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).call(() -> {
assertTrue(QuarkusTransaction.isActive());
assertNotEquals(tx, transactionManager.getTransaction());
return register();
Expand All @@ -221,13 +228,14 @@ public void requireNew() throws SystemException {
@ActivateRequestContext
public void joinExisting() throws SystemException {
assertFalse(QuarkusTransaction.isActive());
assertEquals(Status.STATUS_COMMITTED, QuarkusTransaction.runner().joinExisting().call(this::register).completionStatus);
assertEquals(Status.STATUS_COMMITTED,
QuarkusTransaction.runner(TransactionSemantic.JOIN_EXISTING).call(this::register).completionStatus);
assertFalse(QuarkusTransaction.isActive());

QuarkusTransaction.begin();
assertTrue(QuarkusTransaction.isActive());
var tx = transactionManager.getTransaction();
QuarkusTransaction.runner().joinExisting().call(() -> {
QuarkusTransaction.runner(TransactionSemantic.JOIN_EXISTING).call(() -> {
assertTrue(QuarkusTransaction.isActive());
assertEquals(tx, transactionManager.getTransaction());
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* is committed the transaction is rolled back. Note that this means this can only currently be used when the request scope is
* active.</li>
* <li><b>Per Transaction Timeouts:</b>
* {{@link BeginOptions#timeout(int)}/{@link TransactionRunnerRunOptions#timeout(int)}
* {{@link BeginOptions#timeout(int)}/{@link TransactionRunnerOptions#timeout(int)}
* can be used to set the new transactions timeout, without affecting the per thread default.</li>
* <li><b>Lambda Style Transactions: </b> {@link Runnable} and {@link Callable} instances can be run inside the scope of a new
* transaction.</li>
Expand Down Expand Up @@ -111,30 +111,32 @@ static void setRollbackOnly() {
* Examples of use:
*
* <pre>{@code
* QuarkusTransaction.runner().requireNew().run(() -> ...);
* QuarkusTransaction.runner().joinExisting().run(() -> ...);
* QuarkusTransaction.runner().suspendExisting().run(() -> ...);
* QuarkusTransaction.runner().disallowExisting().run(() -> ...);
* int value = QuarkusTransaction.runner().requireNew().call(() -> { ...; return 42; });
* int value = QuarkusTransaction.runner().joinExisting().call(() -> { ...; return 42; });
* int value = QuarkusTransaction.runner().suspendExisting().call(() -> { ...; return 42; });
* int value = QuarkusTransaction.runner().disallowExisting().call(() -> { ...; return 42; });
* QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).run(() -> ...);
* QuarkusTransaction.runner(TransactionSemantic.JOIN_EXISTING).run(() -> ...);
* QuarkusTransaction.runner(TransactionSemantic.SUSPEND_EXISTING).run(() -> ...);
* QuarkusTransaction.runner(TransactionSemantic.DISALLOW_EXISTING).run(() -> ...);
* int value = QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).call(() -> { ...; return 42; });
* int value = QuarkusTransaction.runner(TransactionSemantic.JOIN_EXISTING).call(() -> { ...; return 42; });
* int value = QuarkusTransaction.runner(TransactionSemantic.SUSPEND_EXISTING).call(() -> { ...; return 42; });
* int value = QuarkusTransaction.runner(TransactionSemantic.DISALLOW_EXISTING).call(() -> { ...; return 42; });
* }</pre>
*
* @return An interface that allows selecting the transaction semantics of the runner.
* @see TransactionRunnerSemanticOptions
* @param semantic The selected {@link TransactionSemantic}.
* @return An interface that allow various options of a transaction runner to be customized,
* or a {@link Runnable}/{@link Callable} to be executed.
* @see TransactionRunnerOptions
*/
static TransactionRunnerSemanticOptions runner() {
return new TransactionRunnerImpl();
static TransactionRunnerOptions runner(TransactionSemantic semantic) {
return new TransactionRunnerImpl(semantic);
}

/**
* Runs a task in a new transaction with the default timeout. This defaults to {@link Transactional.TxType#REQUIRES_NEW}
* semantics, however alternate semantics can be requested using {@link #run(RunOptions, Runnable)}.
*
* @param task The task to run in a transaction
* @deprecated For the same semantics, use {@code QuarkusTransaction.runner().requireNew().run(task)}.
* {@link #runner()} can also be used for alternate semantics and options.
* @deprecated For the same semantics, use {@code QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).run(task)}.
* {@link #runner(TransactionSemantic)} can also be used for alternate semantics and options.
*/
@Deprecated
static void run(Runnable task) {
Expand All @@ -147,7 +149,7 @@ static void run(Runnable task) {
*
* @param options Options that apply to the new transaction
* @param task The task to run in a transaction
* @deprecated Use {@link #runner()} instead.
* @deprecated Use {@link #runner(TransactionSemantic)} instead.
*/
@Deprecated
static void run(RunOptions options, Runnable task) {
Expand All @@ -167,8 +169,8 @@ public Object call() throws Exception {
* If the task throws a checked exception it will be wrapped with a {@link QuarkusTransactionException}
*
* @param task The task to run in a transaction
* @deprecated For the same semantics, use {@code QuarkusTransaction.runner().requireNew().call(task)}.
* {@link #runner()} can also be used for alternate semantics and options.
* @deprecated For the same semantics, use {@code QuarkusTransaction.runner(TransactionSemantic.REQUIRE_NEW).call(task)}.
* {@link #runner(TransactionSemantic)} can also be used for alternate semantics and options.
*/
@Deprecated
static <T> T call(Callable<T> task) {
Expand All @@ -183,7 +185,7 @@ static <T> T call(Callable<T> task) {
*
* @param options Options that apply to the new transaction
* @param task The task to run in a transaction
* @deprecated Use {@link #runner()} instead.
* @deprecated Use {@link #runner(TransactionSemantic)} instead.
*/
@Deprecated
static <T> T call(RunOptions options, Callable<T> task) {
Expand All @@ -192,7 +194,7 @@ static <T> T call(RunOptions options, Callable<T> task) {

/**
* @return a new RunOptions
* @deprecated Use {@link #runner()} instead.
* @deprecated Use {@link #runner(TransactionSemantic)} instead.
*/
@Deprecated
static RunOptions runOptions() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Builder interface to allow a transaction to be customized, including things like timeout and semantics when an existing
* transaction is present.
*
* @deprecated Use {@link QuarkusTransaction#runner()} instead.
* @deprecated Use {@link QuarkusTransaction#runner(TransactionSemantic)} instead.
*/
@Deprecated
public class RunOptions extends RunOptionsBase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
/**
* Enum that can be used to control the decision to rollback or commit based on the type of an exception.
*
* @see QuarkusTransaction#runner()
* @see TransactionRunnerRunOptions#exceptionHandler(Function)
* @see QuarkusTransaction#runner(TransactionSemantic)
* @see TransactionRunnerOptions#exceptionHandler(Function)
*/
public enum TransactionExceptionResult {

Expand Down
Loading

0 comments on commit 3db2874

Please sign in to comment.