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 14f6516f0..ad7ec6111 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 @@ -15,7 +15,6 @@ */ package org.springframework.batch.core.configuration.xml; -import java.util.ArrayList; import java.util.List; import org.springframework.batch.core.step.tasklet.TaskletStep; @@ -125,16 +124,15 @@ public abstract class AbstractStepParser { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(listenersElement.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); - List listenerBeans = new ArrayList(); + ManagedList listenerBeans = new ManagedList(); + listenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute("merge"))); List listenerElements = DomUtils.getChildElementsByTagName(listenersElement, "listener"); if (listenerElements != null) { for (Element listenerElement : listenerElements) { listenerBeans.add(stepListenerParser.parse(listenerElement, parserContext)); } } - ManagedList arguments = new ManagedList(); - arguments.addAll(listenerBeans); - bd.getPropertyValues().addPropertyValue(propertyName, arguments); + bd.getPropertyValues().addPropertyValue(propertyName, listenerBeans); parserContext.popAndRegisterContainingComponent(); } } 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 1f779a203..61ac86637 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 @@ -594,6 +594,14 @@ + + + + Should this list of listeners be merged with the list provided + by the parent? If not, it will overwrite the parent list. + + + diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyAnnotationStepExecutionListener.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyAnnotationStepExecutionListener.java new file mode 100644 index 000000000..a9574d9d9 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyAnnotationStepExecutionListener.java @@ -0,0 +1,15 @@ +package org.springframework.batch.core.configuration.xml; + +import org.springframework.batch.core.annotation.BeforeStep; + +/** + * @author Dan Garrette + * @since 2.0 + */ +public class DummyAnnotationStepExecutionListener { + + @BeforeStep + public void execute() { + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java index 3e1a18e28..9b60ca4a2 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java @@ -15,9 +15,11 @@ */ package org.springframework.batch.core.configuration.xml; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -30,6 +32,7 @@ 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.tasklet.TaskletStep; +import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; @@ -43,19 +46,63 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) public class StepListenerParserTests { - @SuppressWarnings("unchecked") @Test public void testStepListenerParser() throws Exception { ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( "org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml"); + List list = getListeners("s1", ctx); + + assertEquals(3, list.size()); + boolean a = false; + boolean b = false; + boolean c = false; + for (Object listener : list) { + if (listener instanceof DummyAnnotationStepExecutionListener) { + a = true; + } + else if (listener instanceof StepExecutionListenerSupport) { + b = true; + } + else if (listener instanceof CompositeStepExecutionListener) { + c = true; + } + } + assertTrue(a); + assertTrue(b); + assertTrue(c); + } + + @Test + public void testStepListenerParserNoMerge() throws Exception { + ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/StepListenerParserNoMergeTests-context.xml"); + List list = getListeners("s1", ctx); + + assertEquals(2, list.size()); + boolean a = false; + boolean b = false; + for (Object listener : list) { + if (listener instanceof DummyAnnotationStepExecutionListener) { + a = true; + } + else if (listener instanceof StepExecutionListenerSupport) { + b = true; + } + } + assertTrue(a); + assertTrue(b); + } + + @SuppressWarnings("unchecked") + private List getListeners(String stepName, ApplicationContext ctx) throws Exception { Map beans = ctx.getBeansOfType(Step.class); - assertTrue(beans.containsKey("s1")); - Step s1 = (Step) ctx.getBean("s1"); - assertTrue(s1 instanceof TaskletStep); + assertTrue(beans.containsKey(stepName)); + Object step = ctx.getBean(stepName); + assertTrue(step instanceof TaskletStep); Field listenerField = AbstractStep.class.getDeclaredField("stepExecutionListener"); listenerField.setAccessible(true); - Object compositeListener = listenerField.get(s1); + Object compositeListener = listenerField.get(step); Field compositeField = CompositeStepExecutionListener.class.getDeclaredField("list"); compositeField.setAccessible(true); @@ -64,29 +111,15 @@ public class StepListenerParserTests { 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(3, list.size()); - boolean a = false; - boolean b = false; - boolean c = false; - for (StepExecutionListener listener : list) { - if (listener instanceof Advised) { - listener = (StepExecutionListener) ((Advised) listener).getTargetSource().getTarget(); - } - if (listener instanceof TestListener) { - a = true; - } - if (listener instanceof StepExecutionListenerSupport) { - b = true; - } - if (listener instanceof CompositeStepExecutionListener) { - c = true; + List proxiedListeners = (List) listField.get(composite); + List r = new ArrayList(); + for (Object listener : proxiedListeners) { + while (listener instanceof Advised) { + listener = ((Advised) listener).getTargetSource().getTarget(); } + r.add(listener); } - assertTrue(a); - assertTrue(b); -// assertTrue(c); + return r; } } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserNoMergeTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserNoMergeTests-context.xml new file mode 100644 index 000000000..2fdf1476c --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserNoMergeTests-context.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml index 97b38f804..b42e8e44d 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml @@ -8,8 +8,8 @@ - - + + @@ -19,7 +19,9 @@ - + + +