REOPENED - issue BATCH-1338: Allow segregation of jobs by type or origin
Fixed broken build re-jig JobRegistryBackgroundJobRunner
This commit is contained in:
@@ -25,6 +25,7 @@ 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;
|
||||
@@ -112,7 +113,7 @@ public class ClassPathXmlJobRegistry implements ListableJobLocator, ApplicationC
|
||||
*
|
||||
* @see InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
public final void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof ContextRefreshedEvent && event.getSource() == parent) {
|
||||
try {
|
||||
initialize();
|
||||
@@ -139,21 +140,17 @@ public class ClassPathXmlJobRegistry implements ListableJobLocator, ApplicationC
|
||||
protected void initialize() throws DuplicateJobException, NoSuchJobException {
|
||||
|
||||
for (Resource resource : jobPaths) {
|
||||
ClassPathXmlApplicationContextFactory applicationContextFactory = new ClassPathXmlApplicationContextFactory();
|
||||
applicationContextFactory.setPath(resource);
|
||||
if (parent != null) {
|
||||
applicationContextFactory.setApplicationContext(parent);
|
||||
}
|
||||
ConfigurableApplicationContext context = applicationContextFactory.createApplicationContext();
|
||||
|
||||
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);
|
||||
ApplicationContextJobFactory jobFactory = new ApplicationContextJobFactory(name,
|
||||
applicationContextFactory);
|
||||
JobFactory jobFactory = new ReferenceJobFactory((Job) context.getBean(name));
|
||||
jobRegistry.register(jobFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (jobRegistry.getJobNames().isEmpty()) {
|
||||
@@ -162,6 +159,25 @@ public class ClassPathXmlJobRegistry implements ListableJobLocator, ApplicationC
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()}.
|
||||
*
|
||||
|
||||
@@ -123,7 +123,7 @@ public class JobRegistryBeanPostProcessor implements BeanPostProcessor, BeanFact
|
||||
Job job = (Job) bean;
|
||||
try {
|
||||
String groupName = this.groupName;
|
||||
if (beanFactory != null) {
|
||||
if (beanFactory != null && beanFactory.containsBean(beanName)) {
|
||||
groupName = getGroupName(beanFactory.getBeanDefinition(beanName), job);
|
||||
}
|
||||
job = groupName==null ? job : new GroupAwareJob(groupName, job);
|
||||
|
||||
@@ -18,7 +18,9 @@ package org.springframework.batch.core.launch.support;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -27,14 +29,14 @@ 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.JobRegistry;
|
||||
import org.springframework.batch.core.configuration.support.ApplicationContextJobFactory;
|
||||
import org.springframework.batch.core.configuration.support.ClassPathXmlApplicationContextFactory;
|
||||
import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor;
|
||||
import org.springframework.batch.core.configuration.support.ReferenceJobFactory;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -80,6 +82,8 @@ public class JobRegistryBackgroundJobRunner {
|
||||
|
||||
final private String parentContextPath;
|
||||
|
||||
private Collection<ConfigurableApplicationContext> contexts = new HashSet<ConfigurableApplicationContext>();
|
||||
|
||||
private static List<Exception> errors = Collections.synchronizedList(new ArrayList<Exception>());
|
||||
|
||||
/**
|
||||
@@ -113,6 +117,7 @@ public class JobRegistryBackgroundJobRunner {
|
||||
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
|
||||
boolean postProcessorExists = parentContext.getBeanNamesForType(JobRegistryBeanPostProcessor.class).length > 0;
|
||||
Resource[] resources = parentContext.getResources(paths[i]);
|
||||
|
||||
for (int j = 0; j < resources.length; j++) {
|
||||
@@ -120,16 +125,19 @@ public class JobRegistryBackgroundJobRunner {
|
||||
Resource path = resources[j];
|
||||
logger.info("Registering Job definitions from " + Arrays.toString(resources));
|
||||
|
||||
ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(path, parentContext
|
||||
.getAutowireCapableBeanFactory());
|
||||
String[] names = beanFactory.getBeanNamesForType(Job.class);
|
||||
ConfigurableApplicationContext context = createApplicationContext(parentContext, path);
|
||||
contexts.add(context);
|
||||
String[] names = context.getBeanNamesForType(Job.class);
|
||||
|
||||
for (int k = 0; k < names.length; k++) {
|
||||
ClassPathXmlApplicationContextFactory factory = new ClassPathXmlApplicationContextFactory();
|
||||
factory.setApplicationContext(parentContext);
|
||||
factory.setPath(path);
|
||||
logger.info("Registering Job definition: " + names[k]);
|
||||
registry.register(new ApplicationContextJobFactory(names[k], factory));
|
||||
Collection<String> registered = registry.getJobNames();
|
||||
// If there is a JobRegistryBeanPostProcessor in there already
|
||||
// then they can be registered automatically
|
||||
for (String name : names) {
|
||||
if (!registered.contains(name) && postProcessorExists) {
|
||||
logger.debug("Registering job: " + name + " from context: " + path);
|
||||
JobFactory jobFactory = new ReferenceJobFactory((Job) context.getBean(name));
|
||||
registry.register(jobFactory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -138,6 +146,25 @@ public class JobRegistryBackgroundJobRunner {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Supply a list of application context locations, starting with the parent
|
||||
* context, and followed by the children. The parent must contain a
|
||||
@@ -194,7 +221,7 @@ public class JobRegistryBackgroundJobRunner {
|
||||
}
|
||||
}
|
||||
errors.clear();
|
||||
|
||||
|
||||
// Paths to individual job configurations.
|
||||
final String[] paths = new String[args.length - 1];
|
||||
System.arraycopy(args, 1, paths, 0, paths.length);
|
||||
@@ -203,6 +230,7 @@ public class JobRegistryBackgroundJobRunner {
|
||||
launcher.register(paths);
|
||||
|
||||
if (System.getProperty(EMBEDDED) != null) {
|
||||
launcher.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -211,9 +239,27 @@ public class JobRegistryBackgroundJobRunner {
|
||||
.println("Started application. Interrupt (CTRL-C) or call JobRegistryBackgroundJobRunner.stop() to exit.");
|
||||
JobRegistryBackgroundJobRunner.class.wait();
|
||||
}
|
||||
launcher.destroy();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* De-register all the {@link Job} instances that were regsistered by this
|
||||
* post processor.
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
private void destroy() throws Exception {
|
||||
for (ConfigurableApplicationContext context : contexts) {
|
||||
if (context.isActive()) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
for (String jobName : registry.getJobNames()) {
|
||||
registry.unregister(jobName);
|
||||
}
|
||||
contexts.clear();
|
||||
}
|
||||
|
||||
private void run() {
|
||||
final ApplicationContext parent = new ClassPathXmlApplicationContext(parentContextPath);
|
||||
parent.getAutowireCapableBeanFactory().autowireBeanProperties(this,
|
||||
|
||||
@@ -58,7 +58,9 @@ public class RemoteLauncherTests {
|
||||
@Test
|
||||
public void testConnect() throws Exception {
|
||||
String message = errors.isEmpty() ? "" : errors.get(0).getMessage();
|
||||
assertEquals(message, 0, errors.size());
|
||||
if (!errors.isEmpty()) {
|
||||
fail(message);
|
||||
}
|
||||
assertTrue(isConnected());
|
||||
}
|
||||
|
||||
@@ -94,11 +96,11 @@ public class RemoteLauncherTests {
|
||||
// sleep long enough to avoid race conditions (serializable tx isolation
|
||||
// doesn't work with HSQL)
|
||||
Thread.sleep(SLEEP_INTERVAL);
|
||||
// assertEquals(1, launcher.getRunningExecutions("loopJob").size());
|
||||
// assertEquals(1, launcher.getRunningExecutions("loopJob").size());
|
||||
launcher.stop(executionId);
|
||||
|
||||
Thread.sleep(SLEEP_INTERVAL);
|
||||
// assertEquals(0, launcher.getRunningExecutions("loopJob").size());
|
||||
// assertEquals(0, launcher.getRunningExecutions("loopJob").size());
|
||||
logger.debug(launcher.getSummary(executionId));
|
||||
long resumedId = launcher.restart(executionId);
|
||||
assertNotSame("Picked up the same execution after pause and resume", executionId, resumedId);
|
||||
@@ -107,7 +109,7 @@ public class RemoteLauncherTests {
|
||||
launcher.stop(resumedId);
|
||||
Thread.sleep(SLEEP_INTERVAL);
|
||||
|
||||
// assertEquals(0, launcher.getRunningExecutions("loopJob").size());
|
||||
// assertEquals(0, launcher.getRunningExecutions("loopJob").size());
|
||||
logger.debug(launcher.getSummary(resumedId));
|
||||
long resumeId2 = launcher.restart(resumedId);
|
||||
assertNotSame("Picked up the same execution after pause and resume", executionId, resumeId2);
|
||||
@@ -131,6 +133,8 @@ public class RemoteLauncherTests {
|
||||
JobRegistryBackgroundJobRunner.main("adhoc-job-launcher-context.xml", "jobs/adhocLoopJob.xml");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
logger.error(e);
|
||||
errors.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user