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 547c05df0..013714e88 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 @@ -75,11 +75,11 @@ public class ChunkElementParser { propertyValues.addPropertyValue("hasChunkElement", Boolean.TRUE); - handleItemHandler("reader", "itemReader", ITEM_READER_ADAPTER_CLASS, true, element, parserContext, + handleItemHandler(bd, "reader", "itemReader", ITEM_READER_ADAPTER_CLASS, true, element, parserContext, propertyValues, underspecified); - handleItemHandler("processor", "itemProcessor", ITEM_PROCESSOR_ADAPTER_CLASS, false, element, parserContext, + handleItemHandler(bd, "processor", "itemProcessor", ITEM_PROCESSOR_ADAPTER_CLASS, false, element, parserContext, propertyValues, underspecified); - handleItemHandler("writer", "itemWriter", ITEM_WRITER_ADAPTER_CLASS, true, element, parserContext, + handleItemHandler(bd, "writer", "itemWriter", ITEM_WRITER_ADAPTER_CLASS, true, element, parserContext, propertyValues, underspecified); String commitInterval = element.getAttribute(COMMIT_INTERVAL_ATTR); @@ -131,7 +131,7 @@ public class ChunkElementParser { // classes for an abstract parent bean definition propertyValues.addPropertyValue("skippableExceptionClasses", skippableExceptions); - handleItemHandler("skip-policy", "skipPolicy", null, false, element, parserContext, propertyValues, + handleItemHandler(bd, "skip-policy", "skipPolicy", null, false, element, parserContext, propertyValues, underspecified); String retryLimit = element.getAttribute("retry-limit"); @@ -147,7 +147,7 @@ public class ChunkElementParser { // classes for an abstract parent bean definition propertyValues.addPropertyValue("retryableExceptionClasses", retryableExceptions); - handleItemHandler("retry-policy", "retryPolicy", null, false, element, parserContext, propertyValues, + handleItemHandler(bd, "retry-policy", "retryPolicy", null, false, element, parserContext, propertyValues, underspecified); String cacheCapacity = element.getAttribute("cache-capacity"); @@ -176,7 +176,7 @@ public class ChunkElementParser { /** * Handle the ItemReader, ItemProcessor, and ItemWriter attributes/elements. */ - private void handleItemHandler(String handlerName, String propertyName, String adapterClassName, boolean required, + private void handleItemHandler(AbstractBeanDefinition enclosing, String handlerName, String propertyName, String adapterClassName, boolean required, Element element, ParserContext parserContext, MutablePropertyValues propertyValues, boolean underspecified) { String refName = element.getAttribute(handlerName); @SuppressWarnings("unchecked") @@ -187,7 +187,7 @@ public class ChunkElementParser { "The <" + element.getNodeName() + "/> element may not have both a '" + handlerName + "' attribute and a <" + handlerName + "/> element.", element); } - handleItemHandlerElement(propertyName, adapterClassName, propertyValues, children.get(0), parserContext); + handleItemHandlerElement(enclosing, propertyName, adapterClassName, propertyValues, children.get(0), parserContext); } else if (children.size() > 1) { parserContext.getReaderContext().error( @@ -209,7 +209,7 @@ public class ChunkElementParser { * is defined within the item handler. */ @SuppressWarnings("unchecked") - private void handleItemHandlerElement(String propertyName, String adapterClassName, + private void handleItemHandlerElement(AbstractBeanDefinition enclosing, String propertyName, String adapterClassName, MutablePropertyValues propertyValues, Element element, ParserContext parserContext) { List beanElements = DomUtils.getChildElementsByTagName(element, BEAN_ELE); List refElements = DomUtils.getChildElementsByTagName(element, REF_ELE); @@ -221,8 +221,9 @@ public class ChunkElementParser { else if (beanElements.size() == 1) { Element beanElement = beanElements.get(0); BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate().parseBeanDefinitionElement( - beanElement); + beanElement, enclosing); parserContext.getDelegate().decorateBeanDefinitionIfRequired(beanElement, beanDefinitionHolder); + propertyValues.addPropertyValue(propertyName, beanDefinitionHolder); } else if (refElements.size() == 1) { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests.java index 7a6efae60..e218838a2 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests.java @@ -3,7 +3,14 @@ package org.springframework.batch.core.configuration.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.util.Map; + +import org.junit.After; import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.adapter.ItemProcessorAdapter; import org.springframework.batch.item.adapter.ItemReaderAdapter; import org.springframework.batch.item.adapter.ItemWriterAdapter; @@ -17,12 +24,21 @@ import org.springframework.test.util.ReflectionTestUtils; */ public class InlineItemHandlerParserTests { - private ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( - "org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests-context.xml"); + private ConfigurableApplicationContext context; + + @After + public void close() { + if (context != null) { + context.close(); + } + StepSynchronizationManager.release(); + } @Test public void testInlineHandlers() throws Exception { - Object step = ctx.getBean("inlineHandlers"); + context = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests-context.xml"); + Object step = context.getBean("inlineHandlers"); Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); Object chunkProvider = ReflectionTestUtils.getField(tasklet, "chunkProvider"); Object reader = ReflectionTestUtils.getField(chunkProvider, "itemReader"); @@ -37,7 +53,9 @@ public class InlineItemHandlerParserTests { @Test public void testInlineAdapters() throws Exception { - Object step = ctx.getBean("inlineAdapters"); + context = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests-context.xml"); + Object step = context.getBean("inlineAdapters"); Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); Object chunkProvider = ReflectionTestUtils.getField(tasklet, "chunkProvider"); Object reader = ReflectionTestUtils.getField(chunkProvider, "itemReader"); @@ -64,4 +82,17 @@ public class InlineItemHandlerParserTests { assertEquals("dummyWrite", writerMethod); } + @Test + public void testInlineHandlersWithStepScope() throws Exception { + context = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/InlineItemHandlerWithStepScopeParserTests-context.xml"); + StepSynchronizationManager.register(new StepExecution("step", new JobExecution(123L))); + + @SuppressWarnings("unchecked") + Map> readers = context.getBeansOfType(ItemReader.class); + // Should be 2 each (proxy and target) for the two readers in the steps defined + assertEquals(4, readers.size()); + // System.err.println(readers); + } + } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/InlineItemHandlerWithStepScopeParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/InlineItemHandlerWithStepScopeParserTests-context.xml new file mode 100644 index 000000000..53b217254 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/InlineItemHandlerWithStepScopeParserTests-context.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file