Search in sources :

Example 1 with TransactionManager

use of org.springframework.transaction.TransactionManager in project spring-boot by spring-projects.

the class DataSourceTransactionManagerAutoConfigurationTests method transactionManagerWithCustomizationIsConfigured.

@Test
void transactionManagerWithCustomizationIsConfigured() {
    this.contextRunner.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)).withPropertyValues("spring.transaction.default-timeout=1m", "spring.transaction.rollback-on-commit-failure=true").run((context) -> {
        assertThat(context).hasSingleBean(TransactionManager.class).hasSingleBean(JdbcTransactionManager.class);
        JdbcTransactionManager transactionManager = context.getBean(JdbcTransactionManager.class);
        assertThat(transactionManager.getDefaultTimeout()).isEqualTo(60);
        assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
    });
}
Also used : JdbcTransactionManager(org.springframework.jdbc.support.JdbcTransactionManager) TransactionManager(org.springframework.transaction.TransactionManager) JdbcTransactionManager(org.springframework.jdbc.support.JdbcTransactionManager) DataSourceTransactionManager(org.springframework.jdbc.datasource.DataSourceTransactionManager) Test(org.junit.jupiter.api.Test)

Example 2 with TransactionManager

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

the class TransactionAspectSupport method invokeWithinTransaction.

