diff --git a/spring-batch-core/.springBeans b/spring-batch-core/.springBeans
index e3950f15b..7e376f2b9 100644
--- a/spring-batch-core/.springBeans
+++ b/spring-batch-core/.springBeans
@@ -54,7 +54,6 @@
src/test/resources/org/springframework/batch/core/configuration/xml/StopIncompleteJobParserTests-context.xml
src/test/resources/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForJobElementTests-context.xml
src/test/resources/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForStepElementTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryContextTests-context.xml
src/test/resources/org/springframework/batch/core/configuration/xml/StopAndRestartJobParserTests-context.xml
src/test/resources/org/springframework/batch/core/configuration/xml/StopRestartOnCompletedStepJobParserTests-context.xml
src/test/resources/org/springframework/batch/core/configuration/xml/StopRestartOnFailedStepJobParserTests-context.xml
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoader.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoader.java
new file mode 100644
index 000000000..c088194cc
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoader.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2006-2007 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.support;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.configuration.DuplicateJobException;
+import org.springframework.batch.core.configuration.JobFactory;
+import org.springframework.batch.core.configuration.JobLocator;
+import org.springframework.batch.core.configuration.JobRegistry;
+import org.springframework.batch.core.configuration.ListableJobLocator;
+import org.springframework.batch.core.launch.NoSuchJobException;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.core.io.Resource;
+import org.springframework.util.Assert;
+
+/**
+ * Implementation of the {@link ListableJobLocator} interface that assumes all
+ * Jobs will be loaded from class path xml resources. Each resource provided is
+ * loaded as an application context with the current context as its parent, and
+ * then all the jobs from the child context are registered under their bean
+ * names. A {@link JobRegistry} is required, but if there is a unique one
+ * available in the current application context, then that will be used by
+ * default.
+ *
+ * @author Lucas Ward
+ * @author Dave Syer
+ *
+ * @since 2.0
+ * @since 2.1 this class does not implement {@link JobRegistry}
+ */
+public class ClassPathXmlJobLoader implements ApplicationContextAware, InitializingBean, DisposableBean,
+ ApplicationListener {
+
+ private static Log logger = LogFactory.getLog(ClassPathXmlJobLoader.class);
+
+ private List jobPaths;
+
+ private ApplicationContext parent;
+
+ private JobRegistry jobRegistry;
+
+ private Collection contexts = new HashSet();
+
+ /**
+ * A set of resources to load. Each resource should be a Spring
+ * configuration file which is loaded into an application context whose
+ * parent is the current context. In a configuration file the resources can
+ * be given as a pattern (e.g.
+ * classpath*:/config/*-job-context.xml).
+ *
+ * @param jobPaths
+ */
+ public void setJobPaths(Resource[] jobPaths) {
+ this.jobPaths = Arrays.asList(jobPaths);
+ }
+
+ /**
+ * The {@link JobRegistry} to use for jobs created. If not provided an
+ * instance will be discovered from the application context.
+ *
+ * @param jobRegistry
+ */
+ public void setJobRegistry(JobRegistry jobRegistry) {
+ this.jobRegistry = jobRegistry;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.context.ApplicationContextAware#setApplicationContext
+ * (org.springframework.context.ApplicationContext)
+ */
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ parent = applicationContext;
+ }
+
+ /**
+ * Initialize the {@link JobRegistry} if not already injected. Attempts to
+ * discover a registry from the application context, searching for a unique
+ * bean of type {@link JobRegistry}.
+ *
+ * @throws Exception
+ */
+ public void afterPropertiesSet() throws Exception {
+
+ if (jobRegistry == null) {
+ String[] names = parent.getBeanNamesForType(JobRegistry.class);
+ Assert.state(names.length == 1, "Precisely one bean of type JobRegistry is required. Found = "
+ + names.length);
+ jobRegistry = (JobRegistry) parent.getBean(names[0]);
+ }
+
+ }
+
+ /**
+ * Create all the application contexts required and set up job registry
+ * entries with all the instances of {@link Job} found therein.
+ *
+ * @see InitializingBean#afterPropertiesSet()
+ */
+ public final void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof ContextRefreshedEvent && event.getSource() == parent) {
+ try {
+ initialize();
+ }
+ catch (DuplicateJobException e) {
+ throw new IllegalStateException(e);
+ }
+ catch (NoSuchJobException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ /**
+ * Create jobs as instructed and register them so they can be accessed via
+ * the {@link JobLocator} interface. Normally called from
+ * {@link #onApplicationEvent(ApplicationEvent)} when the parent context is
+ * refreshed.
+ *
+ * @throws DuplicateJobException if the job registry detects a duplicate job
+ * @throws NoSuchJobException if no jobs are registered, since this is
+ * usually an error
+ */
+ protected void initialize() throws DuplicateJobException, NoSuchJobException {
+
+ for (Resource resource : jobPaths) {
+
+ ConfigurableApplicationContext context = createApplicationContext(parent, resource);
+ contexts.add(context);
+ String[] names = context.getBeanNamesForType(Job.class);
+
+ for (String name : names) {
+ logger.debug("Registering job: " + name + " from context: " + resource);
+ JobFactory jobFactory = new ReferenceJobFactory((Job) context.getBean(name));
+ jobRegistry.register(jobFactory);
+ }
+
+ }
+
+ if (jobRegistry.getJobNames().isEmpty()) {
+ throw new NoSuchJobException("Could not locate any jobs in resources provided.");
+ }
+
+ }
+
+ /**
+ * Create an application context from the resource provided. Extension point
+ * for subclasses if they need to customize the context in any way. The
+ * default uses a {@link ClassPathXmlApplicationContextFactory}.
+ *
+ * @param parent the parent application context (or null if there is none)
+ * @param resource the location of the XML configuration
+ *
+ * @return an application context containing jobs
+ */
+ protected ConfigurableApplicationContext createApplicationContext(ApplicationContext parent, Resource resource) {
+ ClassPathXmlApplicationContextFactory applicationContextFactory = new ClassPathXmlApplicationContextFactory();
+ applicationContextFactory.setPath(resource);
+ if (parent != null) {
+ applicationContextFactory.setApplicationContext(parent);
+ }
+ return applicationContextFactory.createApplicationContext();
+ }
+
+ /**
+ * Close the contexts that were created in {@link #afterPropertiesSet()}.
+ *
+ * @see DisposableBean#destroy()
+ */
+ public void destroy() throws Exception {
+
+ for (ConfigurableApplicationContext context : contexts) {
+ if (context.isActive()) {
+ context.close();
+ }
+ }
+ for (String jobName : jobRegistry.getJobNames()) {
+ jobRegistry.unregister(jobName);
+ }
+ contexts.clear();
+
+ }
+
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistry.java
index 70648b83f..d215727ff 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistry.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistry.java
@@ -1,200 +1,12 @@
-/*
- * Copyright 2006-2007 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.support;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.batch.core.Job;
-import org.springframework.batch.core.configuration.DuplicateJobException;
-import org.springframework.batch.core.configuration.JobFactory;
-import org.springframework.batch.core.configuration.JobLocator;
-import org.springframework.batch.core.configuration.JobRegistry;
-import org.springframework.batch.core.configuration.ListableJobLocator;
-import org.springframework.batch.core.launch.NoSuchJobException;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.ApplicationEvent;
-import org.springframework.context.ApplicationListener;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.context.event.ContextRefreshedEvent;
-import org.springframework.core.io.Resource;
-
/**
- * Implementation of the {@link ListableJobLocator} interface that assumes all
- * Jobs will be loaded from class path xml resources. Each resource provided is
- * loaded as an application context with the current context as its parent, and
- * then all the jobs from the child context are registered under their bean
- * names. Care must be taken to avoid duplicate names.
+ * Placeholder for deprecation warning.
*
- * @author Lucas Ward
* @author Dave Syer
- *
- * @since 2.0
- * @since 2.1 this class does not implement {@link JobRegistry}: it is a
- * {@link ListableJobLocator}
+ *
+ * @deprecated in version 2.1, please us {@link ClassPathXmlJobLoader} instead
*/
-public class ClassPathXmlJobRegistry implements ListableJobLocator, ApplicationContextAware, DisposableBean,
- ApplicationListener {
-
- private static Log logger = LogFactory.getLog(ClassPathXmlJobRegistry.class);
-
- private List jobPaths;
-
- private ApplicationContext parent;
-
- private JobRegistry jobRegistry = new MapJobRegistry();
-
- private Collection contexts = new HashSet();
-
- /**
- * A set of resources to load. Each resource should be a Spring
- * configuration file which is loaded into an application context whose
- * parent is the current context. In a configuration file the resources can
- * be given as a pattern (e.g.
- * classpath*:/config/*-job-context.xml).
- *
- * @param jobPaths
- */
- public void setJobPaths(Resource[] jobPaths) {
- this.jobPaths = Arrays.asList(jobPaths);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.springframework.context.ApplicationContextAware#setApplicationContext
- * (org.springframework.context.ApplicationContext)
- */
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- parent = applicationContext;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.springframework.batch.core.configuration.JobLocator#getJob(java.lang
- * .String)
- */
- public Job getJob(String name) throws NoSuchJobException {
- return jobRegistry.getJob(name);
- }
-
- public Collection getJobNames() {
- return jobRegistry.getJobNames();
- }
-
- /**
- * Create all the application contexts required and set up job registry
- * entries with all the instances of {@link Job} found therein.
- *
- * @see InitializingBean#afterPropertiesSet()
- */
- public final void onApplicationEvent(ApplicationEvent event) {
- if (event instanceof ContextRefreshedEvent && event.getSource() == parent) {
- try {
- initialize();
- }
- catch (DuplicateJobException e) {
- throw new IllegalStateException(e);
- }
- catch (NoSuchJobException e) {
- throw new IllegalStateException(e);
- }
- }
- }
-
- /**
- * Create jobs as instructed and register them so they can be accessed via
- * the {@link JobLocator} interface. Normally called from
- * {@link #onApplicationEvent(ApplicationEvent)} when the parent context is
- * refreshed.
- *
- * @throws DuplicateJobException if the job registry detects a duplicate job
- * @throws NoSuchJobException if no jobs are registered, since this is
- * usually an error
- */
- protected void initialize() throws DuplicateJobException, NoSuchJobException {
-
- for (Resource resource : jobPaths) {
-
- ConfigurableApplicationContext context = createApplicationContext(parent, resource);
- contexts.add(context);
- String[] names = context.getBeanNamesForType(Job.class);
-
- for (String name : names) {
- logger.debug("Registering job: " + name + " from context: " + resource);
- JobFactory jobFactory = new ReferenceJobFactory((Job) context.getBean(name));
- jobRegistry.register(jobFactory);
- }
-
- }
-
- if (jobRegistry.getJobNames().isEmpty()) {
- throw new NoSuchJobException("Could not locate any jobs in resources provided.");
- }
-
- }
-
- /**
- * Create an application context from the resource provided. Extension point
- * for subclasses if they need to customize the context in any way. The
- * default uses a {@link ClassPathXmlApplicationContextFactory}.
- *
- * @param parent the parent application context (or null if there is none)
- * @param resource the location of the XML configuration
- *
- * @return an application context containing jobs
- */
- protected ConfigurableApplicationContext createApplicationContext(ApplicationContext parent, Resource resource) {
- ClassPathXmlApplicationContextFactory applicationContextFactory = new ClassPathXmlApplicationContextFactory();
- applicationContextFactory.setPath(resource);
- if (parent != null) {
- applicationContextFactory.setApplicationContext(parent);
- }
- return applicationContextFactory.createApplicationContext();
- }
-
- /**
- * Close the contexts that were created in {@link #afterPropertiesSet()}.
- *
- * @see DisposableBean#destroy()
- */
- public void destroy() throws Exception {
-
- for (ConfigurableApplicationContext context : contexts) {
- if (context.isActive()) {
- context.close();
- }
- }
- for (String jobName : jobRegistry.getJobNames()) {
- jobRegistry.unregister(jobName);
- }
- contexts.clear();
-
- }
+public abstract class ClassPathXmlJobRegistry {
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryContextTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoaderContextTests.java
similarity index 85%
rename from spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryContextTests.java
rename to spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoaderContextTests.java
index b45cac070..3b5c52b4b 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryContextTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoaderContextTests.java
@@ -8,6 +8,7 @@ import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.Job;
+import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -20,10 +21,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
-public class ClassPathXmlJobRegistryContextTests {
+public class ClassPathXmlJobLoaderContextTests {
@Autowired
- private ClassPathXmlJobRegistry registry;
+ private JobRegistry registry;
@Test
public void testLocateJob() throws Exception{
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoaderTests.java
similarity index 67%
rename from spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryTests.java
rename to spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoaderTests.java
index 00e13a622..528f2803c 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoaderTests.java
@@ -6,10 +6,12 @@ import static org.junit.Assert.fail;
import java.util.Collection;
+import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
@@ -20,9 +22,15 @@ import org.springframework.core.io.Resource;
* @author Lucas Ward
*
*/
-public class ClassPathXmlJobRegistryTests {
+public class ClassPathXmlJobLoaderTests {
- private ClassPathXmlJobRegistry registry = new ClassPathXmlJobRegistry();
+ private ClassPathXmlJobLoader loader = new ClassPathXmlJobLoader();
+ private MapJobRegistry registry = new MapJobRegistry();
+
+ @Before
+ public void setUp() {
+ loader.setJobRegistry(registry);
+ }
@Test
public void testLocateJob() throws Exception {
@@ -31,11 +39,11 @@ public class ClassPathXmlJobRegistryTests {
new ClassPathResource("org/springframework/batch/core/launch/support/job.xml"),
new ClassPathResource("org/springframework/batch/core/launch/support/job2.xml") };
- registry.setJobPaths(jobPaths);
+ loader.setJobPaths(jobPaths);
GenericApplicationContext applicationContext = new GenericApplicationContext();
applicationContext.refresh();
- registry.setApplicationContext(applicationContext);
- registry.initialize();
+ loader.setApplicationContext(applicationContext);
+ loader.initialize();
Collection names = registry.getJobNames();
assertEquals(2, names.size());
@@ -53,11 +61,11 @@ public class ClassPathXmlJobRegistryTests {
Resource[] jobPaths = new Resource[] { new ClassPathResource(
"org/springframework/batch/core/launch/support/test-environment.xml") };
- registry.setJobPaths(jobPaths);
+ loader.setJobPaths(jobPaths);
GenericApplicationContext applicationContext = new GenericApplicationContext();
applicationContext.refresh();
- registry.setApplicationContext(applicationContext);
- registry.initialize();
+ loader.setApplicationContext(applicationContext);
+ loader.initialize();
}
@Test
@@ -65,11 +73,23 @@ public class ClassPathXmlJobRegistryTests {
Resource[] jobPaths = new Resource[] { new ClassPathResource(
"org/springframework/batch/core/launch/support/2jobs.xml") };
- registry.setJobPaths(jobPaths);
+ loader.setJobPaths(jobPaths);
GenericApplicationContext applicationContext = new GenericApplicationContext();
applicationContext.refresh();
- registry.setApplicationContext(applicationContext);
- registry.initialize();
+ loader.setApplicationContext(applicationContext);
+ loader.initialize();
+ assertEquals(2, registry.getJobNames().size());
+ }
+
+ @Test
+ public void testChildContextOverridesBeanPostProcessor() throws Exception {
+
+ Resource[] jobPaths = new Resource[] { new ClassPathResource(
+ "org/springframework/batch/core/launch/support/2jobs.xml") };
+ loader.setApplicationContext(new ClassPathXmlApplicationContext(
+ "/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml"));
+ loader.setJobPaths(jobPaths);
+ loader.initialize();
assertEquals(2, registry.getJobNames().size());
}
@@ -79,9 +99,9 @@ public class ClassPathXmlJobRegistryTests {
Resource[] jobPaths = new Resource[] {
new ClassPathResource("org/springframework/batch/core/launch/support/2jobs.xml"),
new ClassPathResource("org/springframework/batch/core/launch/support/error.xml") };
- registry.setJobPaths(jobPaths);
+ loader.setJobPaths(jobPaths);
try {
- registry.initialize();
+ loader.initialize();
fail("Expected BeanCreationException");
}
catch (BeanCreationException e) {
@@ -94,10 +114,10 @@ public class ClassPathXmlJobRegistryTests {
Resource[] jobPaths = new Resource[] { new ClassPathResource(
"org/springframework/batch/core/launch/support/2jobs.xml") };
- registry.setJobPaths(jobPaths);
- registry.initialize();
+ loader.setJobPaths(jobPaths);
+ loader.initialize();
assertEquals(2, registry.getJobNames().size());
- registry.destroy();
+ loader.destroy();
assertEquals(0, registry.getJobNames().size());
}
diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoaderContextTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoaderContextTests-context.xml
new file mode 100644
index 000000000..f9b49e6d2
--- /dev/null
+++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/ClassPathXmlJobLoaderContextTests-context.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryContextTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryContextTests-context.xml
deleted file mode 100644
index 1c3eabbf3..000000000
--- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistryContextTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/spring-batch-samples/src/main/resources/skipSample-job-launcher-context.xml b/spring-batch-samples/src/main/resources/skipSample-job-launcher-context.xml
index e18d2513f..fd0a90080 100644
--- a/spring-batch-samples/src/main/resources/skipSample-job-launcher-context.xml
+++ b/spring-batch-samples/src/main/resources/skipSample-job-launcher-context.xml
@@ -30,9 +30,11 @@
-
+
+
+