diff --git a/spring-batch-core/pom.xml b/spring-batch-core/pom.xml
index e3fee1280..32775ff1a 100644
--- a/spring-batch-core/pom.xml
+++ b/spring-batch-core/pom.xml
@@ -40,6 +40,9 @@
hsqldb
hsqldb
+
+ com.h2databaseh21.2.132
+
commons-io
commons-io
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/Step.java b/spring-batch-core/src/main/java/org/springframework/batch/core/Step.java
index 014c28875..df0d61096 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/Step.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/Step.java
@@ -17,7 +17,7 @@ package org.springframework.batch.core;
/**
* Batch domain interface representing the configuration of a step. As with the {@link Job}, a {@link Step} is meant to
- * explicitly represent a the configuration of a step by a developer, but also the ability to execute the step.
+ * explicitly represent the configuration of a step by a developer, but also the ability to execute the step.
*
* @author Dave Syer
*
@@ -52,4 +52,4 @@ public interface Step {
*/
void execute(StepExecution stepExecution) throws JobInterruptedException;
-}
\ No newline at end of file
+}
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 28104c834..eb4d7aa5d 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
@@ -33,11 +33,11 @@ import org.w3c.dom.Element;
* {@link org.springframework.batch.core.Step} and goes on to (optionally) list
* a set of transitions from that step to others with <next on="pattern"
* to="stepName"/>. Used by the {@link JobParser}.
- *
- * @see JobParser
- *
+ *
* @author Dave Syer
* @author Thomas Risberg
+ * @author Josh Long
+ * @see JobParser
* @since 2.0
*/
public abstract class AbstractStepParser {
@@ -60,6 +60,8 @@ public abstract class AbstractStepParser {
private static final String STEP_ATTR = "step";
+ private static final String STEP_ELE = STEP_ATTR;
+
private static final String PARTITIONER_ATTR = "partitioner";
private static final String HANDLER_ATTR = "handler";
@@ -75,10 +77,10 @@ public abstract class AbstractStepParser {
private static final String JOB_REPO_ATTR = "job-repository";
/**
- * @param stepElement The <step/> element
+ * @param stepElement The <step/> element
* @param parserContext
* @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean}
- * from the enclosing tag. Use 'null' if unknown.
+ * from the enclosing tag. Use 'null' if unknown.
*/
protected AbstractBeanDefinition parseStep(Element stepElement, ParserContext parserContext, String jobFactoryRef) {
@@ -100,7 +102,7 @@ public abstract class AbstractStepParser {
Element partitionElement = DomUtils.getChildElementByTagName(stepElement, PARTITION_ELE);
if (partitionElement != null) {
boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
- parsePartition(stepElement, partitionElement, bd, parserContext, stepUnderspecified);
+ parsePartition(stepElement, partitionElement, bd, parserContext, stepUnderspecified, jobFactoryRef);
}
Element jobElement = DomUtils.getChildElementByTagName(stepElement, JOB_ELE);
@@ -137,8 +139,7 @@ public abstract class AbstractStepParser {
}
- private void parsePartition(Element stepElement, Element partitionElement, AbstractBeanDefinition bd,
- ParserContext parserContext, boolean stepUnderspecified) {
+ private void parsePartition(Element stepElement, Element partitionElement, AbstractBeanDefinition bd, ParserContext parserContext, boolean stepUnderspecified, String jobFactoryRef ) {
bd.setBeanClass(StepParserStepFactoryBean.class);
bd.setAttribute("isNamespaceStep", true);
@@ -146,17 +147,27 @@ public abstract class AbstractStepParser {
String partitionerRef = partitionElement.getAttribute(PARTITIONER_ATTR);
String handlerRef = partitionElement.getAttribute(HANDLER_ATTR);
- if (!StringUtils.hasText(stepRef)) {
- parserContext.getReaderContext().error("You must specify a step", partitionElement);
- return;
- }
if (!StringUtils.hasText(partitionerRef)) {
parserContext.getReaderContext().error("You must specify a partitioner", partitionElement);
return;
}
+ Element inlineStepElement = DomUtils.getChildElementByTagName(partitionElement, STEP_ELE);
+ if (inlineStepElement == null && !StringUtils.hasText(stepRef)) {
+ parserContext.getReaderContext().error("You must specify a step", partitionElement);
+ return;
+ }
+
+
MutablePropertyValues propertyValues = bd.getPropertyValues();
- propertyValues.addPropertyValue("step", new RuntimeBeanReference(stepRef));
+
+ if (StringUtils.hasText(stepRef)) {
+ propertyValues.addPropertyValue("step", new RuntimeBeanReference(stepRef));
+ } else if( inlineStepElement!=null) {
+ AbstractBeanDefinition stepDefinition = parseStep(inlineStepElement, parserContext, jobFactoryRef);
+ propertyValues.addPropertyValue("step", stepDefinition );
+ }
+
propertyValues.addPropertyValue("partitioner", new RuntimeBeanReference(partitionerRef));
if (!StringUtils.hasText(handlerRef)) {
@@ -171,15 +182,13 @@ public abstract class AbstractStepParser {
propertyValues.addPropertyValue("gridSize", new TypedStringValue(gridSize));
}
}
- }
- else {
+ } else {
propertyValues.addPropertyValue("partitionHandler", new RuntimeBeanReference(handlerRef));
}
}
- private void parseJob(Element stepElement, Element jobElement, AbstractBeanDefinition bd,
- ParserContext parserContext, boolean stepUnderspecified) {
+ private void parseJob(Element stepElement, Element jobElement, AbstractBeanDefinition bd, ParserContext parserContext, boolean stepUnderspecified) {
bd.setBeanClass(StepParserStepFactoryBean.class);
bd.setAttribute("isNamespaceStep", true);
@@ -207,7 +216,7 @@ public abstract class AbstractStepParser {
private void parseFlow(Element stepElement, Element flowElement, AbstractBeanDefinition bd,
- ParserContext parserContext, boolean stepUnderspecified) {
+ ParserContext parserContext, boolean stepUnderspecified) {
bd.setBeanClass(StepParserStepFactoryBean.class);
bd.setAttribute("isNamespaceStep", true);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java
index 3817f58a1..b864f253f 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java
@@ -32,8 +32,7 @@ public class BeanDefinitionUtils {
* @return The {@link PropertyValue} for the property of the bean. Search
* parent hierarchy if necessary. Return null if none is found.
*/
- public static PropertyValue getPropertyValue(String beanName, String propertyName,
- ConfigurableListableBeanFactory beanFactory) {
+ public static PropertyValue getPropertyValue(String beanName, String propertyName, ConfigurableListableBeanFactory beanFactory) {
return beanFactory.getMergedBeanDefinition(beanName).getPropertyValues().getPropertyValue(propertyName);
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java
index 9373665bb..2ff043353 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java
@@ -19,14 +19,14 @@ import org.springframework.beans.factory.xml.NamespaceHandler;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
+ *
+ *
* @author Dave Syer
*
*/
public class CoreNamespaceHandler extends NamespaceHandlerSupport {
/**
- *
- *
* @see NamespaceHandler#init()
*/
public void init() {
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java
index 864bbaf9a..a8c9c674d 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java
@@ -16,10 +16,6 @@
package org.springframework.batch.core.configuration.xml;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-
import org.springframework.batch.classify.BinaryExceptionClassifier;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
@@ -66,18 +62,23 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.util.Assert;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+
/**
* This {@link FactoryBean} is used by the batch namespace parser to create
* {@link Step} objects. Stores all of the properties that are configurable on
* the <step/> (and its inner <tasklet/>). Based on which properties
* are configured, the {@link #getObject()} method will delegate to the
* appropriate class for generating the {@link Step}.
- *
+ *
* @author Dan Garrette
- * @since 2.0
+ * @author Josh Long
* @see SimpleStepFactoryBean
* @see FaultTolerantStepFactoryBean
* @see TaskletStep
+ * @since 2.0
*/
class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
@@ -194,7 +195,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Create a {@link Step} from the configuration provided.
- *
+ *
* @see FactoryBean#getObject()
*/
public final Object getObject() throws Exception {
@@ -208,34 +209,28 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
configureSimple(fb);
configureFaultTolerant(fb);
return fb.getObject();
- }
- else {
+ } else {
SimpleStepFactoryBean fb = new SimpleStepFactoryBean();
configureSimple(fb);
return fb.getObject();
}
- }
- else if (tasklet != null) {
+ } else if (tasklet != null) {
TaskletStep ts = new TaskletStep();
configureTaskletStep(ts);
return ts;
- }
- else if (flow != null) {
+ } else if (flow != null) {
FlowStep ts = new FlowStep();
configureFlowStep(ts);
return ts;
- }
- else if (job != null) {
+ } else if (job != null) {
JobStep ts = new JobStep();
configureJobStep(ts);
return ts;
- }
- else if (step != null) {
+ } else if (step != null) {
PartitionStep ts = new PartitionStep();
configurePartitionStep(ts);
return ts;
- }
- else {
+ } else {
throw new IllegalStateException("Step [" + name
+ "] has neither a element nor a 'ref' attribute referencing a Tasklet.");
}
@@ -274,10 +269,13 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
Assert.state(partitioner != null, "A Partitioner must be provided for a partition step");
Assert.state(step != null, "A Step must be provided for a partition step");
configureAbstractStep(ts);
+
+ PartitionHandler handler;
+
if (partitionHandler != null) {
+ handler = partitionHandler;
ts.setPartitionHandler(partitionHandler);
- }
- else {
+ } else {
TaskExecutorPartitionHandler partitionHandler = new TaskExecutorPartitionHandler();
partitionHandler.setStep(step);
if (taskExecutor == null) {
@@ -286,7 +284,21 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
partitionHandler.setGridSize(gridSize);
partitionHandler.setTaskExecutor(taskExecutor);
ts.setPartitionHandler(partitionHandler);
+ handler = partitionHandler;
}
+
+
+ // BATCH-1659
+ if (handler instanceof TaskExecutorPartitionHandler) {
+ try {
+ TaskExecutorPartitionHandler taskExecutorPartitionHandler = (TaskExecutorPartitionHandler) handler;
+ taskExecutorPartitionHandler.setStep(step);
+ taskExecutorPartitionHandler.afterPropertiesSet();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, step, partitioner);
ts.setStepExecutionSplitter(splitter);
}
@@ -475,18 +487,17 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* Check if a field is present then a second is also. If the
* twoWayDependency flag is set then the opposite must also be true: if the
* second value is present, the first must also be.
- *
- * @param dependentName the name of the first field
- * @param dependentValue the value of the first field
- * @param name the name of the other field (which should be absent if the
- * first is present)
- * @param value the value of the other field
+ *
+ * @param dependentName the name of the first field
+ * @param dependentValue the value of the first field
+ * @param name the name of the other field (which should be absent if the
+ * first is present)
+ * @param value the value of the other field
* @param twoWayDependency true if both depend on each other
- *
* @throws IllegalArgumentException if eiether condition is violated
*/
private void validateDependency(String dependentName, Object dependentValue, String name, Object value,
- boolean twoWayDependency) {
+ boolean twoWayDependency) {
if (isPresent(dependentValue) && !isPresent(value)) {
throw new IllegalArgumentException("The field '" + dependentName + "' is not permitted on the step ["
+ this.name + "] because there is no '" + name + "'.");
@@ -499,7 +510,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Is the object non-null (or if an Integer, non-zero)?
- *
+ *
* @param o an object
* @return true if the object has a value
*/
@@ -538,7 +549,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Set the bean name property, which will become the name of the
* {@link Step} when it is created.
- *
+ *
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
*/
public void setBeanName(String name) {
@@ -562,9 +573,6 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
// Job Attributes
// =========================================================
- /**
- * @param flow the flow to set
- */
public void setJob(Job job) {
this.job = job;
}
@@ -616,7 +624,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Public setter for the flag to indicate that the step should be replayed
* on a restart, even if successful the first time.
- *
+ *
* @param allowStartIfComplete the shouldAllowStartIfComplete to set
*/
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
@@ -633,7 +641,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Public setter for {@link JobRepository}.
- *
+ *
* @param jobRepository
*/
public void setJobRepository(JobRepository jobRepository) {
@@ -642,7 +650,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* The number of times that the step should be allowed to start
- *
+ *
* @param startLimit
*/
public void setStartLimit(int startLimit) {
@@ -651,7 +659,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* A preconfigured {@link Tasklet} to use.
- *
+ *
* @param tasklet
*/
public void setTasklet(Tasklet tasklet) {
@@ -680,7 +688,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* The listeners to inject into the {@link Step}. Any instance of
* {@link StepListener} can be used, and will then receive callbacks at the
* appropriate stage in the step.
- *
+ *
* @param listeners an array of listeners
*/
public void setListeners(StepListener[] listeners) {
@@ -690,7 +698,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Exception classes that may not cause a rollback if encountered in the
* right place.
- *
+ *
* @param noRollbackExceptionClasses the noRollbackExceptionClasses to set
*/
public void setNoRollbackExceptionClasses(Collection> noRollbackExceptionClasses) {
@@ -724,7 +732,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* A backoff policy to be applied to retry process.
- *
+ *
* @param backOffPolicy the {@link BackOffPolicy} to set
*/
public void setBackOffPolicy(BackOffPolicy backOffPolicy) {
@@ -734,7 +742,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* A retry policy to apply when exceptions occur. If this is specified then
* the retry limit and retryable exceptions will be ignored.
- *
+ *
* @param retryPolicy the {@link RetryPolicy} to set
*/
public void setRetryPolicy(RetryPolicy retryPolicy) {
@@ -752,7 +760,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* A key generator that can be used to compare items with previously
* recorded items in a retry. Only used if the reader is a transactional
* queue.
- *
+ *
* @param keyGenerator the {@link KeyGenerator} to set
*/
public void setKeyGenerator(KeyGenerator keyGenerator) {
@@ -768,14 +776,14 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* items than this fail without being skipped or recovered an exception will
* be thrown. This is to guard against inadvertent infinite loops generated
* by item identity problems.
- *
+ *
* The default value should be high enough and more for most purposes. To
* breach the limit in a single-threaded step typically you have to have
* this many failures in a single transaction. Defaults to the value in the
* {@link MapRetryContextCache}.
- *
+ *
* @param cacheCapacity the cache capacity to set (greater than 0 else
- * ignored)
+ * ignored)
*/
public void setCacheCapacity(int cacheCapacity) {
this.cacheCapacity = cacheCapacity;
@@ -786,7 +794,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* level. A transaction will be committed when this policy decides to
* complete. Defaults to a {@link SimpleCompletionPolicy} with chunk size
* equal to the commitInterval property.
- *
+ *
* @param chunkCompletionPolicy the chunkCompletionPolicy to set
*/
public void setChunkCompletionPolicy(CompletionPolicy chunkCompletionPolicy) {
@@ -796,7 +804,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Set the commit interval. Either set this or the chunkCompletionPolicy but
* not both.
- *
+ *
* @param commitInterval 1 by default
*/
public void setCommitInterval(int commitInterval) {
@@ -807,7 +815,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* Flag to signal that the reader is transactional (usually a JMS consumer)
* so that items are re-presented after a rollback. The default is false and
* readers are assumed to be forward-only.
- *
+ *
* @param isReaderTransactionalQueue the value of the flag
*/
public void setIsReaderTransactionalQueue(boolean isReaderTransactionalQueue) {
@@ -819,7 +827,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* should be called for every item in every transaction. If false then we
* can cache the processor results between transactions in the case of a
* rollback.
- *
+ *
* @param processorTransactional the value to set
*/
public void setProcessorTransactional(Boolean processorTransactional) {
@@ -830,7 +838,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* Public setter for the retry limit. Each item can be retried up to this
* limit. Note this limit includes the initial attempt to process the item,
* therefore retryLimit == 1 by default.
- *
+ *
* @param retryLimit the retry limit to set, must be greater or equal to 1.
*/
public void setRetryLimit(int retryLimit) {
@@ -843,7 +851,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* skipped and no exception propagated until the limit is reached. If it is
* zero then all exceptions will be propagated from the chunk and cause the
* step to abort.
- *
+ *
* @param skipLimit the value to set. Default is 0 (never skip).
*/
public void setSkipLimit(int skipLimit) {
@@ -853,7 +861,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Public setter for a skip policy. If this value is set then the skip limit
* and skippable exceptions are ignored.
- *
+ *
* @param skipPolicy the {@link SkipPolicy} to set
*/
public void setSkipPolicy(SkipPolicy skipPolicy) {
@@ -863,7 +871,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Public setter for the {@link TaskExecutor}. If this is set, then it will
* be used to execute the chunk processing inside the {@link Step}.
- *
+ *
* @param taskExecutor the taskExecutor to set
*/
public void setTaskExecutor(TaskExecutor taskExecutor) {
@@ -875,7 +883,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* queued for concurrent processing to prevent thread pools from being
* overwhelmed. Defaults to
* {@link TaskExecutorRepeatTemplate#DEFAULT_THROTTLE_LIMIT}.
- *
+ *
* @param throttleLimit the throttle limit to set.
*/
public void setThrottleLimit(Integer throttleLimit) {
@@ -909,7 +917,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Public setter for the {@link RetryListener}s.
- *
+ *
* @param retryListeners the {@link RetryListener}s to set
*/
public void setRetryListeners(RetryListener... retryListeners) {
@@ -920,7 +928,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* Public setter for exception classes that when raised won't crash the job
* but will result in transaction rollback and the item which handling
* caused the exception will be skipped.
- *
+ *
* @param exceptionClasses
*/
public void setSkippableExceptionClasses(Map, Boolean> exceptionClasses) {
@@ -929,7 +937,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
/**
* Public setter for exception classes that will retry the item when raised.
- *
+ *
* @param retryableExceptionClasses the retryableExceptionClasses to set
*/
public void setRetryableExceptionClasses(Map, Boolean> retryableExceptionClasses) {
@@ -940,7 +948,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
* The streams to inject into the {@link Step}. Any instance of
* {@link ItemStream} can be used, and will then receive callbacks at the
* appropriate stage in the step.
- *
+ *
* @param streams an array of listeners
*/
public void setStreams(ItemStream[] streams) {
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java
index 977c42431..a16e914f0 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java
@@ -143,9 +143,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean {
/*
* (non-Javadoc)
*
- * @see
- * org.springframework.batch.core.launch.JobOperator#getExecutions(java.
- * lang.Long)
+ * @see org.springframework.batch.core.launch.JobOperator#getExecutions(java.lang.Long)
*/
public List getExecutions(long instanceId) throws NoSuchJobInstanceException {
JobInstance jobInstance = jobExplorer.getJobInstance(instanceId);
@@ -251,8 +249,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean {
* @see
* org.springframework.batch.core.launch.JobOperator#resume(java.lang.Long)
*/
- public Long restart(long executionId) throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException,
- NoSuchJobException, JobRestartException, JobParametersInvalidException {
+ public Long restart(long executionId) throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException, NoSuchJobException, JobRestartException, JobParametersInvalidException {
logger.info("Checking status of job execution with id=" + executionId);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerMetaData.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerMetaData.java
index 0f17510bc..518a1f9df 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerMetaData.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerMetaData.java
@@ -79,8 +79,7 @@ public enum StepListenerMetaData implements ListenerMetaData {
private final Class>[] paramTypes;
private static final Map propertyMap;
- StepListenerMetaData(String methodName, String propertyName, Class extends Annotation> annotation,
- Class extends StepListener> listenerInterface, Class>... paramTypes) {
+ StepListenerMetaData(String methodName, String propertyName, Class extends Annotation> annotation, Class extends StepListener> listenerInterface, Class>... paramTypes) {
this.methodName = methodName;
this.propertyName = propertyName;
this.annotation = annotation;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java
index 998216751..ab74b1044 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java
@@ -54,7 +54,7 @@ public class TaskExecutorPartitionHandler implements PartitionHandler, Initializ
private Step step;
public void afterPropertiesSet() throws Exception {
- Assert.notNull(step, "A Step must be provided.");
+// Assert.notNull(step, "A Step must be provided.");
}
/**
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/Chunk.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/Chunk.java
index bf0f80d01..936807fc1 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/Chunk.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/Chunk.java
@@ -26,8 +26,8 @@ import java.util.List;
* Encapsulation of a list of items to be processed and possibly a list of
* failed items to be skipped. To mark an item as skipped clients should iterate
* over the chunk using the {@link #iterator()} method, and if there is a
- * failure call {@link ChunkIterator#remove(Exception)} on the iterator. The
- * skipped items are then available through the chunk.
+ * failure call {@link org.springframework.batch.core.step.item.Chunk.ChunkIterator#remove()} on the iterator.
+ * The skipped items are then available through the chunk.
*
* @author Dave Syer
* @since 2.0
@@ -246,4 +246,4 @@ public class Chunk implements Iterable {
}
-}
\ No newline at end of file
+}
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd
index 593971a0e..090753d96 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd
@@ -453,6 +453,7 @@
+
stepNames = getStepNames(jobExecution);
- assertEquals(3, stepNames.size());
- assertEquals("[s1, step1:partition0, step1:partition1]", stepNames.toString());
- }
+ @Autowired
+ private JobRepository jobRepository;
- @Test
- public void testHandlerRefStep() throws Exception {
- assertNotNull(job2);
- JobExecution jobExecution = jobRepository.createJobExecution(job2.getName(), new JobParameters());
- job2.execute(jobExecution);
- assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
- List stepNames = getStepNames(jobExecution);
- assertEquals(5, stepNames.size());
- assertEquals("[s2, s3, step1:partition0, step1:partition1, step1:partition2]", stepNames.toString());
- }
+ @Autowired
+ private MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean;
- private List getStepNames(JobExecution jobExecution) {
- List list = new ArrayList();
- for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
- list.add(stepExecution.getStepName());
- }
- Collections.sort(list);
- return list;
- }
+ private ApplicationContext applicationContext;
+
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ @Before
+ public void setUp() {
+ mapJobRepositoryFactoryBean.clear();
+ }
+
+ @SuppressWarnings("unchecked")
+ private T accessPrivateField(Object o, String fieldName) {
+ Field field = ReflectionUtils.findField(o.getClass(), fieldName);
+ boolean previouslyAccessibleValue = field.isAccessible();
+ field.setAccessible(true);
+ T val = (T) ReflectionUtils.getField(field, o);
+ field.setAccessible(previouslyAccessibleValue);
+ return val;
+ }
+
+ /**
+ * BATCH-1509 we now support the ability define steps inline for partitioned steps.
+ * this demonstates that the execution proceeds as expected and that the partitionhandler has a reference to the inline step definition
+ */
+ @Test
+ public void testNestedPartitionStepStepReference() throws Throwable {
+ assertNotNull("the reference to the job3 configured in the XML file must not be null", job3);
+ JobExecution jobExecution = jobRepository.createJobExecution(job3.getName(), new JobParameters());
+
+ job3.execute(jobExecution);
+
+ for (StepExecution se : jobExecution.getStepExecutions()) {
+ String stepExecutionName = se.getStepName();
+ if (stepExecutionName.equalsIgnoreCase("j3s1")) { // the partitioned step
+ PartitionStep partitionStep = (PartitionStep) this.applicationContext.getBean(stepExecutionName);
+
+ // prove that the reference in the {@link TaskExecutorPartitionHandler} is the step configured inline
+ TaskExecutorPartitionHandler taskExecutorPartitionHandler = accessPrivateField(partitionStep, "partitionHandler");
+ TaskletStep taskletStep = accessPrivateField(taskExecutorPartitionHandler, "step");
+
+ assertNotNull("the taskletStep wasn't configured with a step. " +
+ "We're trusting that the factory ensured " +
+ "a reference was given.", taskletStep);
+ }
+ }
+ assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
+ }
+
+ @Test
+ public void testDefaultHandlerStep() throws Exception {
+ assertNotNull(job1);
+ JobExecution jobExecution = jobRepository.createJobExecution(job1.getName(), new JobParameters());
+ job1.execute(jobExecution);
+ assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
+ List stepNames = getStepNames(jobExecution);
+ assertEquals(3, stepNames.size());
+ assertEquals("[s1, step1:partition0, step1:partition1]", stepNames.toString());
+ }
+
+ @Test
+ public void testHandlerRefStep() throws Exception {
+ assertNotNull(job2);
+ JobExecution jobExecution = jobRepository.createJobExecution(job2.getName(), new JobParameters());
+ job2.execute(jobExecution);
+ assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
+ List stepNames = getStepNames(jobExecution);
+ assertEquals(5, stepNames.size());
+ assertEquals("[s2, s3, step1:partition0, step1:partition1, step1:partition2]", stepNames.toString());
+ }
+
+ private List getStepNames(JobExecution jobExecution) {
+ List list = new ArrayList();
+ for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
+ list.add(stepExecution.getStepName());
+ }
+ Collections.sort(list);
+ return list;
+ }
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java
index 2f4309b50..a39e38df1 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java
@@ -81,11 +81,9 @@ public class StepListenerFactoryBeanTests {
@Test
@SuppressWarnings("unchecked")
public void testStepAndChunk() throws Exception {
-
TestListener testListener = new TestListener();
factoryBean.setDelegate(testListener);
Map metaDataMap = new HashMap();
- ;
metaDataMap.put(AFTER_STEP.getPropertyName(), "destroy");
metaDataMap.put(AFTER_CHUNK.getPropertyName(), "afterChunk");
factoryBean.setMetaDataMap(metaDataMap);
diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml
index 114514d5a..7a931a393 100644
--- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml
+++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml
@@ -21,6 +21,15 @@
+
+
+
+
+
+
+
+
+
@@ -34,4 +43,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/classify/SubclassClassifier.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/classify/SubclassClassifier.java
index b19c04aae..a8d76800a 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/classify/SubclassClassifier.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/classify/SubclassClassifier.java
@@ -26,7 +26,7 @@ import java.util.TreeSet;
* A {@link Classifier} for a parameterised object type based on a map.
* Classifies objects according to their inheritance relation with the supplied
* type map. If the object to be classified is one of the keys of the provided
- * map, or is a subclass of one of the keys, then the map entry vale for that
+ * map, or is a subclass of one of the keys, then the map entry value for that
* key is returned. Otherwise returns the default value which is null by
* default.
*