Search in sources :

Example 6 with TransactionManager

use of cn.taketoday.transaction.TransactionManager in project today-framework by TAKETODAY.

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(cn.taketoday.transaction.TransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) BeanFactory(cn.taketoday.beans.factory.BeanFactory) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) Test(org.junit.jupiter.api.Test)

Example 7 with TransactionManager

use of cn.taketoday.transaction.TransactionManager in project today-framework by TAKETODAY.

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) {
        ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
            Class<?> reactiveType = 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);
        });
        return txSupport.invokeWithinTransaction(method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
    }
    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);
        }
        commitTransactionAfterReturning(txInfo);
        return retVal;
    } else {
        Object result;
        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 {
                    return invocation.proceedWithInvocation();
                } 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) {
                log.error("Application exception overridden by commit exception", throwableHolder.throwable);
                ex2.initApplicationException(throwableHolder.throwable);
            }
            throw ex2;
        } catch (Throwable ex2) {
            if (throwableHolder.throwable != null) {
                log.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 : StringUtils(cn.taketoday.util.StringUtils) Assert(cn.taketoday.lang.Assert) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) NoTransactionException(cn.taketoday.transaction.NoTransactionException) TransactionManager(cn.taketoday.transaction.TransactionManager) ClassUtils(cn.taketoday.util.ClassUtils) TransactionStatus(cn.taketoday.transaction.TransactionStatus) TransactionContextManager(cn.taketoday.transaction.reactive.TransactionContextManager) ConcurrentMap(java.util.concurrent.ConcurrentMap) Method(java.lang.reflect.Method) ReactiveTransaction(cn.taketoday.transaction.ReactiveTransaction) Properties(java.util.Properties) BeanFactoryAware(cn.taketoday.beans.factory.BeanFactoryAware) NamedThreadLocal(cn.taketoday.core.NamedThreadLocal) ConcurrentReferenceHashMap(cn.taketoday.util.ConcurrentReferenceHashMap) ReactiveAdapterRegistry(cn.taketoday.core.ReactiveAdapterRegistry) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) BeanFactory(cn.taketoday.beans.factory.BeanFactory) Mono(reactor.core.publisher.Mono) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) LoggerFactory(cn.taketoday.logging.LoggerFactory) Flux(reactor.core.publisher.Flux) BeanFactoryAnnotationUtils(cn.taketoday.beans.factory.annotation.BeanFactoryAnnotationUtils) ReactiveAdapter(cn.taketoday.core.ReactiveAdapter) Nullable(cn.taketoday.lang.Nullable) TransactionSystemException(cn.taketoday.transaction.TransactionSystemException) Logger(cn.taketoday.logging.Logger) InitializingBean(cn.taketoday.beans.factory.InitializingBean) TransactionSystemException(cn.taketoday.transaction.TransactionSystemException) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) TransactionManager(cn.taketoday.transaction.TransactionManager) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) ReactiveAdapter(cn.taketoday.core.ReactiveAdapter) Nullable(cn.taketoday.lang.Nullable)

Example 8 with TransactionManager

use of cn.taketoday.transaction.TransactionManager in project today-framework by TAKETODAY.

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, PlatformTransactionManager.class, qualifier);
        this.transactionManagerCache.putIfAbsent(qualifier, txManager);
    }
    return txManager;
}
Also used : CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) TransactionManager(cn.taketoday.transaction.TransactionManager) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager)

Example 9 with TransactionManager

use of cn.taketoday.transaction.TransactionManager in project today-framework by TAKETODAY.

the class TestContextTransactionUtils method retrieveTransactionManager.

