diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java
index 8dfaf699c..318e38ed2 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java
@@ -16,6 +16,7 @@
package org.springframework.batch.core.configuration.xml;
import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.step.AbstractStep;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
@@ -50,7 +51,8 @@ public class CoreNamespacePostProcessor implements BeanPostProcessor, BeanFactor
private ApplicationContext applicationContext;
/**
- * Inject job-repository from a job into its steps.
+ * Automatically inject job-repository from a job into its steps. Only
+ * inject if the step is an AbstractStep or StepParserStepFactoryBean.
*
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
*/
@@ -59,30 +61,85 @@ public class CoreNamespacePostProcessor implements BeanPostProcessor, BeanFactor
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
MutablePropertyValues pvs = (MutablePropertyValues) bd.getPropertyValues();
if (pvs.contains(JOB_FACTORY_PROPERTY_NAME)) {
- String jobName = (String) pvs.getPropertyValue(JOB_FACTORY_PROPERTY_NAME).getValue();
- PropertyValue jobRepository = getJobRepository(beanFactory, jobName);
- if (jobRepository != null) {
- pvs.addPropertyValue(jobRepository);
- }
- else {
- RuntimeBeanReference jobRepositoryBeanRef = new RuntimeBeanReference(DEFAULT_JOB_REPOSITORY_NAME);
- pvs.addPropertyValue(JOB_REPOSITORY_PROPERTY_NAME, jobRepositoryBeanRef);
+ if (isAbstractStep(bd, beanFactory)) {
+ String jobName = (String) pvs.getPropertyValue(JOB_FACTORY_PROPERTY_NAME).getValue();
+ PropertyValue jobRepository = getJobRepository(jobName, beanFactory);
+ if (jobRepository != null) {
+ // Set the job's JobRepository onto the step
+ pvs.addPropertyValue(jobRepository);
+ }
+ else {
+ // No JobRepository found, so inject the default
+ RuntimeBeanReference jobRepositoryBeanRef = new RuntimeBeanReference(
+ DEFAULT_JOB_REPOSITORY_NAME);
+ pvs.addPropertyValue(JOB_REPOSITORY_PROPERTY_NAME, jobRepositoryBeanRef);
+ }
}
pvs.removePropertyValue(JOB_FACTORY_PROPERTY_NAME);
}
}
}
- private PropertyValue getJobRepository(ConfigurableListableBeanFactory beanFactory, String jobName) {
+ /**
+ * @param bd
+ * @param beanFactory
+ * @return TRUE if the bean represents an AbstractStep (or
+ * StepParserStepFactoryBean).
+ */
+ private boolean isAbstractStep(BeanDefinition bd, ConfigurableListableBeanFactory beanFactory) {
+ Class> stepClass = getClass(bd, beanFactory);
+ return StepParserStepFactoryBean.class.isAssignableFrom(stepClass)
+ || AbstractStep.class.isAssignableFrom(stepClass);
+ }
+
+ /**
+ * @param bd
+ * @param beanFactory
+ * @return The class of the bean. Search parent hierarchy if necessary.
+ * Return null if none is found.
+ */
+ private Class> getClass(BeanDefinition bd, ConfigurableListableBeanFactory beanFactory) {
+ // Get the declared class of the bean
+ String className = bd.getBeanClassName();
+ if (StringUtils.hasText(className)) {
+ try {
+ return Class.forName(className);
+ }
+ catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ else {
+ // Search the parent until you find it
+ String parentName = bd.getParentName();
+ if (StringUtils.hasText(parentName)) {
+ return getClass(beanFactory.getBeanDefinition(parentName), beanFactory);
+ }
+ else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * @param jobName
+ * @param beanFactory
+ * @return The {@link PropertyValue} for the {@link JobRepository} of the
+ * bean. Search parent hierarchy if necessary. Return null if none
+ * is found.
+ */
+ private PropertyValue getJobRepository(String jobName, ConfigurableListableBeanFactory beanFactory) {
BeanDefinition jobDef = beanFactory.getBeanDefinition(jobName);
PropertyValues jobDefPvs = jobDef.getPropertyValues();
if (jobDefPvs.contains(JOB_REPOSITORY_PROPERTY_NAME)) {
+ // return the job repository property
return jobDefPvs.getPropertyValue(JOB_REPOSITORY_PROPERTY_NAME);
}
else {
+ // Search the parent until you find it
String parentName = jobDef.getParentName();
if (StringUtils.hasText(parentName)) {
- return getJobRepository(beanFactory, parentName);
+ return getJobRepository(parentName, beanFactory);
}
else {
return null;
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStep.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStep.java
new file mode 100644
index 000000000..b5c1f625b
--- /dev/null
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStep.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006-2009 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 org.springframework.batch.core.JobInterruptedException;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.beans.factory.BeanNameAware;
+
+/**
+ * @author Dan Garrette
+ * @since 2.0.1
+ */
+public class DummyStep implements Step, BeanNameAware {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setBeanName(String name) {
+ this.name = name;
+ }
+
+ public void execute(StepExecution stepExecution) throws JobInterruptedException {
+ System.out.println("EXECUTING " + getName());
+ }
+
+ public int getStartLimit() {
+ return 100;
+ }
+
+ public boolean isAllowStartIfComplete() {
+ return false;
+ }
+}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java
index b3bb5163a..15a60632a 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java
@@ -308,4 +308,14 @@ public class StepParserTests {
}
return property;
}
+
+ @Test
+ public void testNonAbstractStep() {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml");
+
+ assertTrue(ctx.containsBean("s11"));
+ Object bean = ctx.getBean("s11");
+ assertTrue(bean instanceof DummyStep);
+ }
}
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 3e1cbc634..f830b1734 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
@@ -34,7 +34,8 @@
-
+
+
@@ -84,6 +85,8 @@
+
+