/**
 * General delegate for around-advice-based subclasses, delegating to several other template
 * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
 * as well as regular {@link PlatformTransactionManager} implementations and
 * {@link ReactiveTransactionManager} implementations for reactive return types.
 * @param method the Method being invoked
 * @param targetClass the target class that we're invoking the method on
 * @param invocation the callback to use for proceeding with the target invocation
 * @return the return value of the method, if any
 * @throws Throwable propagated from the target invocation
 */
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable {
    // If the transaction attribute is null, the method is non-transactional.
    TransactionAttributeSource tas = getTransactionAttributeSource();
    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    final TransactionManager tm = determineTransactionManager(txAttr);
    if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
        boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
        boolean hasSuspendingFlowReturnType = isSuspendingFunction && COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName());
        if (isSuspendingFunction && !(invocation instanceof CoroutinesInvocationCallback)) {
            throw new IllegalStateException("Coroutines invocation not supported: " + method);
        }
        CoroutinesInvocationCallback corInv = (isSuspendingFunction ? (CoroutinesInvocationCallback) invocation : null);
        ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
            Class<?> reactiveType = (isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType());
            ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType);
            if (adapter == null) {
                throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " + method.getReturnType());
            }
            return new ReactiveTransactionSupport(adapter);
        });
        InvocationCallback callback = invocation;
        if (corInv != null) {
            callback = () -> CoroutinesUtils.invokeSuspendingFunction(method, corInv.getTarget(), corInv.getArguments());
        }
        Object result = txSupport.invokeWithinTransaction(method, targetClass, callback, txAttr, (ReactiveTransactionManager) tm);
        if (corInv != null) {
            Publisher<?> pr = (Publisher<?>) result;
            return (hasSuspendingFlowReturnType ? KotlinDelegate.asFlow(pr) : KotlinDelegate.awaitSingleOrNull(pr, corInv.getContinuation()));
        }
        return result;
    }
    PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
        // Standard transaction demarcation with getTransaction and commit/rollback calls.
        TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
        Object retVal;
        try {
            // This is an around advice: Invoke the next interceptor in the chain.
            // This will normally result in a target object being invoked.
            retVal = invocation.proceedWithInvocation();
        } catch (Throwable ex) {
            // target invocation exception
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        } finally {
            cleanupTransactionInfo(txInfo);
        }
        if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
            // Set rollback-only in case of Vavr failure matching our rollback rules...
            TransactionStatus status = txInfo.getTransactionStatus();
            if (status != null && txAttr != null) {
                retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
            }
        }
        commitTransactionAfterReturning(txInfo);
        return retVal;
    } else {
        Object result;
        final ThrowableHolder throwableHolder = new ThrowableHolder();
        // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
        try {
            result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
                TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
                try {
                    Object retVal = invocation.proceedWithInvocation();
                    if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                        // Set rollback-only in case of Vavr failure matching our rollback rules...
                        retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                    }
                    return retVal;
                } catch (Throwable ex) {
                    if (txAttr.rollbackOn(ex)) {
                        // A RuntimeException: will lead to a rollback.
                        if (ex instanceof RuntimeException) {
                            throw (RuntimeException) ex;
                        } else {
                            throw new ThrowableHolderException(ex);
                        }
                    } else {
                        // A normal return value: will lead to a commit.
                        throwableHolder.throwable = ex;
                        return null;
                    }
                } finally {
                    cleanupTransactionInfo(txInfo);
                }
            });
        } catch (ThrowableHolderException ex) {
            throw ex.getCause();
        } catch (TransactionSystemException ex2) {
            if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                ex2.initApplicationException(throwableHolder.throwable);
            }
            throw ex2;
        } catch (Throwable ex2) {
            if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
            }
            throw ex2;
        }
        // Check result state: It might indicate a Throwable to rethrow.
        if (throwableHolder.throwable != null) {
            throw throwableHolder.throwable;
        }
        return result;
    }
}
Also used : Continuation(kotlin.coroutines.Continuation) AwaitKt(kotlinx.coroutines.reactive.AwaitKt) ReactiveTransaction(org.springframework.transaction.ReactiveTransaction) InitializingBean(org.springframework.beans.factory.InitializingBean) ConcurrentMap(java.util.concurrent.ConcurrentMap) ConcurrentReferenceHashMap(org.springframework.util.ConcurrentReferenceHashMap) KotlinDetector(org.springframework.core.KotlinDetector) TransactionManager(org.springframework.transaction.TransactionManager) TransactionSystemException(org.springframework.transaction.TransactionSystemException) BeanFactoryAware(org.springframework.beans.factory.BeanFactoryAware) MethodParameter(org.springframework.core.MethodParameter) Nullable(org.springframework.lang.Nullable) Method(java.lang.reflect.Method) BeanFactoryAnnotationUtils(org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils) ReactiveAdapterRegistry(org.springframework.core.ReactiveAdapterRegistry) ReactiveFlowKt(kotlinx.coroutines.reactive.ReactiveFlowKt) CoroutinesUtils(org.springframework.core.CoroutinesUtils) TransactionContextManager(org.springframework.transaction.reactive.TransactionContextManager) ReactiveAdapter(org.springframework.core.ReactiveAdapter) Properties(java.util.Properties) ClassUtils(org.springframework.util.ClassUtils) CallbackPreferringPlatformTransactionManager(org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager) Publisher(org.reactivestreams.Publisher) Mono(reactor.core.publisher.Mono) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) NamedThreadLocal(org.springframework.core.NamedThreadLocal) Flux(reactor.core.publisher.Flux) Try(io.vavr.control.Try) NoTransactionException(org.springframework.transaction.NoTransactionException) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) BeanFactory(org.springframework.beans.factory.BeanFactory) TransactionStatus(org.springframework.transaction.TransactionStatus) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) Assert(org.springframework.util.Assert) StringUtils(org.springframework.util.StringUtils) TransactionStatus(org.springframework.transaction.TransactionStatus) TransactionSystemException(org.springframework.transaction.TransactionSystemException) CallbackPreferringPlatformTransactionManager(org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager) ReactiveAdapter(org.springframework.core.ReactiveAdapter) Mono(reactor.core.publisher.Mono) Flux(reactor.core.publisher.Flux) Publisher(org.reactivestreams.Publisher) CallbackPreferringPlatformTransactionManager(org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) TransactionManager(org.springframework.transaction.TransactionManager) CallbackPreferringPlatformTransactionManager(org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) MethodParameter(org.springframework.core.MethodParameter) Nullable(org.springframework.lang.Nullable)

Example 3 with TransactionManager

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

the class TransactionAspectSupport method determineQualifiedTransactionManager.

