REOPENED - BATCH-778: MapJobRepositoryFactoryBean shouldn't require transactionManager

tx code moved from AbstractJobRepositoryFactoryBean to JobRepositoryFactoryBean
This commit is contained in:
robokaso
2008-08-13 10:52:45 +00:00
parent b9810c6eeb
commit 1f731769f8
5 changed files with 102 additions and 106 deletions

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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());
}
}

View File

@@ -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");

View File

@@ -1,31 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<import resource="data-source-context.xml" />
<import resource="classpath:/org/springframework/batch/sample/config/common-context.xml" />
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<import
resource="classpath:/org/springframework/batch/sample/config/common-context.xml" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
p:databaseType="${environment}" p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager"/>
<bean id="mapJobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"
p:transactionManager-ref="transactionManager" lazy-init="true" autowire-candidate="false" />
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
p:databaseType="${environment}" p:dataSource-ref="dataSource"
p:transactionManager-ref="transactionManager" />
<bean id="mapJobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"
lazy-init="true" autowire-candidate="false" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="logAdvice" class="org.springframework.batch.sample.common.LogAdvice" />
<bean id="eventAdvice" class="org.springframework.batch.sample.jmx.StepExecutionApplicationEventAdvice" />
</beans>
<bean id="eventAdvice"
class="org.springframework.batch.sample.jmx.StepExecutionApplicationEventAdvice" />
</beans>