use of org.springframework.transaction.interceptor.TransactionAttribute in project spring-framework by spring-projects.
the class TransactionAspectTests method testDoesNotResolveTxAnnotationOnMethodFromClassImplementingAnnotatedInterface.
/**
* Note: resolution does not occur. Thus we can't make a class transactional if
* it implements a transactionally annotated interface. This behavior could only
* be changed in AbstractFallbackTransactionAttributeSource in Spring proper.
* See SPR-14322.
*/
@Test
public void testDoesNotResolveTxAnnotationOnMethodFromClassImplementingAnnotatedInterface() throws Exception {
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
Method method = ImplementsAnnotatedInterface.class.getMethod("echo", Throwable.class);
TransactionAttribute ta = atas.getTransactionAttribute(method, ImplementsAnnotatedInterface.class);
assertNull(ta);
}
use of org.springframework.transaction.interceptor.TransactionAttribute in project spring-framework by spring-projects.
the class SqlScriptsTestExecutionListener method executeSqlScripts.
/**
* Execute the SQL scripts configured via the supplied {@link Sql @Sql}
* annotation for the given {@link ExecutionPhase} and {@link TestContext}.
* <p>Special care must be taken in order to properly support the configured
* {@link SqlConfig#transactionMode}.
* @param sql the {@code @Sql} annotation to parse
* @param executionPhase the current execution phase
* @param testContext the current {@code TestContext}
* @param classLevel {@code true} if {@link Sql @Sql} was declared at the class level
*/
private void executeSqlScripts(Sql sql, ExecutionPhase executionPhase, TestContext testContext, boolean classLevel) throws Exception {
if (executionPhase != sql.executionPhase()) {
return;
}
MergedSqlConfig mergedSqlConfig = new MergedSqlConfig(sql.config(), testContext.getTestClass());
if (logger.isDebugEnabled()) {
logger.debug(String.format("Processing %s for execution phase [%s] and test context %s.", mergedSqlConfig, executionPhase, testContext));
}
final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setSqlScriptEncoding(mergedSqlConfig.getEncoding());
populator.setSeparator(mergedSqlConfig.getSeparator());
populator.setCommentPrefix(mergedSqlConfig.getCommentPrefix());
populator.setBlockCommentStartDelimiter(mergedSqlConfig.getBlockCommentStartDelimiter());
populator.setBlockCommentEndDelimiter(mergedSqlConfig.getBlockCommentEndDelimiter());
populator.setContinueOnError(mergedSqlConfig.getErrorMode() == ErrorMode.CONTINUE_ON_ERROR);
populator.setIgnoreFailedDrops(mergedSqlConfig.getErrorMode() == ErrorMode.IGNORE_FAILED_DROPS);
String[] scripts = getScripts(sql, testContext, classLevel);
scripts = TestContextResourceUtils.convertToClasspathResourcePaths(testContext.getTestClass(), scripts);
List<Resource> scriptResources = TestContextResourceUtils.convertToResourceList(testContext.getApplicationContext(), scripts);
for (String stmt : sql.statements()) {
if (StringUtils.hasText(stmt)) {
stmt = stmt.trim();
scriptResources.add(new ByteArrayResource(stmt.getBytes(), "from inlined SQL statement: " + stmt));
}
}
populator.setScripts(scriptResources.toArray(new Resource[scriptResources.size()]));
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL scripts: " + ObjectUtils.nullSafeToString(scriptResources));
}
String dsName = mergedSqlConfig.getDataSource();
String tmName = mergedSqlConfig.getTransactionManager();
DataSource dataSource = TestContextTransactionUtils.retrieveDataSource(testContext, dsName);
PlatformTransactionManager txMgr = TestContextTransactionUtils.retrieveTransactionManager(testContext, tmName);
boolean newTxRequired = (mergedSqlConfig.getTransactionMode() == TransactionMode.ISOLATED);
if (txMgr == null) {
Assert.state(!newTxRequired, () -> String.format("Failed to execute SQL scripts for test context %s: " + "cannot execute SQL scripts using Transaction Mode " + "[%s] without a PlatformTransactionManager.", testContext, TransactionMode.ISOLATED));
Assert.state(dataSource != null, () -> String.format("Failed to execute SQL scripts for test context %s: " + "supply at least a DataSource or PlatformTransactionManager.", testContext));
// Execute scripts directly against the DataSource
populator.execute(dataSource);
} else {
DataSource dataSourceFromTxMgr = getDataSourceFromTransactionManager(txMgr);
// Ensure user configured an appropriate DataSource/TransactionManager pair.
if (dataSource != null && dataSourceFromTxMgr != null && !dataSource.equals(dataSourceFromTxMgr)) {
throw new IllegalStateException(String.format("Failed to execute SQL scripts for test context %s: " + "the configured DataSource [%s] (named '%s') is not the one associated with " + "transaction manager [%s] (named '%s').", testContext, dataSource.getClass().getName(), dsName, txMgr.getClass().getName(), tmName));
}
if (dataSource == null) {
dataSource = dataSourceFromTxMgr;
Assert.state(dataSource != null, () -> String.format("Failed to execute SQL scripts for " + "test context %s: could not obtain DataSource from transaction manager [%s] (named '%s').", testContext, txMgr.getClass().getName(), tmName));
}
final DataSource finalDataSource = dataSource;
int propagation = (newTxRequired ? TransactionDefinition.PROPAGATION_REQUIRES_NEW : TransactionDefinition.PROPAGATION_REQUIRED);
TransactionAttribute txAttr = TestContextTransactionUtils.createDelegatingTransactionAttribute(testContext, new DefaultTransactionAttribute(propagation));
new TransactionTemplate(txMgr, txAttr).execute(status -> {
populator.execute(finalDataSource);
return null;
});
}
}
use of org.springframework.transaction.interceptor.TransactionAttribute in project spring-framework by spring-projects.
the class TransactionalTestExecutionListener method beforeTestMethod.
/**
* If the test method of the supplied {@linkplain TestContext test context}
* is configured to run within a transaction, this method will run
* {@link BeforeTransaction @BeforeTransaction} methods and start a new
* transaction.
* <p>Note that if a {@code @BeforeTransaction} method fails, any remaining
* {@code @BeforeTransaction} methods will not be invoked, and a transaction
* will not be started.
* @see org.springframework.transaction.annotation.Transactional
* @see #getTransactionManager(TestContext, String)
*/
@Override
public void beforeTestMethod(final TestContext testContext) throws Exception {
final Method testMethod = testContext.getTestMethod();
final Class<?> testClass = testContext.getTestClass();
Assert.notNull(testMethod, "The test method of the supplied TestContext must not be null");
TransactionContext txContext = TransactionContextHolder.removeCurrentTransactionContext();
Assert.state(txContext == null, "Cannot start a new transaction without ending the existing transaction.");
PlatformTransactionManager tm = null;
TransactionAttribute transactionAttribute = this.attributeSource.getTransactionAttribute(testMethod, testClass);
if (transactionAttribute != null) {
transactionAttribute = TestContextTransactionUtils.createDelegatingTransactionAttribute(testContext, transactionAttribute);
if (logger.isDebugEnabled()) {
logger.debug("Explicit transaction definition [" + transactionAttribute + "] found for test context " + testContext);
}
if (transactionAttribute.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
return;
}
tm = getTransactionManager(testContext, transactionAttribute.getQualifier());
Assert.state(tm != null, () -> String.format("Failed to retrieve PlatformTransactionManager for @Transactional test for test context %s.", testContext));
}
if (tm != null) {
txContext = new TransactionContext(testContext, tm, transactionAttribute, isRollback(testContext));
runBeforeTransactionMethods(testContext);
txContext.startTransaction();
TransactionContextHolder.setCurrentTransactionContext(txContext);
}
}
use of org.springframework.transaction.interceptor.TransactionAttribute in project spring-framework by spring-projects.
the class AnnotationTransactionAttributeSourceTests method customClassAttributeDetected.
@Test
public void customClassAttributeDetected() throws Exception {
Method method = TestBean5.class.getMethod("getAge");
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
TransactionAttribute actual = atas.getTransactionAttribute(method, TestBean5.class);
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
}
use of org.springframework.transaction.interceptor.TransactionAttribute in project spring-framework by spring-projects.
the class AnnotationTransactionAttributeSourceTests method transactionAttributeDeclaredOnClassMethodWithJta.
@Test
public void transactionAttributeDeclaredOnClassMethodWithJta() throws Exception {
Method getAgeMethod = ITestBean.class.getMethod("getAge");
Method getNameMethod = ITestBean.class.getMethod("getName");
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
TransactionAttribute getAgeAttr = atas.getTransactionAttribute(getAgeMethod, JtaAnnotatedBean1.class);
assertEquals(TransactionAttribute.PROPAGATION_REQUIRED, getAgeAttr.getPropagationBehavior());
TransactionAttribute getNameAttr = atas.getTransactionAttribute(getNameMethod, JtaAnnotatedBean1.class);
assertEquals(TransactionAttribute.PROPAGATION_SUPPORTS, getNameAttr.getPropagationBehavior());
}
Aggregations