diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java index 2bb9375ba..aa79fcc01 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java @@ -17,12 +17,19 @@ import org.w3c.dom.NamedNodeMap; /** * @author Dan Garrette * @since 2.0 + * @see StepListenerParser + * @see JobExecutionListenerParser */ public abstract class AbstractListenerParser { - @SuppressWarnings("unchecked") public AbstractBeanDefinition parse(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(getBeanClass(null)); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(getBeanClass()); + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } + + @SuppressWarnings("unchecked") + public void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String id = element.getAttribute("id"); String listenerRef = element.getAttribute("ref"); String className = element.getAttribute("class"); @@ -48,7 +55,6 @@ public abstract class AbstractListenerParser { } } builder.addPropertyValue("metaDataMap", metaDataMap); - return builder.getBeanDefinition(); } private void checkListenerElementAttributes(ParserContext parserContext, Element element, String id, @@ -77,7 +83,7 @@ public abstract class AbstractListenerParser { return methodNameAttributes; } - protected abstract Class getBeanClass(Element element); + protected abstract Class getBeanClass(); protected abstract ListenerMetaData[] getMetaDataValues(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java index c0dab6517..899c8f5ee 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java @@ -20,7 +20,6 @@ import org.springframework.batch.core.listener.AbstractListenerFactoryBean; import org.springframework.batch.core.listener.JobListenerFactoryBean; import org.springframework.batch.core.listener.JobListenerMetaData; import org.springframework.batch.core.listener.ListenerMetaData; -import org.w3c.dom.Element; /** * Parser for a step listener element. Builds a {@link JobListenerFactoryBean} @@ -28,10 +27,11 @@ import org.w3c.dom.Element; * * @author Dan Garrette * @since 2.0 + * @see AbstractListenerParser */ public class JobExecutionListenerParser extends AbstractListenerParser { - protected Class getBeanClass(Element element) { + protected Class getBeanClass() { return JobListenerFactoryBean.class; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepListenerParser.java index 14bf52b89..c63a33e22 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepListenerParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepListenerParser.java @@ -19,7 +19,6 @@ import org.springframework.batch.core.listener.AbstractListenerFactoryBean; import org.springframework.batch.core.listener.ListenerMetaData; import org.springframework.batch.core.listener.StepListenerFactoryBean; import org.springframework.batch.core.listener.StepListenerMetaData; -import org.w3c.dom.Element; /** * Parser for a step listener element. Builds a {@link StepListenerFactoryBean} @@ -27,10 +26,11 @@ import org.w3c.dom.Element; * * @author Dan Garrette * @since 2.0 + * @see AbstractListenerParser */ public class StepListenerParser extends AbstractListenerParser { - protected Class getBeanClass(Element element) { + protected Class getBeanClass() { return StepListenerFactoryBean.class; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelStepListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelStepListenerParser.java index 9e989ee11..0e420a389 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelStepListenerParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelStepListenerParser.java @@ -1,22 +1,29 @@ package org.springframework.batch.core.configuration.xml; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; +import org.springframework.batch.core.listener.AbstractListenerFactoryBean; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; /** + * Parse <step-listener/> elements in the batch namespace. + * * @author Dan Garrette * @since 2.0 */ -public class TopLevelStepListenerParser extends AbstractBeanDefinitionParser { +public class TopLevelStepListenerParser extends AbstractSingleBeanDefinitionParser { + + private StepListenerParser stepListenerParser = new StepListenerParser(); @Override - protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { - - StepListenerParser stepListenerParser = new StepListenerParser(); - return stepListenerParser.parse(element, parserContext); + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + stepListenerParser.doParse(element, parserContext, builder); + } + @Override + protected Class getBeanClass(Element element) { + return stepListenerParser.getBeanClass(); } } 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 new file mode 100644 index 000000000..3e1a18e28 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +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.tasklet.TaskletStep; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@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"); + Map beans = ctx.getBeansOfType(Step.class); + assertTrue(beans.containsKey("s1")); + Step s1 = (Step) ctx.getBean("s1"); + assertTrue(s1 instanceof TaskletStep); + + Field listenerField = AbstractStep.class.getDeclaredField("stepExecutionListener"); + listenerField.setAccessible(true); + Object compositeListener = listenerField.get(s1); + + 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(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; + } + } + assertTrue(a); + assertTrue(b); +// assertTrue(c); + } + +} 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 new file mode 100644 index 000000000..97b38f804 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + \ 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 index dfe4bf058..8b0486a64 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 @@ -36,6 +36,4 @@ - - \ No newline at end of file diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/common-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/common-context.xml index b04b1cafc..db7711ebd 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/common-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/common-context.xml @@ -37,4 +37,6 @@ + + \ No newline at end of file