/**
 * Retrieve the {@linkplain PlatformTransactionManager transaction manager}
 * to use for the supplied {@linkplain TestContext test context}.
 * <p>The following algorithm is used to retrieve the transaction manager
 * from the {@link cn.taketoday.context.ApplicationContext ApplicationContext}
 * of the supplied test context:
 * <ol>
 * <li>Look up the transaction manager by type and explicit name, if the supplied
 * {@code name} is non-empty, throwing a {@link BeansException} if the named
 * transaction manager does not exist.
 * <li>Attempt to look up the transaction manager via a
 * {@link TransactionManagementConfigurer}, if present.
 * <li>Attempt to look up the single transaction manager by type.
 * <li>Attempt to look up the <em>primary</em> transaction manager by type.
 * <li>Attempt to look up the transaction manager by type and the
 * {@linkplain #DEFAULT_TRANSACTION_MANAGER_NAME default transaction manager
 * name}.
 * </ol>
 *
 * @param testContext the test context for which the transaction manager
 * should be retrieved; never {@code null}
 * @param name the name of the transaction manager to retrieve
 * (may be {@code null} or <em>empty</em>)
 * @return the transaction manager to use, or {@code null} if not found
 * @throws BeansException if an error occurs while retrieving an explicitly
 * named transaction manager
 * @throws IllegalStateException if more than one TransactionManagementConfigurer
 * exists in the ApplicationContext
 */
@Nullable
public static PlatformTransactionManager retrieveTransactionManager(TestContext testContext, @Nullable String name) {
    Assert.notNull(testContext, "TestContext must not be null");
    BeanFactory bf = testContext.getApplicationContext().getAutowireCapableBeanFactory();
    try {
        // Look up by type and explicit name
        if (StringUtils.hasText(name)) {
            return bf.getBean(name, PlatformTransactionManager.class);
        }
    } catch (BeansException ex) {
        logger.error("Failed to retrieve transaction manager named '{}' for test context {}", name, testContext, ex);
        throw ex;
    }
    try {
        // Look up single TransactionManagementConfigurer
        Map<String, TransactionManagementConfigurer> configurers = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, TransactionManagementConfigurer.class);
        Assert.state(configurers.size() <= 1, "Only one TransactionManagementConfigurer may exist in the ApplicationContext");
        if (configurers.size() == 1) {
            TransactionManager tm = configurers.values().iterator().next().annotationDrivenTransactionManager();
            Assert.state(tm instanceof PlatformTransactionManager, () -> "Transaction manager specified via TransactionManagementConfigurer " + "is not a PlatformTransactionManager: " + tm);
            return (PlatformTransactionManager) tm;
        }
        // Look up single bean by type
        Map<String, PlatformTransactionManager> txMgrs = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, PlatformTransactionManager.class);
        if (txMgrs.size() == 1) {
            return txMgrs.values().iterator().next();
        }
        try {
            // Look up single bean by type, with support for 'primary' beans
            return bf.getBean(PlatformTransactionManager.class);
        } catch (BeansException ex) {
            logBeansException(testContext, ex, PlatformTransactionManager.class);
        }
        // look up by type and default name
        return bf.getBean(DEFAULT_TRANSACTION_MANAGER_NAME, PlatformTransactionManager.class);
    } catch (BeansException ex) {
        logBeansException(testContext, ex, PlatformTransactionManager.class);
        return null;
    }
}
Also used : TransactionManager(cn.taketoday.transaction.TransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) BeanFactory(cn.taketoday.beans.factory.BeanFactory) TransactionManagementConfigurer(cn.taketoday.transaction.annotation.TransactionManagementConfigurer) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) BeansException(cn.taketoday.beans.BeansException) Nullable(cn.taketoday.lang.Nullable)

Example 10 with TransactionManager

