diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyTasklet.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyTasklet.java new file mode 100644 index 000000000..996ed41b5 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyTasklet.java @@ -0,0 +1,18 @@ +package org.springframework.batch.core.configuration.xml; + +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; +import org.springframework.batch.repeat.RepeatStatus; + +/** + * @author Dan Garrette + * @since 2.0 + */ +public class DummyTasklet implements Tasklet { + + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + return null; + } + +} 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 d78416ee9..726dbc552 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 @@ -20,10 +20,16 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.lang.reflect.Field; +import java.util.List; import java.util.Map; import org.junit.Test; +import org.springframework.aop.framework.Advised; import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecutionListener; +import org.springframework.batch.core.listener.CompositeStepExecutionListener; +import org.springframework.batch.core.listener.StepExecutionListenerSupport; +import org.springframework.batch.core.step.AbstractStep; import org.springframework.batch.core.step.item.ChunkOrientedTasklet; import org.springframework.batch.core.step.item.ChunkProvider; import org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean; @@ -97,10 +103,25 @@ public class StepParserTests { assertTrue("'s1' bean not found", beans.containsKey("s1")); Step s1 = (Step) ctx.getBean("s1"); CompletionPolicy completionPolicy = getCompletionPolicy(s1); - System.err.println(completionPolicy); assertTrue(completionPolicy instanceof DummyCompletionPolicy); } + @SuppressWarnings("unchecked") + private CompletionPolicy getCompletionPolicy(Step s1) throws NoSuchFieldException, IllegalAccessException { + Field taskletField = TaskletStep.class.getDeclaredField("tasklet"); + taskletField.setAccessible(true); + Tasklet tasklet = (Tasklet) taskletField.get(s1); + Field chunkProviderField = ChunkOrientedTasklet.class.getDeclaredField("chunkProvider"); + chunkProviderField.setAccessible(true); + ChunkProvider chunkProvider = (ChunkProvider) chunkProviderField.get(tasklet); + Field repeatOperationsField = SimpleChunkProvider.class.getDeclaredField("repeatOperations"); + repeatOperationsField.setAccessible(true); + RepeatOperations repeatOperations = (RepeatOperations) repeatOperationsField.get(chunkProvider); + Field completionPolicyField = RepeatTemplate.class.getDeclaredField("completionPolicy"); + completionPolicyField.setAccessible(true); + return (CompletionPolicy) completionPolicyField.get(repeatOperations); + } + @Test(expected = BeanDefinitionParsingException.class) public void testStepParserNoCommitIntervalOrCompletionPolicy() throws Exception { new ClassPathXmlApplicationContext( @@ -121,25 +142,75 @@ public class StepParserTests { try { new ClassPathXmlApplicationContext(contextLocation); fail("Context should not load!"); - } catch (BeanDefinitionParsingException e) { + } + catch (BeanDefinitionParsingException e) { assertTrue(e.getMessage().contains("'ref' and 'class'")); } } - @SuppressWarnings("unchecked") - private CompletionPolicy getCompletionPolicy(Step s1) throws NoSuchFieldException, IllegalAccessException { - Field taskletField = TaskletStep.class.getDeclaredField("tasklet"); - taskletField.setAccessible(true); - Tasklet tasklet = (Tasklet) taskletField.get(s1); - Field chunkProviderField = ChunkOrientedTasklet.class.getDeclaredField("chunkProvider"); - chunkProviderField.setAccessible(true); - ChunkProvider chunkProvider = (ChunkProvider) chunkProviderField.get(tasklet); - Field repeatOperationsField = SimpleChunkProvider.class.getDeclaredField("repeatOperations"); - repeatOperationsField.setAccessible(true); - RepeatOperations repeatOperations = (RepeatOperations) repeatOperationsField.get(chunkProvider); - Field completionPolicyField = RepeatTemplate.class.getDeclaredField("completionPolicy"); - completionPolicyField.setAccessible(true); - return (CompletionPolicy) completionPolicyField.get(repeatOperations); + @Test(expected = BeanDefinitionParsingException.class) + public void testStepParserParentAndRef() throws Exception { + new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/StepParserParentAndRefTests-context.xml"); } + @SuppressWarnings("unchecked") + @Test + public void testStepParserParentAttribute() throws Exception { + ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml"); + Map beans = ctx.getBeansOfType(Step.class); + assertTrue(beans.containsKey("s1")); + Step s1 = (Step) ctx.getBean("s1"); + assertTrue(beans.containsKey("s2")); + Step s2 = (Step) ctx.getBean("s2"); + assertTrue(beans.containsKey("s3")); + Step s3 = (Step) ctx.getBean("s3"); + assertTrue(beans.containsKey("s4")); + Step s4 = (Step) ctx.getBean("s4"); + + assertTrue(s1 instanceof TaskletStep); + assertTrue(getListener((TaskletStep) s1) instanceof StepExecutionListenerSupport); + + assertTrue(s2 instanceof DelegatingStep); + assertTrue(getListener((DelegatingStep) s2) instanceof StepExecutionListenerSupport); + + assertTrue(s3 instanceof TaskletStep); + assertTrue(getListener((TaskletStep) s3) instanceof StepExecutionListenerSupport); + + assertTrue(s4 instanceof DelegatingStep); + assertTrue(getListener((DelegatingStep) s4) instanceof StepExecutionListenerSupport); + } + + private StepExecutionListener getListener(DelegatingStep step) throws Exception { + assertTrue(step instanceof DelegatingStep); + Field delegateField = DelegatingStep.class.getDeclaredField("delegate"); + delegateField.setAccessible(true); + Object delegate = delegateField.get(step); + assertTrue(delegate instanceof TaskletStep); + return getListener((TaskletStep) delegate); + } + + @SuppressWarnings("unchecked") + private StepExecutionListener getListener(TaskletStep step) throws Exception { + Field listenerField = AbstractStep.class.getDeclaredField("stepExecutionListener"); + listenerField.setAccessible(true); + Object compositeListener = listenerField.get(step); + + Field compositeField = CompositeStepExecutionListener.class.getDeclaredField("list"); + compositeField.setAccessible(true); + Object composite = compositeField.get(compositeListener); + + Class cls = Class.forName("org.springframework.batch.core.listener.OrderedComposite"); + Field listField = cls.getDeclaredField("list"); + listField.setAccessible(true); + List list = (List) listField.get(composite); + + assertEquals(1, list.size()); + StepExecutionListener listener = list.get(0); + if (listener instanceof Advised) { + listener = (StepExecutionListener) ((Advised) listener).getTargetSource().getTarget(); + } + return listener; + } } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAndRefTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAndRefTests-context.xml new file mode 100644 index 000000000..603663a87 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAndRefTests-context.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + \ No newline at end of file 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 new file mode 100644 index 000000000..dfe4bf058 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file