diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java index 7586b5190..a6839a46c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java @@ -18,11 +18,13 @@ package org.springframework.batch.core.configuration.xml; import java.util.ArrayList; import java.util.List; +import org.springframework.batch.core.step.tasklet.TaskletStep; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.CompositeComponentDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.RootBeanDefinition; @@ -55,7 +57,8 @@ public abstract class AbstractStepParser { */ protected AbstractBeanDefinition parseTaskletRef(Element stepElement, String taskletRef, ParserContext parserContext, String jobRepositoryRef) { - RootBeanDefinition bd = new RootBeanDefinition("org.springframework.batch.core.step.tasklet.TaskletStep", null, null); + GenericBeanDefinition bd = new GenericBeanDefinition(); + bd.setBeanClass(TaskletStep.class); if (StringUtils.hasText(taskletRef)) { RuntimeBeanReference taskletBeanRef = new RuntimeBeanReference(taskletRef); @@ -117,6 +120,10 @@ public abstract class AbstractStepParser { String allowStartIfComplete = stepElement.getAttribute("allow-start-if-complete"); if (StringUtils.hasText(allowStartIfComplete)) { bd.getPropertyValues().addPropertyValue("allowStartIfComplete", allowStartIfComplete); + } + String parentRef = stepElement.getAttribute("parent"); + if (StringUtils.hasText(parentRef)) { + bd.setParentName(parentRef); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java index 0075293b6..b5b3c5e2f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java @@ -74,6 +74,9 @@ public class InlineStepParser extends AbstractStepParser { if (listOfListenersElements.size() > 0) { parserContext.getReaderContext().error("The 'listeners' element can't be combined with the 'ref=\""+ stepRef +"\"' attribute specification for <" + element.getNodeName() + ">", element); } + if (StringUtils.hasText(element.getAttribute("parent"))) { + parserContext.getReaderContext().error("The 'parent' element can't be combined with the 'ref=\""+ stepRef +"\"' attribute specification for <" + element.getNodeName() + ">", element); + } BeanDefinitionBuilder stepBuilder = BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.configuration.xml.DelegatingStep"); stepBuilder.addConstructorArgValue(stepId); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java index 86a842bb0..0143594e5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java @@ -54,6 +54,7 @@ public class StandaloneStepParser extends AbstractStepParser { Element taskElement = processTaskElements.get(0); bd = parseTaskletElement(element, taskElement, parserContext, jobRepositoryRef); } + bd.setAbstract(Boolean.valueOf(element.getAttribute("abstract"))); return bd; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletElementParser.java index e65eb5d68..dea5d38f4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletElementParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletElementParser.java @@ -18,12 +18,15 @@ package org.springframework.batch.core.configuration.xml; import java.util.ArrayList; import java.util.List; +import org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean; +import org.springframework.batch.core.step.item.SimpleStepFactoryBean; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanReference; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.CompositeComponentDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; @@ -46,8 +49,6 @@ public class TaskletElementParser { */ protected AbstractBeanDefinition parseTaskletElement(Element element, ParserContext parserContext) { - RootBeanDefinition bd; - boolean isFaultTolerant = false; String skipLimit = element.getAttribute("skip-limit"); @@ -72,11 +73,12 @@ public class TaskletElementParser { checkExceptionElementForFaultToleranceNeeded(element, "retryable-exception-classes"); checkExceptionElementForFaultToleranceNeeded(element, "fatal-exception-classes"); + GenericBeanDefinition bd = new GenericBeanDefinition(); if (isFaultTolerant) { - bd = new RootBeanDefinition("org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean", null, null); + bd.setBeanClass(FaultTolerantStepFactoryBean.class); } else { - bd = new RootBeanDefinition("org.springframework.batch.core.step.item.SimpleStepFactoryBean", null, null); + bd.setBeanClass(SimpleStepFactoryBean.class); } MutablePropertyValues propertyValues = bd.getPropertyValues(); diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd index e6a562e3b..12dc58ba5 100644 --- a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd @@ -753,6 +753,9 @@ The name of the parent step from which the configuration should inherit. + + + diff --git a/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml b/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml index f0fc1897b..f43cb9632 100644 --- a/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml @@ -13,13 +13,17 @@ http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> - + + + + - + @@ -31,18 +35,7 @@ - - - - - - - - - - - + @@ -50,22 +43,27 @@ java.lang.RuntimeException - - - - - + + + + + + + + + + + + + + - - - stepName - - + diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java index 5a1a48654..a342bbc05 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java @@ -201,11 +201,6 @@ public class SkipSampleFunctionalTests { } private Map getStepExecution(long jobExecutionId, String stepName) { - for (Map rs : simpleJdbcTemplate.queryForList( - "SELECT * from BATCH_STEP_EXECUTION where JOB_EXECUTION_ID = ? and STEP_NAME = ?", jobExecutionId, - stepName)) { - System.err.println(rs); - } return simpleJdbcTemplate.queryForMap( "SELECT * from BATCH_STEP_EXECUTION where JOB_EXECUTION_ID = ? and STEP_NAME = ?", jobExecutionId, stepName); diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ErrorLogTasklet.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ErrorLogTasklet.java index b078fc40b..34c35abc3 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ErrorLogTasklet.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ErrorLogTasklet.java @@ -12,17 +12,25 @@ import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; +import org.springframework.util.Assert; +/** + * @author Dan Garrette + * @since 2.0 + */ public class ErrorLogTasklet implements Tasklet, StepExecutionListener { protected final Log logger = LogFactory.getLog(getClass()); private SimpleJdbcTemplate simpleJdbcTemplate; - + private String jobName; private String stepName; public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - this.simpleJdbcTemplate.update("insert into ERROR_LOG values (?, ?, 'Some records were skipped!')", jobName, stepName); + Assert.notNull(this.stepName, "Step name not set. Either this class was not registered as a listener " + + "or the key 'stepName' was not found in the Job's ExecutionContext."); + this.simpleJdbcTemplate.update("insert into ERROR_LOG values (?, ?, 'Some records were skipped!')", jobName, + stepName); return RepeatStatus.FINISHED; } @@ -30,12 +38,14 @@ public class ErrorLogTasklet implements Tasklet, StepExecutionListener { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); } + public void beforeStep(StepExecution stepExecution) { + this.jobName = stepExecution.getJobExecution().getJobInstance().getJobName().trim(); + this.stepName = (String) stepExecution.getJobExecution().getExecutionContext().get("stepName"); + stepExecution.getJobExecution().getExecutionContext().remove("stepName"); + } + public ExitStatus afterStep(StepExecution stepExecution) { return null; } - public void beforeStep(StepExecution stepExecution) { - this.jobName = stepExecution.getJobExecution().getJobInstance().getJobName().trim(); - this.stepName = (String)stepExecution.getJobExecution().getExecutionContext().get("stepName"); - } }