private TransactionManager determineQualifiedTransactionManager(BeanFactory beanFactory, String qualifier) {
    TransactionManager txManager = this.transactionManagerCache.get(qualifier);
    if (txManager == null) {
        txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, TransactionManager.class, qualifier);
        this.transactionManagerCache.putIfAbsent(qualifier, txManager);
    }
    return txManager;
}
Also used : TransactionManager(org.springframework.transaction.TransactionManager) CallbackPreferringPlatformTransactionManager(org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager) ReactiveTransactionManager(org.springframework.transaction.ReactiveTransactionManager) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager)

Example 4 with TransactionManager

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

the class TransactionInterceptorTests method determineTransactionManagerDefaultSeveralTimes.

@Test
public void determineTransactionManagerDefaultSeveralTimes() {
    BeanFactory beanFactory = mock(BeanFactory.class);
    TransactionInterceptor ti = simpleTransactionInterceptor(beanFactory);
    PlatformTransactionManager txManager = mock(PlatformTransactionManager.class);
    given(beanFactory.getBean(TransactionManager.class)).willReturn(txManager);
    DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
    TransactionManager actual = ti.determineTransactionManager(attribute);
    assertThat(actual).isSameAs(txManager);
    // Call again, should be cached
    TransactionManager actual2 = ti.determineTransactionManager(attribute);
    assertThat(actual2).isSameAs(txManager);
    verify(beanFactory, times(1)).getBean(TransactionManager.class);
}
Also used : TransactionManager(org.springframework.transaction.TransactionManager) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) BeanFactory(org.springframework.beans.factory.BeanFactory) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) Test(org.junit.jupiter.api.Test)

Example 5 with TransactionManager

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

the class TransactionInterceptorTests method determineTransactionManagerWithQualifierSeveralTimes.

@Test
public void determineTransactionManagerWithQualifierSeveralTimes() {
    BeanFactory beanFactory = mock(BeanFactory.class);
    TransactionInterceptor ti = simpleTransactionInterceptor(beanFactory);
    PlatformTransactionManager txManager = associateTransactionManager(beanFactory, "fooTransactionManager");
    DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
    attribute.setQualifier("fooTransactionManager");
    TransactionManager actual = ti.determineTransactionManager(attribute);
    assertThat(actual).isSameAs(txManager);
    // Call again, should be cached
    TransactionManager actual2 = ti.determineTransactionManager(attribute);
    assertThat(actual2).isSameAs(txManager);
    verify(beanFactory, times(1)).containsBean("fooTransactionManager");
    verify(beanFactory, times(1)).getBean("fooTransactionManager", TransactionManager.class);
}
Also used : TransactionManager(org.springframework.transaction.TransactionManager) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) BeanFactory(org.springframework.beans.factory.BeanFactory) PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager) Test(org.junit.jupiter.api.Test)

Aggregations

TransactionManager (org.springframework.transaction.TransactionManager)7 PlatformTransactionManager (org.springframework.transaction.PlatformTransactionManager)6 Test (org.junit.jupiter.api.Test)5 BeanFactory (org.springframework.beans.factory.BeanFactory)4 ReactiveTransactionManager (org.springframework.transaction.ReactiveTransactionManager)2 CallbackPreferringPlatformTransactionManager (org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager)2 Try (io.vavr.control.Try)1 Method (java.lang.reflect.Method)1 Properties (java.util.Properties)1 ConcurrentMap (java.util.concurrent.ConcurrentMap)1 Continuation (kotlin.coroutines.Continuation)1 AwaitKt (kotlinx.coroutines.reactive.AwaitKt)1 ReactiveFlowKt (kotlinx.coroutines.reactive.ReactiveFlowKt)1 Log (org.apache.commons.logging.Log)1 LogFactory (org.apache.commons.logging.LogFactory)1 Publisher (org.reactivestreams.Publisher)1 BeanFactoryAware (org.springframework.beans.factory.BeanFactoryAware)1 InitializingBean (org.springframework.beans.factory.InitializingBean)1 BeanFactoryAnnotationUtils (org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils)1 CoroutinesUtils (org.springframework.core.CoroutinesUtils)1