use of cn.taketoday.transaction.TransactionManager in project today-infrastructure by TAKETODAY.

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) {
        ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
            Class<?> reactiveType = 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);
        });
        return txSupport.invokeWithinTransaction(method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
    }
    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);
        }
        commitTransactionAfterReturning(txInfo);
        return retVal;
    } else {
        Object result;
        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 {
                    return invocation.proceedWithInvocation();
                } 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) {
                log.error("Application exception overridden by commit exception", throwableHolder.throwable);
                ex2.initApplicationException(throwableHolder.throwable);
            }
            throw ex2;
        } catch (Throwable ex2) {
            if (throwableHolder.throwable != null) {
                log.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 : StringUtils(cn.taketoday.util.StringUtils) Assert(cn.taketoday.lang.Assert) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) NoTransactionException(cn.taketoday.transaction.NoTransactionException) TransactionManager(cn.taketoday.transaction.TransactionManager) ClassUtils(cn.taketoday.util.ClassUtils) TransactionStatus(cn.taketoday.transaction.TransactionStatus) TransactionContextManager(cn.taketoday.transaction.reactive.TransactionContextManager) ConcurrentMap(java.util.concurrent.ConcurrentMap) Method(java.lang.reflect.Method) ReactiveTransaction(cn.taketoday.transaction.ReactiveTransaction) Properties(java.util.Properties) BeanFactoryAware(cn.taketoday.beans.factory.BeanFactoryAware) NamedThreadLocal(cn.taketoday.core.NamedThreadLocal) ConcurrentReferenceHashMap(cn.taketoday.util.ConcurrentReferenceHashMap) ReactiveAdapterRegistry(cn.taketoday.core.ReactiveAdapterRegistry) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) BeanFactory(cn.taketoday.beans.factory.BeanFactory) Mono(reactor.core.publisher.Mono) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) LoggerFactory(cn.taketoday.logging.LoggerFactory) Flux(reactor.core.publisher.Flux) BeanFactoryAnnotationUtils(cn.taketoday.beans.factory.annotation.BeanFactoryAnnotationUtils) ReactiveAdapter(cn.taketoday.core.ReactiveAdapter) Nullable(cn.taketoday.lang.Nullable) TransactionSystemException(cn.taketoday.transaction.TransactionSystemException) Logger(cn.taketoday.logging.Logger) InitializingBean(cn.taketoday.beans.factory.InitializingBean) TransactionSystemException(cn.taketoday.transaction.TransactionSystemException) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) CallbackPreferringPlatformTransactionManager(cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager) TransactionManager(cn.taketoday.transaction.TransactionManager) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) ReactiveTransactionManager(cn.taketoday.transaction.ReactiveTransactionManager) ReactiveAdapter(cn.taketoday.core.ReactiveAdapter) Nullable(cn.taketoday.lang.Nullable)

Aggregations

PlatformTransactionManager (cn.taketoday.transaction.PlatformTransactionManager)12 TransactionManager (cn.taketoday.transaction.TransactionManager)12 BeanFactory (cn.taketoday.beans.factory.BeanFactory)10 Test (org.junit.jupiter.api.Test)6 Nullable (cn.taketoday.lang.Nullable)4 ReactiveTransactionManager (cn.taketoday.transaction.ReactiveTransactionManager)4 CallbackPreferringPlatformTransactionManager (cn.taketoday.transaction.support.CallbackPreferringPlatformTransactionManager)4 BeansException (cn.taketoday.beans.BeansException)2 BeanFactoryAware (cn.taketoday.beans.factory.BeanFactoryAware)2 InitializingBean (cn.taketoday.beans.factory.InitializingBean)2 BeanFactoryAnnotationUtils (cn.taketoday.beans.factory.annotation.BeanFactoryAnnotationUtils)2 NamedThreadLocal (cn.taketoday.core.NamedThreadLocal)2 ReactiveAdapter (cn.taketoday.core.ReactiveAdapter)2 ReactiveAdapterRegistry (cn.taketoday.core.ReactiveAdapterRegistry)2 Assert (cn.taketoday.lang.Assert)2 Logger (cn.taketoday.logging.Logger)2 LoggerFactory (cn.taketoday.logging.LoggerFactory)2 NoTransactionException (cn.taketoday.transaction.NoTransactionException)2 ReactiveTransaction (cn.taketoday.transaction.ReactiveTransaction)2 TransactionStatus (cn.taketoday.transaction.TransactionStatus)2