REOPENED - issue BATCH-1338: Allow segregation of jobs by type or origin

Fixed broken build re-jig JobRegistryBackgroundJobRunner
This commit is contained in:
dsyer
2009-09-09 11:42:12 +00:00
parent f98c5775ed
commit def829f87a
4 changed files with 93 additions and 27 deletions

View File

@@ -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()}.
*

View File

@@ -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);

View File

@@ -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,

View File

@@ -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);
}
}