use of cn.taketoday.transaction.TransactionDefinition in project today-infrastructure by TAKETODAY.
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));
}
});
}
use of cn.taketoday.transaction.TransactionDefinition in project today-infrastructure by TAKETODAY.
the class BeanFactoryTransactionTests method doTestGetsAreNotTransactional.
private void doTestGetsAreNotTransactional(final ITestBean testBean) {
// Install facade
PlatformTransactionManager ptm = mock(PlatformTransactionManager.class);
PlatformTransactionManagerFacade.delegate = ptm;
assertThat(testBean.getAge() == 666).as("Age should not be " + testBean.getAge()).isTrue();
// Expect no methods
verifyNoInteractions(ptm);
// Install facade expecting a call
final TransactionStatus ts = mock(TransactionStatus.class);
ptm = new PlatformTransactionManager() {
private boolean invoked;
@Override
public TransactionStatus getTransaction(@Nullable TransactionDefinition def) throws TransactionException {
if (invoked) {
throw new IllegalStateException("getTransaction should not get invoked more than once");
}
invoked = true;
if (!(def.getName().contains(DerivedTestBean.class.getName()) && def.getName().contains("setAge"))) {
throw new IllegalStateException("transaction name should contain class and method name: " + def.getName());
}
return ts;
}
@Override
public void commit(TransactionStatus status) throws TransactionException {
assertThat(status == ts).isTrue();
}
@Override
public void rollback(TransactionStatus status) throws TransactionException {
throw new IllegalStateException("rollback should not get invoked");
}
};
PlatformTransactionManagerFacade.delegate = ptm;
// TODO same as old age to avoid ordering effect for now
int age = 666;
testBean.setAge(age);
assertThat(testBean.getAge() == age).isTrue();
}
use of cn.taketoday.transaction.TransactionDefinition in project today-framework by TAKETODAY.
the class DefaultJpaDialectTests method testDefaultBeginTransaction.
@Test
public void testDefaultBeginTransaction() throws Exception {
TransactionDefinition definition = new DefaultTransactionDefinition();
EntityManager entityManager = mock(EntityManager.class);
EntityTransaction entityTx = mock(EntityTransaction.class);
given(entityManager.getTransaction()).willReturn(entityTx);
dialect.beginTransaction(entityManager, definition);
}
use of cn.taketoday.transaction.TransactionDefinition in project today-framework by TAKETODAY.
the class BeanFactoryTransactionTests method doTestGetsAreNotTransactional.
private void doTestGetsAreNotTransactional(final ITestBean testBean) {
// Install facade
PlatformTransactionManager ptm = mock(PlatformTransactionManager.class);
PlatformTransactionManagerFacade.delegate = ptm;
assertThat(testBean.getAge() == 666).as("Age should not be " + testBean.getAge()).isTrue();
// Expect no methods
verifyNoInteractions(ptm);
// Install facade expecting a call
final TransactionStatus ts = mock(TransactionStatus.class);
ptm = new PlatformTransactionManager() {
private boolean invoked;
@Override
public TransactionStatus getTransaction(@Nullable TransactionDefinition def) throws TransactionException {
if (invoked) {
throw new IllegalStateException("getTransaction should not get invoked more than once");
}
invoked = true;
if (!(def.getName().contains(DerivedTestBean.class.getName()) && def.getName().contains("setAge"))) {
throw new IllegalStateException("transaction name should contain class and method name: " + def.getName());
}
return ts;
}
@Override
public void commit(TransactionStatus status) throws TransactionException {
assertThat(status == ts).isTrue();
}
@Override
public void rollback(TransactionStatus status) throws TransactionException {
throw new IllegalStateException("rollback should not get invoked");
}
};
PlatformTransactionManagerFacade.delegate = ptm;
// TODO same as old age to avoid ordering effect for now
int age = 666;
testBean.setAge(age);
assertThat(testBean.getAge() == age).isTrue();
}
use of cn.taketoday.transaction.TransactionDefinition in project today-framework by TAKETODAY.
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));
}
});
}
Aggregations