diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobContext.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobContext.java
index dcd63eb67..8574e06ac 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobContext.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobContext.java
@@ -17,6 +17,7 @@ package org.springframework.batch.core.jsr;
import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
import javax.batch.runtime.BatchStatus;
import org.springframework.batch.core.ExitStatus;
@@ -36,14 +37,14 @@ public class JobContext implements javax.batch.runtime.context.JobContext {
private Object transientUserData;
private Properties properties;
private JobExecution jobExecution;
+ private AtomicBoolean exitStatusSet = new AtomicBoolean();
- /**
- * @param jobExecution for the related job
- */
- public JobContext(JobExecution jobExecution, Properties properties) {
+ public void setJobExecution(JobExecution jobExecution) {
Assert.notNull(jobExecution, "A JobExecution is required");
-
this.jobExecution = jobExecution;
+ }
+
+ public void setProperties(Properties properties) {
this.properties = properties != null ? properties : new Properties();
}
@@ -108,7 +109,7 @@ public class JobContext implements javax.batch.runtime.context.JobContext {
*/
@Override
public String getExitStatus() {
- return jobExecution.getExitStatus().getExitCode();
+ return exitStatusSet.get() ? jobExecution.getExitStatus().getExitCode() : null;
}
/* (non-Javadoc)
@@ -117,5 +118,6 @@ public class JobContext implements javax.batch.runtime.context.JobContext {
@Override
public void setExitStatus(String status) {
jobExecution.setExitStatus(new ExitStatus(status));
+ exitStatusSet.set(true);
}
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyBeanPostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyBeanPostProcessor.java
index a6ccfbcd6..d5c03afc3 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyBeanPostProcessor.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyBeanPostProcessor.java
@@ -38,6 +38,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.expression.StandardBeanExpressionResolver;
import org.springframework.util.ReflectionUtils;
+import org.springframework.util.StringUtils;
/**
*
@@ -114,7 +115,7 @@ public class BatchPropertyBeanPostProcessor implements BeanPostProcessor, BeanFa
String batchProperty = getBatchPropertyFieldValue(field, artifactProperties);
- if (batchProperty != null) {
+ if (StringUtils.hasText(batchProperty)) {
field.set(artifact, batchProperty);
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyContext.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyContext.java
index 7b6312591..0e0d4d3b3 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyContext.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyContext.java
@@ -106,6 +106,7 @@ public class BatchPropertyContext {
*/
public Properties getStepArtifactProperties(String stepName, String artifactName) {
Properties properties = new Properties();
+ properties.putAll(getJobProperties());
properties.putAll(getStepProperties(stepName));
Map artifactProperties = stepArtifactProperties.get(stepName);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/JobParameterResolvingBeanFactoryPostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/JobParameterResolvingBeanFactoryPostProcessor.java
index ab6a24640..a8920458b 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/JobParameterResolvingBeanFactoryPostProcessor.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/JobParameterResolvingBeanFactoryPostProcessor.java
@@ -67,12 +67,12 @@ public class JobParameterResolvingBeanFactoryPostProcessor implements BeanFactor
}
/**
- * Sets this {@link BeanFactoryPostProcessor} to the lowest precedence so that
- * it is executed as late as possible in the chain of {@link BeanFactoryPostProcessor}s
+ * Sets this {@link BeanFactoryPostProcessor} to the highest precedence so that
+ * it is executed as early as possible in the chain of {@link BeanFactoryPostProcessor}s
*/
@Override
public int getOrder() {
- return PriorityOrdered.LOWEST_PRECEDENCE;
+ return PriorityOrdered.HIGHEST_PRECEDENCE;
}
protected class JobParameterResolver {
@@ -98,7 +98,7 @@ public class JobParameterResolvingBeanFactoryPostProcessor implements BeanFactor
@Override
public String resolveStringValue(String value) {
if (value != null && ! "".equals(value)) {
- String resolvedString = resolveJobProperties(value);
+ String resolvedString = resolveJobParameters(value);
if (!"".equals(resolvedString)) {
return jsrExpressionParser.parseExpression(resolvedString);
@@ -108,7 +108,7 @@ public class JobParameterResolvingBeanFactoryPostProcessor implements BeanFactor
return value;
}
- private String resolveJobProperties(String value) {
+ private String resolveJobParameters(String value) {
StringBuffer valueBuffer = new StringBuffer();
Matcher jobParameterMatcher = JOB_PARAMETERS_PATTERN.matcher(value);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/FlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/FlowParser.java
index ac01e6ad2..94993a28d 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/FlowParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/FlowParser.java
@@ -41,13 +41,25 @@ import org.w3c.dom.NodeList;
* as it is within a regular Spring Batch job/flow.
*
* @author Michael Minella
+ * @author Chris Schaefer
* @since 3.0
*/
public class FlowParser extends AbstractFlowParser {
-
private static final String DECISION_ELEMENT = "decision";
private static final String SPLIT_ELEMENT = "split";
private static final String STEP_ELEMENT = "step";
+ private static final String FLOW_ELEMENT = "flow";
+ private static final String ID_ATTRIBUTE = "id";
+ private static final String NEXT_ATTRIBUTE = "next";
+ private static final String STOP_ATTRIBUTE = "stop";
+ private static final String FAIL_ATTRIBUTE = "fail";
+ private static final String END_ATTRIBUTE = "end";
+ private static final String ON_ATTRIBUTE = "on";
+ private static final String TO_ATTRIBUTE = "to";
+ private static final String RESTART_ATTRIBUTE = "restart";
+ private static final String EXIT_STATUS_ATTRIBUTE = "exit-status";
+
+ private String jobFactoryRef;
private StepParser stepParser = new StepParser();
private String flowName;
@@ -57,6 +69,7 @@ public class FlowParser extends AbstractFlowParser {
*/
public FlowParser(String flowName, String jobFactoryRef) {
super.setJobFactoryRef(jobFactoryRef);
+ this.jobFactoryRef = jobFactoryRef;
this.flowName = flowName;
}
@@ -86,6 +99,12 @@ public class FlowParser extends AbstractFlowParser {
stateTransitions.addAll(new SplitParser(flowName).parse(child, parserContext));
} else if(nodeName.equals(DECISION_ELEMENT)) {
stateTransitions.addAll(new DecisionParser().parse(child, parserContext, flowName));
+ } else if(nodeName.equals(FLOW_ELEMENT)) {
+ org.springframework.batch.core.jsr.configuration.xml.InlineFlowParser flowParser =
+ new org.springframework.batch.core.jsr.configuration.xml.InlineFlowParser(child.getAttribute(ID_ATTRIBUTE), jobFactoryRef);
+ flowParser.parse(child, parserContext);
+
+ stateTransitions.addAll(parseFlow(child, parserContext));
}
}
}
@@ -103,6 +122,19 @@ public class FlowParser extends AbstractFlowParser {
builder.addPropertyValue("stateTransitions", managedList);
}
+ private Collection parseFlow(Element element, ParserContext parserContext) {
+ String idAttribute = element.getAttribute(ID_ATTRIBUTE);
+
+ BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder
+ .genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.FlowState");
+
+ FlowParser flowParser = new FlowParser(idAttribute, jobFactoryRef);
+
+ stateBuilder.addConstructorArgValue(flowParser.parse(element, parserContext));
+ stateBuilder.addConstructorArgValue(idAttribute);
+
+ return FlowParser.getNextElements(parserContext, null, stateBuilder.getBeanDefinition(), element);
+ }
public static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef,
Element element) {
@@ -114,7 +146,7 @@ public class FlowParser extends AbstractFlowParser {
Collection list = new ArrayList();
- String shortNextAttribute = element.getAttribute("next");
+ String shortNextAttribute = element.getAttribute(NEXT_ATTRIBUTE);
boolean hasNextAttribute = StringUtils.hasText(shortNextAttribute);
if (hasNextAttribute) {
list.add(getStateTransitionReference(parserContext, stateDef, null, shortNextAttribute));
@@ -122,7 +154,7 @@ public class FlowParser extends AbstractFlowParser {
boolean transitionElementExists = false;
List patterns = new ArrayList();
- for (String transitionName : new String[] { "next", "stop", "end", "fail" }) {
+ for (String transitionName : new String[] { NEXT_ATTRIBUTE, STOP_ATTRIBUTE, END_ATTRIBUTE, FAIL_ATTRIBUTE }) {
List transitionElements = DomUtils.getChildElementsByTagName(element, transitionName);
for (Element transitionElement : transitionElements) {
verifyUniquePattern(transitionElement, patterns, element, parserContext);
@@ -152,16 +184,18 @@ public class FlowParser extends AbstractFlowParser {
protected static Collection parseTransitionElement(Element transitionElement, String stateId,
BeanDefinition stateDef, ParserContext parserContext) {
-
FlowExecutionStatus status = getBatchStatusFromEndTransitionName(transitionElement.getNodeName());
- String onAttribute = transitionElement.getAttribute("on");
- String restartAttribute = transitionElement.getAttribute("restart");
- String nextAttribute = transitionElement.getAttribute("to");
+ String onAttribute = transitionElement.getAttribute(ON_ATTRIBUTE);
+ String restartAttribute = transitionElement.getAttribute(RESTART_ATTRIBUTE);
+ String nextAttribute = transitionElement.getAttribute(TO_ATTRIBUTE);
+
if (!StringUtils.hasText(nextAttribute)) {
nextAttribute = restartAttribute;
}
+
boolean abandon = stateId != null && StringUtils.hasText(restartAttribute) && !restartAttribute.equals(stateId);
- String exitCodeAttribute = transitionElement.getAttribute("exit-status");
+ String exitCodeAttribute = transitionElement.getAttribute(EXIT_STATUS_ATTRIBUTE);
return createTransition(status, onAttribute, nextAttribute, exitCodeAttribute, stateDef, parserContext, abandon);
- }}
+ }
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/InlineFlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/InlineFlowParser.java
new file mode 100644
index 000000000..ec4637711
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/InlineFlowParser.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2013 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.jsr.configuration.xml;
+
+import org.springframework.batch.core.job.flow.support.DefaultStateTransitionComparator;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+/**
+ *
+ * Parses a flow element in a JSR-352 job defintion.
+ *
+ *
+ * @author Chris Schaefer
+ * @since 3.0
+ */
+public class InlineFlowParser extends FlowParser {
+ private final String flowName;
+
+ /**
+ * Construct a {@link InlineFlowParser} with the specified name and using the
+ * provided job repository ref.
+ *
+ * @param flowName the name of the flow
+ * @param jobFactoryRef the reference to the {@link org.springframework.batch.core.configuration.xml.JobParserJobFactoryBean}
+ * from the enclosing tag
+ */
+ public InlineFlowParser(String flowName, String jobFactoryRef) {
+ super(flowName, jobFactoryRef);
+ this.flowName = flowName;
+ }
+
+ /**
+ * Parses the flow from the provided {@link Element}.
+ *
+ * @param element the top level element containing a flow definition
+ * @param parserContext the {@link org.springframework.beans.factory.xml.ParserContext}
+ * @param builder the {@link BeanDefinitionBuilder} to handle bean defintion operations
+ */
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ builder.getRawBeanDefinition().setAttribute("flowName", flowName);
+ builder.addPropertyValue("name", flowName);
+ builder.addPropertyValue("stateTransitionComparator", new RuntimeBeanReference(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR));
+ super.doParse(element, parserContext, builder);
+ builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+ }
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/ListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/ListenerParser.java
index 82b0e1154..ec3af3c12 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/ListenerParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/ListenerParser.java
@@ -18,10 +18,12 @@ package org.springframework.batch.core.jsr.configuration.xml;
import java.util.List;
import org.springframework.batch.core.jsr.configuration.support.BatchArtifact;
+import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
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.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
@@ -84,6 +86,8 @@ public class ListenerParser {
BeanDefinitionBuilder bd = BeanDefinitionBuilder.genericBeanDefinition(listenerType);
bd.addPropertyValue("delegate", new RuntimeBeanReference(beanName));
+ applyListenerScope(beanName, parserContext.getRegistry());
+
listeners.add(bd.getBeanDefinition());
new PropertyParser(beanName, parserContext, getBatchArtifactType(stepName), stepName).parseProperties(listenerElement);
@@ -98,6 +102,15 @@ public class ListenerParser {
return listeners;
}
+ protected void applyListenerScope(String beanName, BeanDefinitionRegistry beanDefinitionRegistry) {
+ if (listenerType == JobListenerFactoryBean.class) {
+ if (beanDefinitionRegistry.containsBeanDefinition(beanName)) {
+ BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition(beanName);
+ beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
+ }
+ }
+ }
+
private BatchArtifact.BatchArtifactType getBatchArtifactType(String stepName) {
return (stepName != null && !"".equals(stepName)) ? BatchArtifact.BatchArtifactType.STEP_ARTIFACT
: BatchArtifact.BatchArtifactType.ARTIFACT;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/launch/JsrJobOperator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/launch/JsrJobOperator.java
index d0de1d8d2..13efbff67 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/launch/JsrJobOperator.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/launch/JsrJobOperator.java
@@ -55,6 +55,8 @@ import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.context.support.GenericXmlApplicationContext;
@@ -120,6 +122,7 @@ import org.springframework.util.Assert;
*/
public class JsrJobOperator implements JobOperator, InitializingBean {
private static final String BATCH_PROPERTY_CONTEXT_BEAN_NAME = "batchPropertyContext";
+ private static final String JSR_JOB_CONTEXT_BEAN_NAME = "jsr_jobContext";
private org.springframework.batch.core.launch.JobOperator batchJobOperator;
private JobExplorer jobExplorer;
@@ -456,12 +459,16 @@ public class JsrJobOperator implements JobOperator, InitializingBean {
}
batchContext.addBeanFactoryPostProcessor(new JobParameterResolvingBeanFactoryPostProcessor(params));
+
+ AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.jsr.JobContext").getBeanDefinition();
+ batchContext.registerBeanDefinition(JSR_JOB_CONTEXT_BEAN_NAME, beanDefinition);
+
batchContext.setParent(baseContext);
try {
batchContext.refresh();
} catch (BeanCreationException e) {
- throw new JobStartException(e);
+ throw new JobRestartException(e);
}
final Job job = batchContext.getBean(Job.class);
@@ -486,7 +493,9 @@ public class JsrJobOperator implements JobOperator, InitializingBean {
BatchPropertyContext batchPropertyContext = factory.getBean(BATCH_PROPERTY_CONTEXT_BEAN_NAME, BatchPropertyContext.class);
Properties properties = batchPropertyContext.getJobProperties();
- factory.registerSingleton(job.getName() + "_" + jobExecution.getId() + "_jobContext", new JobContext(jobExecution, properties));
+ JobContext jobContext = factory.getBean(JSR_JOB_CONTEXT_BEAN_NAME, JobContext.class);
+ jobContext.setJobExecution(jobExecution);
+ jobContext.setProperties(properties);
taskExecutor.execute(new Runnable() {
@@ -562,6 +571,10 @@ public class JsrJobOperator implements JobOperator, InitializingBean {
}
batchContext.addBeanFactoryPostProcessor(new JobParameterResolvingBeanFactoryPostProcessor(params));
+
+ AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.jsr.JobContext").getBeanDefinition();
+ batchContext.registerBeanDefinition(JSR_JOB_CONTEXT_BEAN_NAME, beanDefinition);
+
batchContext.setParent(baseContext);
try {
@@ -590,7 +603,9 @@ public class JsrJobOperator implements JobOperator, InitializingBean {
BatchPropertyContext batchPropertyContext = factory.getBean(BATCH_PROPERTY_CONTEXT_BEAN_NAME, BatchPropertyContext.class);
Properties properties = batchPropertyContext.getJobProperties();
- factory.registerSingleton(job.getName() + "_" + jobExecution.getId() + "_jobContext", new JobContext(jobExecution, properties));
+ JobContext jobContext = factory.getBean(JSR_JOB_CONTEXT_BEAN_NAME, JobContext.class);
+ jobContext.setJobExecution(jobExecution);
+ jobContext.setProperties(properties);
taskExecutor.execute(new Runnable() {
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java
index 211eebdd4..ac529598d 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java
@@ -47,6 +47,7 @@ import org.springframework.util.ClassUtils;
* @author Ben Hale
* @author Robert Kasanicky
* @author Michael Minella
+ * @author Chris Schaefer
*/
public abstract class AbstractStep implements Step, InitializingBean, BeanNameAware {
@@ -114,7 +115,7 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
* @param startLimit the startLimit to set
*/
public void setStartLimit(int startLimit) {
- this.startLimit = startLimit;
+ this.startLimit = startLimit == 0 ? Integer.MAX_VALUE : startLimit;
}
@Override
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobContextTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobContextTests.java
index d01de801a..4e74d0cca 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobContextTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobContextTests.java
@@ -44,16 +44,20 @@ public class JobContextTests {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- Properties properties = new Properties();
- properties.put("jobLevelProperty1", "jobLevelValue1");
+ Properties properties = new Properties();
+ properties.put("jobLevelProperty1", "jobLevelValue1");
+
+ context = new JobContext();
+ context.setProperties(properties);
+ context.setJobExecution(execution);
- context = new JobContext(execution, properties);
when(execution.getJobInstance()).thenReturn(instance);
}
@Test(expected=IllegalArgumentException.class)
public void testCreateWithNull() {
- context = new JobContext(null, null);
+ context = new JobContext();
+ context.setJobExecution(null);
}
@Test
@@ -91,12 +95,12 @@ public class JobContextTests {
when(execution.getJobParameters()).thenReturn(params);
- assertEquals("value1", execution.getJobParameters().getString("key1"));
+ assertEquals("value1", execution.getJobParameters().getString("key1"));
}
@Test
public void testJobProperties() {
- assertEquals("jobLevelValue1", context.getProperties().get("jobLevelProperty1"));
+ assertEquals("jobLevelValue1", context.getProperties().get("jobLevelProperty1"));
}
@Test
@@ -108,12 +112,16 @@ public class JobContextTests {
@Test
public void testExitStatus() {
- when(execution.getExitStatus()).thenReturn(new ExitStatus("exit"));
-
- assertEquals("exit", context.getExitStatus());
-
context.setExitStatus("my exit status");
-
verify(execution).setExitStatus(new ExitStatus("my exit status"));
+
+ when(execution.getExitStatus()).thenReturn(new ExitStatus("exit"));
+ assertEquals("exit", context.getExitStatus());
+ }
+
+ @Test
+ public void testInitialNullExitStatus() {
+ when(execution.getExitStatus()).thenReturn(new ExitStatus("exit"));
+ assertEquals(null, context.getExitStatus());
}
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyContextTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyContextTests.java
index 9b18aad86..84d02b1ca 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyContextTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyContextTests.java
@@ -170,11 +170,13 @@ public class BatchPropertyContextTests {
batchPropertyContext.setStepArtifactPropertiesContextEntry(stepArtifactProperties);
Properties artifactProperties = batchPropertyContext.getStepArtifactProperties("step1", "reader");
- assertEquals(4, artifactProperties.size());
+ assertEquals(6, artifactProperties.size());
assertEquals("readerProperty1value", artifactProperties.getProperty("readerProperty1"));
assertEquals("readerProperty2value", artifactProperties.getProperty("readerProperty2"));
assertEquals("step1PropertyValue1", artifactProperties.getProperty("step1PropertyName1"));
assertEquals("step1PropertyValue2", artifactProperties.getProperty("step1PropertyName2"));
+ assertEquals("jobProperty1value", artifactProperties.getProperty("jobProperty1"));
+ assertEquals("jobProperty2value", artifactProperties.getProperty("jobProperty2"));
}
@Test
@@ -213,12 +215,14 @@ public class BatchPropertyContextTests {
batchPropertyContext.setStepArtifactPropertiesContextEntry(partitionProperties);
Properties artifactProperties = batchPropertyContext.getStepArtifactProperties("step2:partition0", "writer");
- assertEquals(6, artifactProperties.size());
+ assertEquals(8, artifactProperties.size());
assertEquals("writerProperty1", artifactProperties.getProperty("writerProperty1Step"));
assertEquals("writerProperty2", artifactProperties.getProperty("writerProperty2Step"));
assertEquals("writerProperty1valuePartition0", artifactProperties.getProperty("writerProperty1"));
assertEquals("writerProperty2valuePartition0", artifactProperties.getProperty("writerProperty2"));
assertEquals("step2PropertyValue1", artifactProperties.getProperty("step2PropertyName1"));
assertEquals("step2PropertyValue2", artifactProperties.getProperty("step2PropertyName2"));
+ assertEquals("jobProperty1value", artifactProperties.getProperty("jobProperty1"));
+ assertEquals("jobProperty2value", artifactProperties.getProperty("jobProperty2"));
}
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/ListenerParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/ListenerParserTests.java
new file mode 100644
index 000000000..56026c4d0
--- /dev/null
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/ListenerParserTests.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 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.jsr.configuration.xml;
+
+import org.junit.Test;
+import org.springframework.batch.core.listener.StepListenerFactoryBean;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.context.support.GenericApplicationContext;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ * Test cases around scoping of job/step listeners when building their bean definitions.
+ *
+ *
+ * @author Chris Schaefer
+ */
+public class ListenerParserTests {
+ @Test
+ public void testStepListenerStepScoped() {
+ GenericApplicationContext applicationContext = new GenericApplicationContext();
+
+ AbstractBeanDefinition newBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition("stepListener").getBeanDefinition();
+ newBeanDefinition.setScope("step");
+
+ applicationContext.registerBeanDefinition("stepListener", newBeanDefinition);
+
+ ListenerParser listenerParser = new ListenerParser(StepListenerFactoryBean.class, "listeners");
+ listenerParser.applyListenerScope("stepListener", applicationContext);
+
+ BeanDefinition beanDefinition = applicationContext.getBeanDefinition("stepListener");
+ assertEquals("step", beanDefinition.getScope());
+ }
+
+ @Test
+ public void testJobListenerSingletonScoped() {
+ GenericApplicationContext applicationContext = new GenericApplicationContext();
+
+ AbstractBeanDefinition newBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition("jobListener").getBeanDefinition();
+ newBeanDefinition.setScope("step");
+
+ applicationContext.registerBeanDefinition("jobListener", newBeanDefinition);
+
+ ListenerParser listenerParser = new ListenerParser(JobListenerFactoryBean.class, "jobExecutionListeners");
+ listenerParser.applyListenerScope("jobListener", applicationContext);
+
+ BeanDefinition beanDefinition = applicationContext.getBeanDefinition("jobListener");
+ assertEquals("singleton", beanDefinition.getScope());
+ }
+}