IN PROGRESS - issue BATCH-24: Provide exit code for job executed as a main method

http://opensource.atlassian.com/projects/spring/browse/BATCH-24
This commit is contained in:
lucasward
2007-09-20 01:16:57 +00:00
parent 464b1393b6
commit 7e83c33632
10 changed files with 417 additions and 79 deletions

View File

@@ -16,36 +16,55 @@
package org.springframework.batch.execution.bootstrap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.core.executor.ExitCodeExceptionClassifier;
import org.springframework.batch.execution.bootstrap.support.JvmSystemExiter;
import org.springframework.batch.execution.bootstrap.support.SimpleJvmExitCodeMapper;
import org.springframework.batch.execution.step.simple.SimpleExitCodeExceptionClassifier;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.Assert;
/**
* @author Dave Syer
* @author Lucas Ward
* @since 2.1
*/
public class BatchCommandLineLauncher {
protected static final Log logger = LogFactory
.getLog(BatchCommandLineLauncher.class);
/**
* The key for the parent context.
*/
public static final String PARENT_KEY = "simple-container";
private static final String DEFAULT_PARENT_KEY = "batchExecutionEnvironment";
private static final String DEFAULT_JOB_CONFIGURATION_PATH = "job-configuration.xml";
private ConfigurableApplicationContext parent;
private JvmExitCodeMapper exitCodeMapper;
private static final String JOB_CONFIGURATIN_PATH_KEY = "job.configuration.path";
private static final String JOB_NAME_KEY = "job.name";
private static final String BATCH_EXECUTION_ENVIRONMENT_KEY = "batch.execution.environment.key";
private BeanFactoryLocator beanFactoryLocator;
private JvmExitCodeMapper exitCodeMapper = new SimpleJvmExitCodeMapper();
private ExitCodeExceptionClassifier exceptionClassifier = new SimpleExitCodeExceptionClassifier();
private JobLauncher launcher;
/**
* Default constructor for the launcher. Sets up the parent context to use
* for all job executions using a context key {@link #PARENT_KEY}.
*/
private SystemExiter systemExiter = new JvmSystemExiter();
public BatchCommandLineLauncher() {
parent = (ConfigurableApplicationContext) ContextSingletonBeanFactoryLocator
.getInstance().useBeanFactory(PARENT_KEY).getFactory();
beanFactoryLocator = ContextSingletonBeanFactoryLocator.getInstance();
}
/**
@@ -58,6 +77,16 @@ public class BatchCommandLineLauncher {
this.launcher = launcher;
}
/**
* Injection setter for the {@link ExitCodeExceptionClassifier}
*
* @param exceptionClassifier
*/
public void setExceptionClassifier(
ExitCodeExceptionClassifier exceptionClassifier) {
this.exceptionClassifier = exceptionClassifier;
}
/**
* Injection setter for the {@link JvmExitCodeMapper}.
*
@@ -68,25 +97,52 @@ public class BatchCommandLineLauncher {
this.exitCodeMapper = exitCodeMapper;
}
/**
* Injection setter for the {@link SystemExiter}.
*
* @param systemExitor
*/
public void setSystemExiter(SystemExiter systemExitor) {
this.systemExiter = systemExitor;
}
public SystemExiter getSystemExiter() {
return systemExiter;
}
/**
* @param path
* the path to a Spring context configuration for this job
* @param jobName
* the name of the job execution to use
* @throws NoSuchJobConfigurationException
* @throws IllegalStateException
* if JobLauncher is not autowired by the ApplicationContext
*/
int start(String path, String jobName) {
if (!path.endsWith(".xml")) {
path = path + ".xml";
}
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { path }, parent);
context.getAutowireCapableBeanFactory().autowireBeanProperties(this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
ExitStatus status = null;
int start(String path, String jobName, String parentKey) {
ExitStatus status = ExitStatus.FAILED;
ClassPathXmlApplicationContext context = null;
try {
ClassPathXmlApplicationContext parent = (ClassPathXmlApplicationContext) beanFactoryLocator
.useBeanFactory(parentKey).getFactory();
if (!path.endsWith(".xml")) {
path = path + ".xml";
}
context = new ClassPathXmlApplicationContext(
new String[] { path }, parent);
context.getAutowireCapableBeanFactory().autowireBeanProperties(
this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
Assert.state(launcher != null,
"JobLauncher must be provided in the parent ApplicationContext"
+ ", check the context created within classpath*:beanRefContext.xml to ensure a JobLauncher"
+ " is declared");
if (!launcher.isRunning()) {
if (jobName == null) {
status = launcher.run();
@@ -94,15 +150,21 @@ public class BatchCommandLineLauncher {
status = launcher.run(jobName);
}
}
} catch (NoSuchJobConfigurationException e) {
status = new ExitStatus(false,
JvmExitCodeMapper.BATCH_EXITCODE_NO_SUCH_JOBCONFIGURATION,
"Could not locate JobConfiguration \"" + jobName + "\"" );
} catch (NoSuchJobConfigurationException e) {
logger.fatal("Could not locate JobConfiguration \"" + jobName
+ "\"", e);
status = new ExitStatus(false,
JvmExitCodeMapper.BATCH_EXITCODE_NO_SUCH_JOBCONFIGURATION);
} catch (Throwable t) {
logger.fatal(t);
status = exceptionClassifier.classifyForExitCode(t);
} finally {
try {
context.stop();
} finally {
context.close();
if(context != null){
try {
context.stop();
} finally {
context.close();
}
}
}
return exitCodeMapper.getExitCode(status.getExitCode());
@@ -115,27 +177,26 @@ public class BatchCommandLineLauncher {
*
* @param args
* <ol>
* <li> path to resource to load job configuration context
* (default "job-configuration.xml");</li>
* <li>runtime name for job execution (default
* "job-execution-id").</li>
* <li> classpath location of resource to load job configuration
* context (default "job-configuration.xml");</li>
* <li>runtime name of Job (default "job-execution-id").</li>
* <li> parent context key for use in pulling the correct
* beanFactory from the beanRefContext.xml (@see
* ContextSingletonBeanFactoryLocator)</li>
* </ol>
* @throws NoSuchJobConfigurationException
*/
public static void main(String[] args) {
String path = "job-configuration.xml";
String name = null;
if (args.length > 0) {
path = args[0];
}
if (args.length > 1) {
name = args[1];
}
String path = System.getProperty(JOB_CONFIGURATIN_PATH_KEY,
DEFAULT_JOB_CONFIGURATION_PATH);
String name = System.getProperty(JOB_NAME_KEY);
String parentKey = System.getProperty(BATCH_EXECUTION_ENVIRONMENT_KEY,
DEFAULT_PARENT_KEY);
BatchCommandLineLauncher command = new BatchCommandLineLauncher();
int result = command.start(path, name);
System.exit(result);
int result = command.start(path, name, parentKey);
command.getSystemExiter().exit(result);
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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.execution.bootstrap;
/**
* Interface for exiting the JVM. This abstraction is only
* useful in order to allow classes that make System.exit calls
* to be testable, since calling System.exit during a unit
* test would cause the entire jvm to finish.
*
* @author Lucas Ward
*
*/
public interface SystemExiter {
/**
* Terminate the currently running Java Virtual Machine.
*
* @param status exit status.
* @throws SecurityException
* if a security manager exists and its <code>checkExit</code>
* method doesn't allow exit with the specified status.
* @see System.exit
*/
void exit(int status);
}