Allow the transaction manager to be overridden in DefaultBatchConfigurer
Before this commit, it was not possible to override the transaction manager by subclassing DefaultBatchConfigurer and overriding the getTransactionManager method. This commit uses the getTransactionManager method in the initialize method in order to take into account the transaction manager provided by the user. Resolves BATCH-2294
This commit is contained in:
committed by
Michael Minella
parent
e83ed1db11
commit
a68d70043a
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.batch.core.configuration.annotation;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
|
||||
/**
|
||||
* @author Mahmoud Ben Hassine
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public abstract class TransactionManagerConfigurationTests {
|
||||
|
||||
@Mock
|
||||
protected static PlatformTransactionManager transactionManager;
|
||||
|
||||
@Mock
|
||||
protected static PlatformTransactionManager transactionManager2;
|
||||
|
||||
/*
|
||||
* The transaction manager set on JobRepositoryFactoryBean in DefaultBatchConfigurer.createJobRepository
|
||||
* ends up in the TransactionInterceptor advise applied to the (proxied) JobRepository.
|
||||
* This method extracts the advise from the proxy and returns the transaction manager.
|
||||
*/
|
||||
PlatformTransactionManager getTransactionManagerSetOnJobRepository(JobRepository jobRepository) throws Exception {
|
||||
TargetSource targetSource = ((Advised) jobRepository).getTargetSource(); // proxy created in SimpleBatchConfiguration.createLazyProxy
|
||||
Advised target = (Advised) targetSource.getTarget(); // initial proxy created in AbstractJobRepositoryFactoryBean.initializeProxy
|
||||
Advisor[] advisors = target.getAdvisors();
|
||||
for (Advisor advisor : advisors) {
|
||||
if (advisor.getAdvice() instanceof TransactionInterceptor) {
|
||||
TransactionInterceptor transactionInterceptor = (TransactionInterceptor) advisor.getAdvice();
|
||||
return transactionInterceptor.getTransactionManager();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static DataSource createDataSource() {
|
||||
return new EmbeddedDatabaseBuilder()
|
||||
.addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql")
|
||||
.addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.batch.core.configuration.annotation;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.test.util.AopTestUtils;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* @author Mahmoud Ben Hassine
|
||||
*/
|
||||
public class TransactionManagerConfigurationWithBatchConfigurerTests extends TransactionManagerConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void testConfigurationWithNoDataSourceAndNoTransactionManager() throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithNoDataSourceAndNoTransactionManager.class);
|
||||
BatchConfigurer batchConfigurer = applicationContext.getBean(BatchConfigurer.class);
|
||||
|
||||
PlatformTransactionManager platformTransactionManager = batchConfigurer.getTransactionManager();
|
||||
Assert.assertTrue(platformTransactionManager instanceof ResourcelessTransactionManager);
|
||||
Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), platformTransactionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigurationWithNoDataSourceAndTransactionManager() throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithNoDataSourceAndTransactionManager.class);
|
||||
BatchConfigurer batchConfigurer = applicationContext.getBean(BatchConfigurer.class);
|
||||
|
||||
PlatformTransactionManager platformTransactionManager = batchConfigurer.getTransactionManager();
|
||||
Assert.assertSame(transactionManager, platformTransactionManager);
|
||||
Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), transactionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigurationWithDataSourceAndNoTransactionManager() throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndNoTransactionManager.class);
|
||||
BatchConfigurer batchConfigurer = applicationContext.getBean(BatchConfigurer.class);
|
||||
|
||||
PlatformTransactionManager platformTransactionManager = batchConfigurer.getTransactionManager();
|
||||
Assert.assertTrue(platformTransactionManager instanceof DataSourceTransactionManager);
|
||||
DataSourceTransactionManager dataSourceTransactionManager = AopTestUtils.getTargetObject(platformTransactionManager);
|
||||
Assert.assertEquals(applicationContext.getBean(DataSource.class), dataSourceTransactionManager.getDataSource());
|
||||
Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), platformTransactionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigurationWithDataSourceAndTransactionManager() throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndTransactionManager.class);
|
||||
BatchConfigurer batchConfigurer = applicationContext.getBean(BatchConfigurer.class);
|
||||
|
||||
PlatformTransactionManager platformTransactionManager = batchConfigurer.getTransactionManager();
|
||||
Assert.assertSame(transactionManager, platformTransactionManager);
|
||||
Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), transactionManager);
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
public static class BatchConfigurationWithNoDataSourceAndNoTransactionManager {
|
||||
@Bean
|
||||
public BatchConfigurer batchConfigurer() {
|
||||
return new DefaultBatchConfigurer();
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
public static class BatchConfigurationWithNoDataSourceAndTransactionManager {
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BatchConfigurer batchConfigurer() {
|
||||
return new DefaultBatchConfigurer() {
|
||||
@Override
|
||||
public PlatformTransactionManager getTransactionManager() {
|
||||
return transactionManager();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
public static class BatchConfigurationWithDataSourceAndNoTransactionManager {
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return createDataSource();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BatchConfigurer batchConfigurer(DataSource dataSource) {
|
||||
return new DefaultBatchConfigurer(dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
public static class BatchConfigurationWithDataSourceAndTransactionManager {
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return createDataSource();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BatchConfigurer batchConfigurer(DataSource dataSource) {
|
||||
return new DefaultBatchConfigurer(dataSource) {
|
||||
@Override
|
||||
public PlatformTransactionManager getTransactionManager() {
|
||||
return transactionManager();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.batch.core.configuration.annotation;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.test.util.AopTestUtils;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* @author Mahmoud Ben Hassine
|
||||
*/
|
||||
public class TransactionManagerConfigurationWithoutBatchConfigurerTests extends TransactionManagerConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void testConfigurationWithNoDataSourceAndNoTransactionManager() throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithNoDataSourceAndNoTransactionManager.class);
|
||||
Assert.assertTrue(applicationContext.containsBean("transactionManager"));
|
||||
PlatformTransactionManager platformTransactionManager = applicationContext.getBean(PlatformTransactionManager.class);
|
||||
Object targetObject = AopTestUtils.getTargetObject(platformTransactionManager);
|
||||
Assert.assertTrue(targetObject instanceof ResourcelessTransactionManager);
|
||||
Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), targetObject);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigurationWithNoDataSourceAndTransactionManager() throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithNoDataSourceAndTransactionManager.class);
|
||||
PlatformTransactionManager platformTransactionManager = applicationContext.getBean(PlatformTransactionManager.class);
|
||||
Assert.assertSame(transactionManager, platformTransactionManager);
|
||||
// In this case, the supplied transaction manager won't be used by batch and a ResourcelessTransactionManager will be used instead.
|
||||
// The user has to provide a custom BatchConfigurer.
|
||||
Assert.assertTrue(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)) instanceof ResourcelessTransactionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigurationWithDataSourceAndNoTransactionManager() throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndNoTransactionManager.class);
|
||||
Assert.assertTrue(applicationContext.containsBean("transactionManager"));
|
||||
PlatformTransactionManager platformTransactionManager = applicationContext.getBean(PlatformTransactionManager.class);
|
||||
Object targetObject = AopTestUtils.getTargetObject(platformTransactionManager);
|
||||
Assert.assertTrue(targetObject instanceof DataSourceTransactionManager);
|
||||
DataSourceTransactionManager dataSourceTransactionManager = (DataSourceTransactionManager) targetObject;
|
||||
Assert.assertEquals(applicationContext.getBean(DataSource.class), dataSourceTransactionManager.getDataSource());
|
||||
Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), dataSourceTransactionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigurationWithDataSourceAndOneTransactionManager() throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndOneTransactionManager.class);
|
||||
PlatformTransactionManager platformTransactionManager = applicationContext.getBean(PlatformTransactionManager.class);
|
||||
Assert.assertSame(transactionManager, platformTransactionManager);
|
||||
// In this case, the supplied transaction manager won't be used by batch and a DataSourceTransactionManager will be used instead.
|
||||
// The user has to provide a custom BatchConfigurer.
|
||||
Assert.assertTrue(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)) instanceof DataSourceTransactionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigurationWithDataSourceAndMultipleTransactionManagers() throws Exception {
|
||||
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndMultipleTransactionManagers.class);
|
||||
PlatformTransactionManager platformTransactionManager = applicationContext.getBean(PlatformTransactionManager.class);
|
||||
Assert.assertSame(transactionManager2, platformTransactionManager);
|
||||
// In this case, the supplied primary transaction manager won't be used by batch and a DataSourceTransactionManager will be used instead.
|
||||
// The user has to provide a custom BatchConfigurer.
|
||||
Assert.assertTrue(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)) instanceof DataSourceTransactionManager);
|
||||
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
public static class BatchConfigurationWithNoDataSourceAndNoTransactionManager {
|
||||
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
public static class BatchConfigurationWithNoDataSourceAndTransactionManager {
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return transactionManager;
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
public static class BatchConfigurationWithDataSourceAndNoTransactionManager {
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return createDataSource();
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
public static class BatchConfigurationWithDataSourceAndOneTransactionManager {
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return createDataSource();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return transactionManager;
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBatchProcessing
|
||||
public static class BatchConfigurationWithDataSourceAndMultipleTransactionManagers {
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return createDataSource();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager2() {
|
||||
return transactionManager2;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user