Search in sources :

Example 6 with ReactiveTransactionManager

use of org.springframework.transaction.ReactiveTransactionManager in project spring-framework by spring-projects.

the class AbstractReactiveTransactionAspectTests method twoTransactionsShouldSucceed.

/**
 * Check that two transactions are created and committed.
 */
@Test
public void twoTransactionsShouldSucceed() throws Exception {
    TransactionAttribute txatt = new DefaultTransactionAttribute();
    MapTransactionAttributeSource tas1 = new MapTransactionAttributeSource();
    tas1.register(getNameMethod, txatt);
    MapTransactionAttributeSource tas2 = new MapTransactionAttributeSource();
    tas2.register(setNameMethod, txatt);
    ReactiveTransaction status = mock(ReactiveTransaction.class);
    ReactiveTransactionManager rtm = mock(ReactiveTransactionManager.class);
    // expect a transaction
    given(rtm.getReactiveTransaction(txatt)).willReturn(Mono.just(status));
    given(rtm.commit(status)).willReturn(Mono.empty());
    DefaultTestBean tb = new DefaultTestBean();
    TestBean itb = (TestBean) advised(tb, rtm, new TransactionAttributeSource[] { tas1, tas2 });
    itb.getName().as(StepVerifier::create).verifyComplete();
    Mono.from(itb.setName("myName")).as(StepVerifier::create).verifyComplete();
    verify(rtm, times(2)).commit(status);
}
Also used : ReactiveTransaction(org.springframework.transaction.ReactiveTransaction) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) Test(org.junit.jupiter.api.Test)

Example 7 with ReactiveTransactionManager

use of org.springframework.transaction.ReactiveTransactionManager in project spring-framework by spring-projects.

the class ReactiveTransactionSupportTests method noExistingTransaction.

@Test
public void noExistingTransaction() {
    ReactiveTransactionManager tm = new ReactiveTestTransactionManager(false, true);
    tm.getReactiveTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS)).contextWrite(TransactionContextManager.createTransactionContext()).cast(GenericReactiveTransaction.class).as(StepVerifier::create).consumeNextWith(actual -> assertThat(actual.hasTransaction()).isFalse()).verifyComplete();
    tm.getReactiveTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED)).cast(GenericReactiveTransaction.class).contextWrite(TransactionContextManager.createTransactionContext()).as(StepVerifier::create).consumeNextWith(actual -> {
        assertThat(actual.hasTransaction()).isTrue();
        assertThat(actual.isNewTransaction()).isTrue();
    }).verifyComplete();
    tm.getReactiveTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_MANDATORY)).contextWrite(TransactionContextManager.createTransactionContext()).cast(GenericReactiveTransaction.class).as(StepVerifier::create).expectError(IllegalTransactionStateException.class).verify();
}
Also used : Test(org.junit.jupiter.api.Test) Flux(reactor.core.publisher.Flux) StepVerifier(reactor.test.StepVerifier) TransactionDefinition(org.springframework.transaction.TransactionDefinition) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) Mono(reactor.core.publisher.Mono) ReactiveTransaction(org.springframework.transaction.ReactiveTransaction) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) StepVerifier(reactor.test.StepVerifier) Test(org.junit.jupiter.api.Test)

Example 8 with ReactiveTransactionManager

use of org.springframework.transaction.ReactiveTransactionManager in project spring-framework by spring-projects.

the class AbstractReactiveTransactionManager method getReactiveTransaction.

// ---------------------------------------------------------------------
// Implementation of ReactiveTransactionManager
// ---------------------------------------------------------------------
/**
 * This implementation handles propagation behavior. Delegates to
 * {@code doGetTransaction}, {@code isExistingTransaction}
 * and {@code doBegin}.
 * @see #doGetTransaction
 * @see #isExistingTransaction
 * @see #doBegin
 */
