diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleExportedJobLauncher.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleExportedJobLauncher.java index 6f7a9ee43..23d5fabea 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleExportedJobLauncher.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleExportedJobLauncher.java @@ -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()); } } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/AbstractStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/AbstractStepFactoryBean.java index 7667f6926..2428aecab 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/AbstractStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/AbstractStepFactoryBean.java @@ -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); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ItemOrientedStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ItemOrientedStep.java index d516e1f5c..e357dba4f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ItemOrientedStep.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ItemOrientedStep.java @@ -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 { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java index 731f5f53f..78445d2e9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java @@ -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(); } } diff --git a/spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java b/spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java index 210d73b57..b5e410af7 100644 --- a/spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java +++ b/spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java @@ -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) { diff --git a/spring-batch-infrastructure-tests/src/test/resources/data-source.xml b/spring-batch-infrastructure-tests/src/test/resources/data-source.xml index f1723b5f8..c631924c8 100644 --- a/spring-batch-infrastructure-tests/src/test/resources/data-source.xml +++ b/spring-batch-infrastructure-tests/src/test/resources/data-source.xml @@ -4,7 +4,7 @@ - + diff --git a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java index 210d73b57..b5e410af7 100644 --- a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java +++ b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java @@ -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) { diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/data-source-context.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/data-source-context.xml index 4bd3a443c..90b2ebc9d 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/data-source-context.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/data-source-context.xml @@ -9,7 +9,7 @@ - + diff --git a/spring-batch-samples/src/main/resources/jobs/tradeJob.xml b/spring-batch-samples/src/main/resources/jobs/tradeJob.xml index b99ed91e9..ee1f3b0bd 100644 --- a/spring-batch-samples/src/main/resources/jobs/tradeJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/tradeJob.xml @@ -13,7 +13,8 @@ - + + - - - - - -