diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java index 9c012539b..42cecba6e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java @@ -60,7 +60,7 @@ public class ChunkElementParser { MutablePropertyValues propertyValues = bd.getPropertyValues(); - propertyValues.addPropertyValue("hasChunkTaskletElement", Boolean.TRUE); + propertyValues.addPropertyValue("hasChunkElement", Boolean.TRUE); String readerBeanId = element.getAttribute("reader"); if (StringUtils.hasText(readerBeanId)) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java index 9610467e8..2816e31a5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java @@ -65,6 +65,9 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { // private String name; + // + // Tasklet Attributes + // private Boolean allowStartIfComplete; private JobRepository jobRepository; @@ -76,10 +79,12 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { private PlatformTransactionManager transactionManager; // - // Step Elements + // Tasklet Elements // private StepListener[] listeners; + private Collection> noRollbackExceptionClasses; + private int transactionTimeout = DefaultTransactionAttribute.TIMEOUT_DEFAULT; private Propagation propagation; @@ -87,7 +92,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { private Isolation isolation; // - // Tasklet Attributes + // Chunk Attributes // private Integer cacheCapacity; @@ -110,7 +115,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { private ItemWriter itemWriter; // - // Tasklet Elements + // Chunk Elements // private RetryListener[] retryListeners; @@ -120,14 +125,12 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { private Collection> fatalExceptionClasses; - private Collection> noRollbackExceptionClasses; - private ItemStream[] streams; // // Additional // - private boolean hasChunkTaskletElement = false; + private boolean hasChunkElement = false; /** * Create a {@link Step} from the configuration provided. @@ -135,7 +138,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { * @see FactoryBean#getObject() */ public final Object getObject() throws Exception { - if (hasChunkTaskletElement) { + if (hasChunkElement) { Assert.isNull(tasklet, "Step [" + name + "] has both a element and a 'ref' attribute referencing a Tasklet."); @@ -300,7 +303,6 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { new PropertyNamePair(retryListeners, "retry-listeners"), new PropertyNamePair(skippableExceptionClasses, "skippable-exception-classes"), new PropertyNamePair(retryableExceptionClasses, "retryable-exception-classes"), - new PropertyNamePair(noRollbackExceptionClasses, "no-rollback-exception-classes"), new PropertyNamePair(fatalExceptionClasses, "fatal-exception-classes") }; List wrong = new ArrayList(); @@ -374,6 +376,10 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { } } + // ========================================================= + // Tasklet Attributes + // ========================================================= + /** * Public setter for the flag to indicate that the step should be replayed * on a restart, even if successful the first time. @@ -420,7 +426,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { } // ========================================================= - // Step Elements + // Tasklet Elements // ========================================================= /** @@ -434,6 +440,16 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { this.listeners = listeners; } + /** + * Exception classes that may not cause a rollback if encountered in the + * right place. + * + * @param noRollbackExceptionClasses the noRollbackExceptionClasses to set + */ + public void setNoRollbackExceptionClasses(Collection> noRollbackExceptionClasses) { + this.noRollbackExceptionClasses = noRollbackExceptionClasses; + } + /** * @param transactionTimeout the transactionTimeout to set */ @@ -456,7 +472,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { } // ========================================================= - // Tasklet Attributes + // Chunk Attributes // ========================================================= /** @@ -566,7 +582,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { } // ========================================================= - // Tasklet Elements + // Chunk Elements // ========================================================= /** @@ -598,16 +614,6 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { this.retryableExceptionClasses = retryableExceptionClasses; } - /** - * Exception classes that may not cause a rollback if encountered in the - * right place. - * - * @param noRollbackExceptionClasses the noRollbackExceptionClasses to set - */ - public void setNoRollbackExceptionClasses(Collection> noRollbackExceptionClasses) { - this.noRollbackExceptionClasses = noRollbackExceptionClasses; - } - /** * Public setter for exception classes that should cause immediate failure. * @@ -628,10 +634,14 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { this.streams = streams; } + // ========================================================= + // Additional + // ========================================================= + /** - * @param hasChunkTaskletElement + * @param hasChunkElement */ - public void setHasChunkTaskletElement(boolean hasChunkTaskletElement) { - this.hasChunkTaskletElement = hasChunkTaskletElement; + public void setHasChunkElement(boolean hasChunkElement) { + this.hasChunkElement = hasChunkElement; } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java index 08ff17dec..5ab9aec0c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java @@ -146,7 +146,7 @@ public class StepParserStepFactoryBeanTests { @Test public void testSimpleStep() throws Exception { StepParserStepFactoryBean fb = new StepParserStepFactoryBean(); - fb.setHasChunkTaskletElement(true); + fb.setHasChunkElement(true); fb.setBeanName("step1"); fb.setAllowStartIfComplete(true); fb.setJobRepository(new JobRepositorySupport()); @@ -172,7 +172,7 @@ public class StepParserStepFactoryBeanTests { @Test public void testFaultTolerantStep() throws Exception { StepParserStepFactoryBean fb = new StepParserStepFactoryBean(); - fb.setHasChunkTaskletElement(true); + fb.setHasChunkElement(true); fb.setBeanName("step1"); fb.setAllowStartIfComplete(true); fb.setJobRepository(new JobRepositorySupport()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java index 23c17befa..2d0f21568 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java @@ -26,6 +26,7 @@ import org.springframework.aop.framework.Advised; import org.springframework.batch.core.Step; import org.springframework.batch.core.StepExecutionListener; import org.springframework.batch.core.listener.StepExecutionListenerSupport; +import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.core.step.tasklet.TaskletStep; import org.springframework.batch.repeat.CompletionPolicy; import org.springframework.batch.repeat.policy.SimpleCompletionPolicy; @@ -209,4 +210,23 @@ public class StepParserTests { return txa; } + @Test + public void testInheritFromBean() throws Exception { + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml"); + + assertTrue(getTasklet("s9", ctx) instanceof DummyTasklet); + assertTrue(getTasklet("s10", ctx) instanceof DummyTasklet); + } + + @SuppressWarnings("unchecked") + private Tasklet getTasklet(String stepName, ApplicationContext ctx) { + Map beans = ctx.getBeansOfType(Step.class); + assertTrue(beans.containsKey(stepName)); + Step step = (Step) ctx.getBean(stepName); + assertTrue(step instanceof TaskletStep); + Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); + assertTrue(tasklet instanceof Tasklet); + return (Tasklet)tasklet; + } } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml index 91fde8769..5d1707de3 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml @@ -32,7 +32,9 @@ - + + + @@ -61,6 +63,18 @@ + + + + + + + + + + + +