diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/AbstractJobRepositoryFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/AbstractJobRepositoryFactoryBean.java index 57a081ac2..df7d4b2de 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/AbstractJobRepositoryFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/AbstractJobRepositoryFactoryBean.java @@ -1,19 +1,11 @@ package org.springframework.batch.core.repository.support; -import org.springframework.aop.framework.ProxyFactory; -import org.springframework.aop.support.DefaultPointcutAdvisor; -import org.springframework.aop.support.NameMatchMethodPointcut; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.dao.ExecutionContextDao; import org.springframework.batch.core.repository.dao.JobExecutionDao; import org.springframework.batch.core.repository.dao.JobInstanceDao; import org.springframework.batch.core.repository.dao.StepExecutionDao; -import org.springframework.batch.support.PropertiesConverter; import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.interceptor.TransactionInterceptor; -import org.springframework.util.Assert; /** * A {@link FactoryBean} that automates the creation of a @@ -27,18 +19,7 @@ import org.springframework.util.Assert; * @author Lucas Ward * @author Robert Kasanicky */ -public abstract class AbstractJobRepositoryFactoryBean implements FactoryBean, InitializingBean { - - /** - * Default value for isolation level in create* method. - */ - private static final String DEFAULT_ISOLATION_LEVEL = "ISOLATION_SERIALIZABLE"; - - private ProxyFactory proxyFactory; - - private String isolationLevelForCreate = DEFAULT_ISOLATION_LEVEL; - - private PlatformTransactionManager transactionManager; +public abstract class AbstractJobRepositoryFactoryBean implements FactoryBean { /** * @return fully configured {@link JobInstanceDao} implementation. @@ -60,10 +41,6 @@ public abstract class AbstractJobRepositoryFactoryBean implements FactoryBean, I */ protected abstract ExecutionContextDao createExecutionContextDao() throws Exception; - public Object getObject() throws Exception { - return proxyFactory.getProxy(); - } - /** * The type of object to be returned from {@link #getObject()}. * @@ -78,53 +55,4 @@ public abstract class AbstractJobRepositoryFactoryBean implements FactoryBean, I return true; } - public void afterPropertiesSet() throws Exception { - - Assert.notNull(transactionManager, "TransactionManager must not be null."); - - initializeProxy(); - } - - protected void initializeProxy() throws Exception { - proxyFactory = new ProxyFactory(); - TransactionInterceptor advice = new TransactionInterceptor(transactionManager, PropertiesConverter - .stringToProperties("create*=PROPAGATION_REQUIRES_NEW," + isolationLevelForCreate - + "\n*=PROPAGATION_REQUIRED")); - DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(advice); - NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut(); - pointcut.addMethodName("*"); - advisor.setPointcut(pointcut); - proxyFactory.addAdvisor(advisor); - proxyFactory.setProxyTargetClass(false); - proxyFactory.addInterface(JobRepository.class); - proxyFactory.setTarget(getTarget()); - } - - private Object getTarget() throws Exception { - return new SimpleJobRepository(createJobInstanceDao(), createJobExecutionDao(), createStepExecutionDao(), createExecutionContextDao()); - } - - /** - * Public setter for the {@link PlatformTransactionManager}. - * @param transactionManager the transactionManager to set - */ - public void setTransactionManager(PlatformTransactionManager transactionManager) { - this.transactionManager = transactionManager; - } - - /** - * Public setter for the isolation level to be used for the transaction when - * job execution entities are initially created. The default is - * ISOLATION_SERIALIZABLE, which prevents accidental concurrent execution of - * the same job (ISOLATION_REPEATABLE_READ would work as well). - * - * @param isolationLevelForCreate the isolation level name to set - * - * @see SimpleJobRepository#createJobExecution(org.springframework.batch.core.Job, - * org.springframework.batch.core.JobParameters) - */ - public void setIsolationLevelForCreate(String isolationLevelForCreate) { - this.isolationLevelForCreate = isolationLevelForCreate; - } - } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java index c242b4a2d..d1cb46e63 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java @@ -18,6 +18,10 @@ package org.springframework.batch.core.repository.support; import javax.sql.DataSource; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.aop.support.DefaultPointcutAdvisor; +import org.springframework.aop.support.NameMatchMethodPointcut; +import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao; import org.springframework.batch.core.repository.dao.ExecutionContextDao; import org.springframework.batch.core.repository.dao.JdbcExecutionContextDao; @@ -29,9 +33,13 @@ import org.springframework.batch.core.repository.dao.JobInstanceDao; import org.springframework.batch.core.repository.dao.StepExecutionDao; import org.springframework.batch.item.database.support.DataFieldMaxValueIncrementerFactory; import org.springframework.batch.item.database.support.DefaultDataFieldMaxValueIncrementerFactory; +import org.springframework.batch.support.PropertiesConverter; import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; import org.springframework.jdbc.core.simple.SimpleJdbcOperations; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.interceptor.TransactionInterceptor; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -44,7 +52,16 @@ import org.springframework.util.StringUtils; * @author Ben Hale * @author Lucas Ward */ -public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean { +public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean implements InitializingBean { + + /** + * Default value for isolation level in create* method. + */ + private static final String DEFAULT_ISOLATION_LEVEL = "ISOLATION_SERIALIZABLE"; + + private ProxyFactory proxyFactory; + + private String isolationLevelForCreate = DEFAULT_ISOLATION_LEVEL; private DataSource dataSource; @@ -55,7 +72,32 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean { private String tablePrefix = AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX; private DataFieldMaxValueIncrementerFactory incrementerFactory; + + private PlatformTransactionManager transactionManager; + /** + * Public setter for the isolation level to be used for the transaction when + * job execution entities are initially created. The default is + * ISOLATION_SERIALIZABLE, which prevents accidental concurrent execution of + * the same job (ISOLATION_REPEATABLE_READ would work as well). + * + * @param isolationLevelForCreate the isolation level name to set + * + * @see SimpleJobRepository#createJobExecution(org.springframework.batch.core.Job, + * org.springframework.batch.core.JobParameters) + */ + public void setIsolationLevelForCreate(String isolationLevelForCreate) { + this.isolationLevelForCreate = isolationLevelForCreate; + } + + /** + * Public setter for the {@link PlatformTransactionManager}. + * @param transactionManager the transactionManager to set + */ + public void setTransactionManager(PlatformTransactionManager transactionManager) { + this.transactionManager = transactionManager; + } + /** * Public setter for the {@link DataSource}. * @param dataSource a {@link DataSource} @@ -86,7 +128,9 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean { public void afterPropertiesSet() throws Exception { + Assert.notNull(transactionManager, "TransactionManager must not be null."); Assert.notNull(dataSource, "DataSource must not be null."); + jdbcTemplate = new SimpleJdbcTemplate(dataSource); if (incrementerFactory == null) { @@ -96,10 +140,31 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean { Assert.isTrue(incrementerFactory.isSupportedIncrementerType(databaseType), "'" + databaseType + "' is an unsupported database type. The supported database types are " + StringUtils.arrayToCommaDelimitedString(incrementerFactory.getSupportedIncrementerTypes())); + + initializeProxy(); - super.afterPropertiesSet(); + } + + protected void initializeProxy() throws Exception { + proxyFactory = new ProxyFactory(); + TransactionInterceptor advice = new TransactionInterceptor(transactionManager, PropertiesConverter + .stringToProperties("create*=PROPAGATION_REQUIRES_NEW," + isolationLevelForCreate + + "\n*=PROPAGATION_REQUIRED")); + DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(advice); + NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut(); + pointcut.addMethodName("*"); + advisor.setPointcut(pointcut); + proxyFactory.addAdvisor(advisor); + proxyFactory.setProxyTargetClass(false); + proxyFactory.addInterface(JobRepository.class); + proxyFactory.setTarget(getTarget()); + } + + private Object getTarget() throws Exception { + return new SimpleJobRepository(createJobInstanceDao(), createJobExecutionDao(), createStepExecutionDao(), createExecutionContextDao()); } + @Override protected JobInstanceDao createJobInstanceDao() throws Exception { JdbcJobInstanceDao dao = new JdbcJobInstanceDao(); dao.setJdbcTemplate(jdbcTemplate); @@ -109,6 +174,7 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean { return dao; } + @Override protected JobExecutionDao createJobExecutionDao() throws Exception { JdbcJobExecutionDao dao = new JdbcJobExecutionDao(); dao.setJdbcTemplate(jdbcTemplate); @@ -121,6 +187,7 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean { return dao; } + @Override protected StepExecutionDao createStepExecutionDao() throws Exception { JdbcStepExecutionDao dao = new JdbcStepExecutionDao(); dao.setJdbcTemplate(jdbcTemplate); @@ -139,4 +206,8 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean { dao.afterPropertiesSet(); return dao; } + + public Object getObject() throws Exception { + return proxyFactory.getProxy(); + } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBean.java index 45b9d1d75..70122ee09 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBean.java @@ -19,14 +19,17 @@ import org.springframework.beans.factory.FactoryBean; */ public class MapJobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean { + @Override protected JobExecutionDao createJobExecutionDao() throws Exception { return new MapJobExecutionDao(); } + @Override protected JobInstanceDao createJobInstanceDao() throws Exception { return new MapJobInstanceDao(); } + @Override protected StepExecutionDao createStepExecutionDao() throws Exception { return new MapStepExecutionDao(); } @@ -36,4 +39,9 @@ public class MapJobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBea return new MapExecutionContextDao(); } + public Object getObject() throws Exception { + return new SimpleJobRepository(createJobInstanceDao(), createJobExecutionDao(), createStepExecutionDao(), + createExecutionContextDao()); + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBeanTests.java index c197abe3b..5247c9218 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBeanTests.java @@ -1,33 +1,24 @@ package org.springframework.batch.core.repository.support; -import junit.framework.TestCase; - +import org.junit.Test; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.job.JobSupport; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.JobRestartException; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; -import org.springframework.transaction.PlatformTransactionManager; /** * Tests for {@link MapJobRepositoryFactoryBean}. */ -public class MapJobRepositoryFactoryBeanTests extends TestCase { +public class MapJobRepositoryFactoryBeanTests { private MapJobRepositoryFactoryBean tested = new MapJobRepositoryFactoryBean(); - private PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); - - protected void setUp() throws Exception { - tested.setTransactionManager(transactionManager); - tested.afterPropertiesSet(); - } - /** * Use the factory to create repository and check the repository remembers * created executions. */ + @Test public void testCreateRepository() throws Exception { JobRepository repository = (JobRepository) tested.getObject(); Job job = new JobSupport("jobName"); diff --git a/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml b/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml index 3c56f9d32..100d46630 100644 --- a/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml +++ b/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml @@ -1,31 +1,29 @@ - - - - - + + - - - - - + + - - - - - + + \ No newline at end of file