RESOLVED - issue BATCH-680: Allow override of Transaction Definition in get transaction in Item Oriented Step
Added transactionAttribute to ItemOrientedStep and the factory bean
This commit is contained in:
@@ -19,6 +19,7 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
@@ -30,6 +31,7 @@ import org.springframework.batch.core.converter.DefaultJobParametersConverter;
|
||||
import org.springframework.batch.core.converter.JobParametersConverter;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.repository.NoSuchJobException;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.support.PropertiesConverter;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -104,10 +106,10 @@ public class SimpleExportedJobLauncher implements ExportedJobLauncher, Initializ
|
||||
int i = 0;
|
||||
for (Iterator iterator = execution.getStepExecutions().iterator(); iterator.hasNext();) {
|
||||
StepExecution stepExecution = (StepExecution) iterator.next();
|
||||
Properties statistics = stepExecution.getExecutionContext().getProperties();
|
||||
for (Iterator iter = statistics.keySet().iterator(); iter.hasNext();) {
|
||||
String key = (String) iter.next();
|
||||
result.setProperty(prefix + "step" + i + "." + key, statistics.getProperty(key));
|
||||
ExecutionContext statistics = stepExecution.getExecutionContext();
|
||||
for (Iterator iter = statistics.entrySet().iterator(); iter.hasNext();) {
|
||||
Entry entry = (Entry) iter.next();
|
||||
result.setProperty(prefix + "step" + i + "." + entry.getKey(), ""+entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.batch.item.validator.Validator;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -53,6 +54,8 @@ public abstract class AbstractStepFactoryBean implements FactoryBean, BeanNameAw
|
||||
private ItemWriter itemWriter;
|
||||
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
private TransactionAttribute transactionAttribute;
|
||||
|
||||
private JobRepository jobRepository;
|
||||
|
||||
@@ -185,6 +188,14 @@ public abstract class AbstractStepFactoryBean implements FactoryBean, BeanNameAw
|
||||
this.transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link TransactionAttribute}.
|
||||
* @param transactionAttribute the {@link TransactionAttribute} to set
|
||||
*/
|
||||
public void setTransactionAttribute(TransactionAttribute transactionAttribute) {
|
||||
this.transactionAttribute = transactionAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Step} from the configuration provided.
|
||||
*
|
||||
@@ -209,6 +220,9 @@ public abstract class AbstractStepFactoryBean implements FactoryBean, BeanNameAw
|
||||
|
||||
step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter));
|
||||
step.setTransactionManager(transactionManager);
|
||||
if (transactionAttribute!=null) {
|
||||
step.setTransactionAttribute(transactionAttribute);
|
||||
}
|
||||
step.setJobRepository(jobRepository);
|
||||
step.setStartLimit(startLimit);
|
||||
step.setAllowStartIfComplete(allowStartIfComplete);
|
||||
|
||||
@@ -40,7 +40,8 @@ import org.springframework.batch.repeat.RepeatOperations;
|
||||
import org.springframework.batch.repeat.support.RepeatTemplate;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
|
||||
/**
|
||||
* Simple implementation of executing the step as a set of chunks, each chunk
|
||||
@@ -78,6 +79,8 @@ public class ItemOrientedStep extends AbstractStep {
|
||||
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
private TransactionAttribute transactionAttribute = new DefaultTransactionAttribute();
|
||||
|
||||
private ItemHandler itemHandler;
|
||||
|
||||
private StepExecutionSynchronizer synchronizer;
|
||||
@@ -98,7 +101,15 @@ public class ItemOrientedStep extends AbstractStep {
|
||||
public void setTransactionManager(PlatformTransactionManager transactionManager) {
|
||||
this.transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Public setter for the {@link TransactionAttribute}.
|
||||
* @param transactionAttribute the {@link TransactionAttribute} to set
|
||||
*/
|
||||
public void setTransactionAttribute(TransactionAttribute transactionAttribute) {
|
||||
this.transactionAttribute = transactionAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link ItemHandler}.
|
||||
*
|
||||
@@ -230,7 +241,7 @@ public class ItemOrientedStep extends AbstractStep {
|
||||
|
||||
ExitStatus exitStatus = ExitStatus.CONTINUABLE;
|
||||
|
||||
TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
|
||||
TransactionStatus transaction = transactionManager.getTransaction(transactionAttribute);
|
||||
|
||||
try {
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.springframework.batch.core.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@@ -102,10 +101,10 @@ public class AbstractStepTests extends TestCase {
|
||||
*/
|
||||
private static class JobRepositoryStub extends JobRepositorySupport {
|
||||
|
||||
Properties saved = new Properties();
|
||||
ExecutionContext saved = new ExecutionContext();
|
||||
|
||||
public void saveOrUpdateExecutionContext(StepExecution stepExecution) {
|
||||
saved = stepExecution.getExecutionContext().getProperties();
|
||||
saved = stepExecution.getExecutionContext();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,20 +36,35 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
public class InitializingDataSourceFactoryBean extends AbstractFactoryBean {
|
||||
|
||||
private Resource initScript;
|
||||
private Resource[] initScripts;
|
||||
|
||||
private Resource destroyScript;
|
||||
|
||||
DataSource dataSource;
|
||||
|
||||
public void destroy() throws Exception {
|
||||
super.destroy();
|
||||
private static boolean initialized = false;
|
||||
|
||||
/**
|
||||
* @throws Throwable
|
||||
* @see java.lang.Object#finalize()
|
||||
*/
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
initialized = false;
|
||||
logger.debug("finalize called");
|
||||
}
|
||||
|
||||
protected void destroyInstance(Object instance) throws Exception {
|
||||
try {
|
||||
doExecuteScript(destroyScript);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Could not execute destroy script [" + destroyScript + "]", e);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn("Could not execute destroy script [" + destroyScript + "]", e);
|
||||
}
|
||||
else {
|
||||
logger.warn("Could not execute destroy script [" + destroyScript + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,13 +75,21 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean {
|
||||
|
||||
protected Object createInstance() throws Exception {
|
||||
Assert.notNull(dataSource);
|
||||
try {
|
||||
doExecuteScript(destroyScript);
|
||||
if (!initialized) {
|
||||
try {
|
||||
doExecuteScript(destroyScript);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.debug("Could not execute destroy script [" + destroyScript + "]", e);
|
||||
}
|
||||
if (initScripts != null) {
|
||||
for (int i = 0; i < initScripts.length; i++) {
|
||||
Resource initScript = initScripts[i];
|
||||
doExecuteScript(initScript);
|
||||
}
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.debug("Could not execute destroy script [" + destroyScript + "]", e);
|
||||
}
|
||||
doExecuteScript(initScript);
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@@ -74,31 +97,29 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean {
|
||||
if (scriptResource == null || !scriptResource.exists())
|
||||
return;
|
||||
TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
|
||||
if (initScript != null) {
|
||||
transactionTemplate.execute(new TransactionCallback() {
|
||||
transactionTemplate.execute(new TransactionCallback() {
|
||||
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
String[] scripts;
|
||||
try {
|
||||
scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource
|
||||
.getInputStream())), ";");
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BeanInitializationException("Cannot load script from [" + initScript + "]", e);
|
||||
}
|
||||
for (int i = 0; i < scripts.length; i++) {
|
||||
String script = scripts[i].trim();
|
||||
if (StringUtils.hasText(script)) {
|
||||
jdbcTemplate.execute(scripts[i]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
String[] scripts;
|
||||
try {
|
||||
scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource
|
||||
.getInputStream())), ";");
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e);
|
||||
}
|
||||
for (int i = 0; i < scripts.length; i++) {
|
||||
String script = scripts[i].trim();
|
||||
if (StringUtils.hasText(script)) {
|
||||
jdbcTemplate.execute(scripts[i]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String stripComments(List list) {
|
||||
@@ -116,8 +137,8 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean {
|
||||
return DataSource.class;
|
||||
}
|
||||
|
||||
public void setInitScript(Resource initScript) {
|
||||
this.initScript = initScript;
|
||||
public void setInitScripts(Resource[] initScripts) {
|
||||
this.initScripts = initScripts;
|
||||
}
|
||||
|
||||
public void setDestroyScript(Resource destroyScript) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<bean id="dataSource" class="test.jdbc.datasource.InitializingDataSourceFactoryBean">
|
||||
<property name="dataSource" ref="hsql" />
|
||||
<property name="initScript" value="org/springframework/batch/jms/init.sql" />
|
||||
<property name="initScripts" value="org/springframework/batch/jms/init.sql" />
|
||||
<property name="destroyScript" value="org/springframework/batch/jms/destroy.sql" />
|
||||
</bean>
|
||||
|
||||
|
||||
@@ -36,20 +36,35 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
public class InitializingDataSourceFactoryBean extends AbstractFactoryBean {
|
||||
|
||||
private Resource initScript;
|
||||
private Resource[] initScripts;
|
||||
|
||||
private Resource destroyScript;
|
||||
|
||||
DataSource dataSource;
|
||||
|
||||
public void destroy() throws Exception {
|
||||
super.destroy();
|
||||
private static boolean initialized = false;
|
||||
|
||||
/**
|
||||
* @throws Throwable
|
||||
* @see java.lang.Object#finalize()
|
||||
*/
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
initialized = false;
|
||||
logger.debug("finalize called");
|
||||
}
|
||||
|
||||
protected void destroyInstance(Object instance) throws Exception {
|
||||
try {
|
||||
doExecuteScript(destroyScript);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Could not execute destroy script [" + destroyScript + "]", e);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn("Could not execute destroy script [" + destroyScript + "]", e);
|
||||
}
|
||||
else {
|
||||
logger.warn("Could not execute destroy script [" + destroyScript + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,13 +75,21 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean {
|
||||
|
||||
protected Object createInstance() throws Exception {
|
||||
Assert.notNull(dataSource);
|
||||
try {
|
||||
doExecuteScript(destroyScript);
|
||||
if (!initialized) {
|
||||
try {
|
||||
doExecuteScript(destroyScript);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.debug("Could not execute destroy script [" + destroyScript + "]", e);
|
||||
}
|
||||
if (initScripts != null) {
|
||||
for (int i = 0; i < initScripts.length; i++) {
|
||||
Resource initScript = initScripts[i];
|
||||
doExecuteScript(initScript);
|
||||
}
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.debug("Could not execute destroy script [" + destroyScript + "]", e);
|
||||
}
|
||||
doExecuteScript(initScript);
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@@ -74,31 +97,29 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean {
|
||||
if (scriptResource == null || !scriptResource.exists())
|
||||
return;
|
||||
TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
|
||||
if (initScript != null) {
|
||||
transactionTemplate.execute(new TransactionCallback() {
|
||||
transactionTemplate.execute(new TransactionCallback() {
|
||||
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
String[] scripts;
|
||||
try {
|
||||
scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource
|
||||
.getInputStream())), ";");
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BeanInitializationException("Cannot load script from [" + initScript + "]", e);
|
||||
}
|
||||
for (int i = 0; i < scripts.length; i++) {
|
||||
String script = scripts[i].trim();
|
||||
if (StringUtils.hasText(script)) {
|
||||
jdbcTemplate.execute(scripts[i]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
String[] scripts;
|
||||
try {
|
||||
scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource
|
||||
.getInputStream())), ";");
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e);
|
||||
}
|
||||
for (int i = 0; i < scripts.length; i++) {
|
||||
String script = scripts[i].trim();
|
||||
if (StringUtils.hasText(script)) {
|
||||
jdbcTemplate.execute(scripts[i]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String stripComments(List list) {
|
||||
@@ -116,8 +137,8 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean {
|
||||
return DataSource.class;
|
||||
}
|
||||
|
||||
public void setInitScript(Resource initScript) {
|
||||
this.initScript = initScript;
|
||||
public void setInitScripts(Resource[] initScripts) {
|
||||
this.initScripts = initScripts;
|
||||
}
|
||||
|
||||
public void setDestroyScript(Resource destroyScript) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<property name="url" value="jdbc:hsqldb:mem:testdb" />
|
||||
</bean>
|
||||
</property>
|
||||
<property name="initScript" value="org/springframework/batch/item/database/init-foo-schema-hsqldb.sql" />
|
||||
<property name="initScripts" value="org/springframework/batch/item/database/init-foo-schema-hsqldb.sql" />
|
||||
<property name="destroyScript" value="org/springframework/batch/item/database/destroy-foo-schema-hsqldb.sql" />
|
||||
</bean>
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
<bean id="tradeJob" parent="simpleJob">
|
||||
<property name="steps">
|
||||
<list>
|
||||
<bean id="step1" parent="simpleStep">
|
||||
<bean id="step1" parent="simpleStep">
|
||||
<property name="transactionAttribute" value="PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED"/>
|
||||
<property name="streams" ref="fileItemReader" />
|
||||
<property name="itemReader">
|
||||
<bean
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
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.0.xsd">
|
||||
|
||||
<import resource="classpath:/simple-job-launcher-context.xml" />
|
||||
<import resource="classpath:/jobs/simpleJob.xml" />
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user