@Override
public final Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
    // Use defaults if no transaction definition given.
    TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
    return TransactionSynchronizationManager.forCurrentTransaction().flatMap(synchronizationManager -> {
        Object transaction = doGetTransaction(synchronizationManager);
        // Cache debug flag to avoid repeated checks.
        boolean debugEnabled = logger.isDebugEnabled();
        if (isExistingTransaction(transaction)) {
            // Existing transaction found -> check propagation behavior to find out how to behave.
            return handleExistingTransaction(synchronizationManager, def, transaction, debugEnabled);
        }
        // Check definition settings for new transaction.
        if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
            return Mono.error(new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout()));
        }
        // No existing transaction found -> check propagation behavior to find out how to proceed.
        if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
            return Mono.error(new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'"));
        } else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
            return TransactionContextManager.currentContext().map(TransactionSynchronizationManager::new).flatMap(nestedSynchronizationManager -> suspend(nestedSynchronizationManager, null).map(Optional::of).defaultIfEmpty(Optional.empty()).flatMap(suspendedResources -> {
                if (debugEnabled) {
                    logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
                }
                return Mono.defer(() -> {
                    GenericReactiveTransaction status = newReactiveTransaction(nestedSynchronizationManager, def, transaction, true, debugEnabled, suspendedResources.orElse(null));
                    return doBegin(nestedSynchronizationManager, transaction, def).doOnSuccess(ignore -> prepareSynchronization(nestedSynchronizationManager, status, def)).thenReturn(status);
                }).onErrorResume(ErrorPredicates.RUNTIME_OR_ERROR, ex -> resume(nestedSynchronizationManager, null, suspendedResources.orElse(null)).then(Mono.error(ex)));
            }));
        } else {
            // Create "empty" transaction: no actual transaction, but potentially synchronization.
            if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
                logger.warn("Custom isolation level specified but no actual transaction initiated; " + "isolation level will effectively be ignored: " + def);
            }
            return Mono.just(prepareReactiveTransaction(synchronizationManager, def, null, true, debugEnabled, null));
        }
    });
}
Also used : TransactionDefinition(org.springframework.transaction.TransactionDefinition) TransactionSuspensionNotSupportedException(org.springframework.transaction.TransactionSuspensionNotSupportedException) Predicate(java.util.function.Predicate) TransactionDefinition(org.springframework.transaction.TransactionDefinition) ObjectInputStream(java.io.ObjectInputStream) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) IOException(java.io.IOException) Mono(reactor.core.publisher.Mono) UnexpectedRollbackException(org.springframework.transaction.UnexpectedRollbackException) ReactiveTransaction(org.springframework.transaction.ReactiveTransaction) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) Serializable(java.io.Serializable) Flux(reactor.core.publisher.Flux) List(java.util.List) InvalidTimeoutException(org.springframework.transaction.InvalidTimeoutException) TransactionException(org.springframework.transaction.TransactionException) Optional(java.util.Optional) Log(org.apache.commons.logging.Log) Nullable(org.springframework.lang.Nullable) LogFactory(org.apache.commons.logging.LogFactory) InvalidTimeoutException(org.springframework.transaction.InvalidTimeoutException) Optional(java.util.Optional) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException)

Example 9 with ReactiveTransactionManager

use of org.springframework.transaction.ReactiveTransactionManager in project spring-framework by spring-projects.

the class AbstractReactiveTransactionAspectTests method cannotCreateTransaction.

/**
 * Simulate a transaction infrastructure failure.
 * Shouldn't invoke target method.
 */
@Test
public void cannotCreateTransaction() throws Exception {
    TransactionAttribute txatt = new DefaultTransactionAttribute();
    Method m = getNameMethod;
    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(m, txatt);
    ReactiveTransactionManager rtm = mock(ReactiveTransactionManager.class);
    // Expect a transaction
    CannotCreateTransactionException ex = new CannotCreateTransactionException("foobar", null);
    given(rtm.getReactiveTransaction(txatt)).willThrow(ex);
    DefaultTestBean tb = new DefaultTestBean() {

        @Override
        public Mono<String> getName() {
            throw new UnsupportedOperationException("Shouldn't have invoked target method when couldn't create transaction for transactional method");
        }
    };
    TestBean itb = (TestBean) advised(tb, rtm, tas);
    itb.getName().as(StepVerifier::create).expectError(CannotCreateTransactionException.class).verify();
}
Also used : CannotCreateTransactionException(org.springframework.transaction.CannotCreateTransactionException) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) Method(java.lang.reflect.Method) StepVerifier(reactor.test.StepVerifier) Test(org.junit.jupiter.api.Test)

