BATCH-1396: added step scope to completion policy in chunk parser
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
<step id="playerload" next="gameLoad">
|
||||
<tasklet>
|
||||
<chunk reader="playerFileItemReader" writer="playerWriter"
|
||||
commit-interval="${job.commit.interval}" />
|
||||
commit-interval="#{jobParameters['commit.interval']}" />
|
||||
</tasklet>
|
||||
</step>
|
||||
<step id="gameLoad" next="playerSummarization">
|
||||
|
||||
@@ -37,10 +37,9 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.jdbc.SimpleJdbcTestUtils;
|
||||
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/footballJob.xml" })
|
||||
@@ -48,31 +47,32 @@ public class FootballJobIntegrationTests {
|
||||
|
||||
/** Logger */
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
|
||||
private SimpleJdbcTemplate simpleJdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
private JobLauncher jobLauncher;
|
||||
|
||||
|
||||
@Autowired
|
||||
private Job job;
|
||||
|
||||
|
||||
@Autowired
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void clear() {
|
||||
SimpleJdbcTestUtils.deleteFromTables(simpleJdbcTemplate, "PLAYER_SUMMARY", "GAMES", "PLAYERS");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLaunchJob() throws Exception {
|
||||
JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().toJobParameters());
|
||||
JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().addLong("commit.interval", 10L)
|
||||
.toJobParameters());
|
||||
assertEquals(BatchStatus.COMPLETED, execution.getStatus());
|
||||
for (StepExecution stepExecution : execution.getStepExecutions()) {
|
||||
logger.info("Processed: "+stepExecution);
|
||||
logger.info("Processed: " + stepExecution);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.batch.core.configuration.xml;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.core.listener.StepListenerMetaData;
|
||||
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
@@ -25,6 +26,7 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
@@ -59,7 +61,8 @@ public class ChunkElementParser {
|
||||
|
||||
private static final String ITEM_WRITER_ADAPTER_CLASS = "org.springframework.batch.item.adapter.ItemWriterAdapter";
|
||||
|
||||
private static final StepListenerParser stepListenerParser = new StepListenerParser(StepListenerMetaData.itemListenerMetaData());
|
||||
private static final StepListenerParser stepListenerParser = new StepListenerParser(
|
||||
StepListenerMetaData.itemListenerMetaData());
|
||||
|
||||
/**
|
||||
* @param element
|
||||
@@ -80,7 +83,17 @@ public class ChunkElementParser {
|
||||
|
||||
String commitInterval = element.getAttribute(COMMIT_INTERVAL_ATTR);
|
||||
if (StringUtils.hasText(commitInterval)) {
|
||||
propertyValues.addPropertyValue("commitInterval", commitInterval);
|
||||
if (commitInterval.startsWith("#")) {
|
||||
// It's a late binding expression, so we need step scope...
|
||||
BeanDefinitionBuilder completionPolicy = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(SimpleCompletionPolicy.class);
|
||||
completionPolicy.addConstructorArgValue(commitInterval);
|
||||
completionPolicy.setScope("step");
|
||||
propertyValues.addPropertyValue("chunkCompletionPolicy", completionPolicy.getBeanDefinition());
|
||||
}
|
||||
else {
|
||||
propertyValues.addPropertyValue("commitInterval", commitInterval);
|
||||
}
|
||||
}
|
||||
|
||||
String completionPolicyRef = element.getAttribute(CHUNK_COMPLETION_POLICY_ATTR);
|
||||
@@ -144,7 +157,7 @@ public class ChunkElementParser {
|
||||
handleRetryListenersElement(element, propertyValues, parserContext, bd);
|
||||
|
||||
handleStreamsElement(element, propertyValues, parserContext);
|
||||
|
||||
|
||||
stepListenerParser.handleListenersElement(element, bd, parserContext);
|
||||
|
||||
}
|
||||
@@ -202,8 +215,8 @@ public class ChunkElementParser {
|
||||
propertyValues.addPropertyValue(propertyName, beanDefinitionHolder);
|
||||
}
|
||||
else if (refElements.size() == 1) {
|
||||
propertyValues.addPropertyValue(propertyName, parserContext.getDelegate().parsePropertySubElement(
|
||||
refElements.get(0), null));
|
||||
propertyValues.addPropertyValue(propertyName,
|
||||
parserContext.getDelegate().parsePropertySubElement(refElements.get(0), null));
|
||||
}
|
||||
|
||||
handleAdapterMethodAttribute(propertyName, adapterClassName, propertyValues, element);
|
||||
@@ -251,7 +264,8 @@ public class ChunkElementParser {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void handleRetryListenerElements(ParserContext parserContext, Element element, ManagedList beans, BeanDefinition enclosing) {
|
||||
private void handleRetryListenerElements(ParserContext parserContext, Element element, ManagedList beans,
|
||||
BeanDefinition enclosing) {
|
||||
List<Element> listenerElements = DomUtils.getChildElementsByTagName(element, "listener");
|
||||
if (listenerElements != null) {
|
||||
for (Element listenerElement : listenerElements) {
|
||||
|
||||
@@ -27,12 +27,21 @@ import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A {@link CompletionPolicy} that picks up a commit interval from
|
||||
* {@link JobParameters} by listening to the start of a step. Use anywhere that
|
||||
* a {@link CompletionPolicy} can be used (usually at the chunk level in a
|
||||
* step), and inject as a {@link StepExecutionListener} into the surrounding
|
||||
* step. N.B. only after the step has started will the completion policy be
|
||||
* usable.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It is easier and probably preferable to simply declare the chunk with a
|
||||
* commit-interval that is a late-binding expression (e.g.
|
||||
* <code>#{jobParameters['commit.interval']}</code>). That feature is available
|
||||
* from of Spring Batch 2.1.7.
|
||||
* </p>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
|
||||
@@ -823,7 +823,8 @@ ref" is not required, and only needs to be specified explicitly
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The number of items that will be processed before commit is called for the transaction.
|
||||
Either set this or the chunk-completion-policy but not both.
|
||||
Either set this or the chunk-completion-policy but not both. Can be specified as an expression
|
||||
that will be evaluated in the scope of the step (e.g. "#{jobParameters['commit.interval']}").
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
||||
@@ -65,6 +65,14 @@ public class ChunkElementParserTests {
|
||||
assertTrue("Wrong processor type", chunkProcessor instanceof SimpleChunkProcessor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommitIntervalLateBinding() throws Exception {
|
||||
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
"org/springframework/batch/core/configuration/xml/ChunkElementCommitIntervalParserTests-context.xml");
|
||||
Step step = (Step) context.getBean("s1", Step.class);
|
||||
assertNotNull("Step not parsed", step);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetryPolicyAttribute() throws Exception {
|
||||
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
|
||||
Reference in New Issue
Block a user