Example 10 with ReactiveTransactionManager

use of org.springframework.transaction.ReactiveTransactionManager in project spring-framework by spring-projects.

the class AbstractReactiveTransactionAspectTests method cannotCommitTransaction.

/**
 * Simulate failure of the underlying transaction infrastructure to commit.
 * Check that the target method was invoked, but that the transaction
 * infrastructure exception was thrown to the client
 */
@Test
public void cannotCommitTransaction() throws Exception {
    TransactionAttribute txatt = new DefaultTransactionAttribute();
    Method m = setNameMethod;
    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(m, txatt);
    // Method m2 = getNameMethod;
    // No attributes for m2
    ReactiveTransactionManager rtm = mock(ReactiveTransactionManager.class);
    ReactiveTransaction status = mock(ReactiveTransaction.class);
    given(rtm.getReactiveTransaction(txatt)).willReturn(Mono.just(status));
    UnexpectedRollbackException ex = new UnexpectedRollbackException("foobar", null);
    given(rtm.commit(status)).willReturn(Mono.error(ex));
    given(rtm.rollback(status)).willReturn(Mono.empty());
    DefaultTestBean tb = new DefaultTestBean();
    TestBean itb = (TestBean) advised(tb, rtm, tas);
    String name = "new name";
    Mono.from(itb.setName(name)).as(StepVerifier::create).consumeErrorWith(throwable -> {
        assertThat(throwable.getClass()).isEqualTo(RuntimeException.class);
        assertThat(throwable.getCause()).isEqualTo(ex);
    }).verify();
    // Should have invoked target and changed name
    itb.getName().as(StepVerifier::create).expectNext(name).verifyComplete();
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) StepVerifier(reactor.test.StepVerifier) Publisher(org.reactivestreams.Publisher) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) Mono(reactor.core.publisher.Mono) UnexpectedRollbackException(org.springframework.transaction.UnexpectedRollbackException) Mockito.times(org.mockito.Mockito.times) ReactiveTransaction(org.springframework.transaction.ReactiveTransaction) Fail.fail(org.assertj.core.api.Fail.fail) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) Mockito.verify(org.mockito.Mockito.verify) Mockito.verifyNoInteractions(org.mockito.Mockito.verifyNoInteractions) Test(org.junit.jupiter.api.Test) TransactionSystemException(org.springframework.transaction.TransactionSystemException) BDDMockito.given(org.mockito.BDDMockito.given) TransactionContext(org.springframework.transaction.reactive.TransactionContext) CannotCreateTransactionException(org.springframework.transaction.CannotCreateTransactionException) Method(java.lang.reflect.Method) Mockito.mock(org.mockito.Mockito.mock) Method(java.lang.reflect.Method) ReactiveTransaction(org.springframework.transaction.ReactiveTransaction) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) UnexpectedRollbackException(org.springframework.transaction.UnexpectedRollbackException) StepVerifier(reactor.test.StepVerifier) Test(org.junit.jupiter.api.Test)

Aggregations

ReactiveTransactionManager (org.springframework.transaction.ReactiveTransactionManager)13 Test (org.junit.jupiter.api.Test)11 ReactiveTransaction (org.springframework.transaction.ReactiveTransaction)9 Mono (reactor.core.publisher.Mono)6 Method (java.lang.reflect.Method)4 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)4 Flux (reactor.core.publisher.Flux)4 StepVerifier (reactor.test.StepVerifier)4 Publisher (org.reactivestreams.Publisher)3 CannotCreateTransactionException (org.springframework.transaction.CannotCreateTransactionException)3 IllegalTransactionStateException (org.springframework.transaction.IllegalTransactionStateException)3 TransactionDefinition (org.springframework.transaction.TransactionDefinition)3 TransactionSystemException (org.springframework.transaction.TransactionSystemException)3 UnexpectedRollbackException (org.springframework.transaction.UnexpectedRollbackException)3 Log (org.apache.commons.logging.Log)2 LogFactory (org.apache.commons.logging.LogFactory)2 Fail.fail (org.assertj.core.api.Fail.fail)2 BeforeEach (org.junit.jupiter.api.BeforeEach)2 BDDMockito.given (org.mockito.BDDMockito.given)2 Mockito.mock (org.mockito.Mockito.mock)2