Rationalise exit code mapping a bit

This commit is contained in:
dsyer
2007-09-25 17:49:42 +00:00
parent ba67b7faa1
commit deef433bc3
19 changed files with 360 additions and 364 deletions

View File

@@ -10,6 +10,8 @@
<config>src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-context.xml</config>
<config>src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-dao-test.xml</config>
<config>src/test/resources/org/springframework/batch/execution/repository/dao/sql-dao-test.xml</config>
<config>src/test/resources/org/springframework/batch/execution/bootstrap/support/test-batch-environment.xml</config>
<config>src/test/resources/org/springframework/batch/execution/bootstrap/support/test-batch-environment-no-launcher.xml</config>
</configs>
<configSets>
<configSet>

View File

@@ -1,44 +0,0 @@
/*
* 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;
import org.springframework.batch.repeat.ExitCodeMapper;
/**
* Abstract class for mapping ExitCodes from the Batch framework to
* JVM Return Codes
*
* @author Stijn Maller
* @author Lucas Ward
*/
public interface JvmExitCodeMapper extends ExitCodeMapper {
static int JVM_EXITCODE_COMPLETED = 0;
static int JVM_EXITCODE_GENERIC_ERROR = 1;
static int JVM_EXITCODE_JOB_CONFIGURATION_ERROR = 2;
/**
* Transform the exitcode known by the batchframework into a JVM return
* value.(Must be of type int)
* @param exitCode The exitcode which is used internally by the batch framework.
* @return The corresponding JVM return value
*/
public int getExitCode(String exitCode);
}

View File

@@ -21,61 +21,68 @@ 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.JobLauncher;
import org.springframework.batch.execution.bootstrap.JvmExitCodeMapper;
import org.springframework.batch.execution.bootstrap.SystemExiter;
import org.springframework.batch.execution.step.simple.SimpleExitCodeExceptionClassifier;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.Assert;
/**
*<p>Basic Launcher for starting jobs from the command line. In general,
* it is assumed that this launcher will primarily be used to start
* a job via a script from an Enterprise Scheduler. Therefore, exit codes
* are mapped to integers so that schedulers can use the returned values to
* determine the next course of action. The returned values can also
* be useful to operations teams in determining what should happen upon failure.
* For example, a returned code of 5 might mean that some resource wasn't available
* and the job should be restarted. However, a code of 10 might mean that something
* critical has happened and the issue should be escalated.</p>
*
* <p>With any launch of a batch job within Spring Batch, a minimum of two contexts
* must be loaded. One is the context containing the JobConfiguration, the other
* contains the 'Execution Environment'. That is, the JobExecutorFacade (which
* contains all the executors, plus the repository), the JobIdentifierFactory, and
* a normal JobLauncher. This command line launcher loads these application contexts
* by first loading the execution environment context via a
* {@link ContextSingletonBeanFactoryLocator}, which will search for the default
* key from classpath*:beanRefContext.xml to return the context. This will then
* be used as the parent to the JobConfiguration context. All required dependencies
* of the launcher will then be satisfied by autowiring by type from the combined
* application context. Default values are provided for all fields except the JobLauncher.
* Therefore, if autowiring fails to set it (it should be noted that dependency checking
* is disabled because most of the fields have default values and thus don't require
* dependencies to be fulfilled via autowiring) then an exception will be thrown.
* It should be noted that even if an exception is thrown by this class, it will be
* mapped to an integer and returned.</p>
*
* <p>One odd field might be noticed in the launcher, SystemExiter. This class is
* used to exit from the main method, rather than calling System.exit directly. This
* is because unit testing a class the calls System.exit() is impossible without
* kicking off the test within a new Jvm, which it is possible to do, however it is a
* complex solution, much more so than strategizing the exiter.</p>
*
* <p>VM Arguments vs. Program arguments: Because all of the arguments to the main
* <p>
* Basic Launcher for starting jobs from the command line. In general, it is
* assumed that this launcher will primarily be used to start a job via a script
* from an Enterprise Scheduler. Therefore, exit codes are mapped to integers so
* that schedulers can use the returned values to determine the next course of
* action. The returned values can also be useful to operations teams in
* determining what should happen upon failure. For example, a returned code of
* 5 might mean that some resource wasn't available and the job should be
* restarted. However, a code of 10 might mean that something critical has
* happened and the issue should be escalated.
* </p>
*
* <p>
* With any launch of a batch job within Spring Batch, a minimum of two contexts
* must be loaded. One is the context containing the JobConfiguration, the other
* contains the 'Execution Environment'. That is, the JobExecutorFacade (which
* contains all the executors, plus the repository), the JobIdentifierFactory,
* and a normal JobLauncher. This command line launcher loads these application
* contexts by first loading the execution environment context via a
* {@link ContextSingletonBeanFactoryLocator}, which will search for the
* default key from classpath*:beanRefContext.xml to return the context. This
* will then be used as the parent to the JobConfiguration context. All required
* dependencies of the launcher will then be satisfied by autowiring by type
* from the combined application context. Default values are provided for all
* fields except the JobLauncher. Therefore, if autowiring fails to set it (it
* should be noted that dependency checking is disabled because most of the
* fields have default values and thus don't require dependencies to be
* fulfilled via autowiring) then an exception will be thrown. It should be
* noted that even if an exception is thrown by this class, it will be mapped to
* an integer and returned.
* </p>
*
* <p>
* One odd field might be noticed in the launcher, SystemExiter. This class is
* used to exit from the main method, rather than calling System.exit directly.
* This is because unit testing a class the calls System.exit() is impossible
* without kicking off the test within a new Jvm, which it is possible to do,
* however it is a complex solution, much more so than strategizing the exiter.
* </p>
*
* <p>
* VM Arguments vs. Program arguments: Because all of the arguments to the main
* method are optional, VM arguments are used:
*
*
* <ul>
* <li>-Djob.configuration.path: the classpath location of the JobConfiguration
* <li>-Djob.configuration.path: the classpath location of the JobConfiguration
* to use
* <li>-Djob.name: job name to be passed to the {@link JobLauncher}
* <li>-Dbatch.execution.environment.key: the key in beanRefContext.xml used to load
* the execution envrionement.
* <li>-Djob.name: job name to be passed to the {@link JobLauncher}
* <li>-Dbatch.execution.environment.key: the key in beanRefContext.xml used to
* load the execution envrionement.
* </ul>
*
*
* @author Dave Syer
* @author Lucas Ward
* @since 2.1
@@ -86,18 +93,21 @@ public class BatchCommandLineLauncher {
.getLog(BatchCommandLineLauncher.class);
/**
* The key for the parent context.
* The default key for the parent context.
*/
private static final String DEFAULT_PARENT_KEY = "batchExecutionEnvironment";
private static final String DEFAULT_JOB_CONFIGURATION_PATH = "job-configuration.xml";
public static final String DEFAULT_PARENT_KEY = "batchExecutionEnvironment";
/**
* The default path to the job configuration.
*/
public static final String DEFAULT_JOB_CONFIGURATION_PATH = "job-configuration.xml";
private static final String JOB_CONFIGURATIN_PATH_KEY = "job.configuration.path";
private static final String JOB_CONFIGURATION_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 ExitCodeMapper exitCodeMapper = new SimpleJvmExitCodeMapper();
private ExitCodeExceptionClassifier exceptionClassifier = new SimpleExitCodeExceptionClassifier();
@@ -111,7 +121,7 @@ public class BatchCommandLineLauncher {
/**
* Injection setter for the {@link JobLauncher}.
*
*
* @param launcher
* the launcher to set
*/
@@ -121,7 +131,7 @@ public class BatchCommandLineLauncher {
/**
* Injection setter for the {@link ExitCodeExceptionClassifier}
*
*
* @param exceptionClassifier
*/
public void setExceptionClassifier(
@@ -131,25 +141,30 @@ public class BatchCommandLineLauncher {
/**
* Injection setter for the {@link JvmExitCodeMapper}.
*
*
* @param exitCodeMapper
* the exitCodeMapper to set
*/
public void setExitCodeMapper(JvmExitCodeMapper exitCodeMapper) {
public void setExitCodeMapper(ExitCodeMapper exitCodeMapper) {
this.exitCodeMapper = exitCodeMapper;
}
/**
* Injection setter for the {@link SystemExiter}.
*
*
* @param systemExitor
*/
public void setSystemExiter(SystemExiter systemExitor) {
this.systemExiter = systemExitor;
}
public SystemExiter getSystemExiter() {
return systemExiter;
/**
* Delegate to the exiter to (possibly) exit the VM gracefully.
*
* @param status
*/
public void exit(int status) {
systemExiter.exit(status);
}
/**
@@ -157,8 +172,8 @@ public class BatchCommandLineLauncher {
* the path to a Spring context configuration for this job
* @param jobName
* the name of the job execution to use
* @parm parentKey the key to be loaded by ContextSingletonBeanFactoryLocator and
* used as the parent context.
* @parm parentKey the key to be loaded by
* ContextSingletonBeanFactoryLocator and used as the parent context.
* @throws NoSuchJobConfigurationException
* @throws IllegalStateException
* if JobLauncher is not autowired by the ApplicationContext
@@ -169,23 +184,28 @@ public class BatchCommandLineLauncher {
ClassPathXmlApplicationContext context = null;
try {
ClassPathXmlApplicationContext parent = (ClassPathXmlApplicationContext) beanFactoryLocator
ConfigurableApplicationContext parent = (ConfigurableApplicationContext) beanFactoryLocator
.useBeanFactory(parentKey).getFactory();
parent.getAutowireCapableBeanFactory().autowireBeanProperties(this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
if (!path.endsWith(".xml")) {
path = path + ".xml";
}
context = new ClassPathXmlApplicationContext(
new String[] { path }, parent);
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");
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) {
@@ -198,12 +218,12 @@ public class BatchCommandLineLauncher {
logger.fatal("Could not locate JobConfiguration \"" + jobName
+ "\"", e);
status = new ExitStatus(false,
JvmExitCodeMapper.BATCH_EXITCODE_NO_SUCH_JOBCONFIGURATION);
JobLauncher.NO_SUCH_JOB_CONFIGURATION);
} catch (Throwable t) {
logger.fatal(t);
status = exceptionClassifier.classifyForExitCode(t);
} finally {
if(context != null){
if (context != null) {
try {
context.stop();
} finally {
@@ -217,21 +237,24 @@ public class BatchCommandLineLauncher {
/**
* Launch a batch job using a {@link BatchCommandLineLauncher}. Creates a
* new Spring context for the job execution, and uses a common parent for
* all such contexts. No exception should be thrown from this method, rather
* exceptions should be logged and an integer returned.
*
* all such contexts. No exception are thrown from this method, rather
* exceptions are logged and an integer returned through the exit status in
* a {@link JvmSystemExiter} (which can be overridden by defining one in the
* Spring context).
*
* @param args
* <ul>
* <li>-Djob.configuration.path: the classpath location of the JobConfiguration
* to use
* <li>-Djob.name: job name to be passed to the {@link JobLauncher}
* <li>-Dbatch.execution.environment.key: the key in beanRefContext.xml used to load
* the execution envrionement.
* </ul>
* <ul>
* <li>-Djob.configuration.path: the classpath location of the
* JobConfiguration to use
* <li>-Djob.name: job name to be passed to the
* {@link JobLauncher}
* <li>-Dbatch.execution.environment.key: the key in
* beanRefContext.xml used to load the execution envrionment.
* </ul>
*/
public static void main(String[] args) {
String path = System.getProperty(JOB_CONFIGURATIN_PATH_KEY,
String path = System.getProperty(JOB_CONFIGURATION_PATH_KEY,
DEFAULT_JOB_CONFIGURATION_PATH);
String name = System.getProperty(JOB_NAME_KEY);
String parentKey = System.getProperty(BATCH_EXECUTION_ENVIRONMENT_KEY,
@@ -239,7 +262,7 @@ public class BatchCommandLineLauncher {
BatchCommandLineLauncher command = new BatchCommandLineLauncher();
int result = command.start(path, name, parentKey);
command.getSystemExiter().exit(result);
command.exit(result);
}
}

View File

@@ -0,0 +1,28 @@
package org.springframework.batch.execution.bootstrap.support;
/**
*
* This interface should be implemented when an environment calling the batch famework has specific
* requirements regarding the process return codes.
*
* @param The type of returncode expected by the environment
* @author Stijn Maller
* @author Lucas Ward
* @author Dave Syer
*/
public interface ExitCodeMapper {
static int JVM_EXITCODE_COMPLETED = 0;
static int JVM_EXITCODE_GENERIC_ERROR = 1;
static int JVM_EXITCODE_JOB_CONFIGURATION_ERROR = 2;
/**
* Transform the exitcode known by the batchframework into an exitcode in the
* format of the calling environment.
* @param exitCode The exitcode which is used internally by the batch framework.
* @return The corresponding exitcode as known by the calling environment.
*/
public int getExitCode(String exitCode);
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.batch.execution.bootstrap.support;
import org.springframework.batch.execution.bootstrap.SystemExiter;
/**
* Implementation of the {@link SystemExiter} interface

View File

@@ -22,20 +22,19 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.execution.bootstrap.JobLauncher;
import org.springframework.batch.execution.bootstrap.JvmExitCodeMapper;
import org.springframework.batch.execution.bootstrap.SimpleJobLauncher;
import org.springframework.batch.repeat.ExitStatus;
/**
* An implementation of JvmExitCodeMapper that can be configured
* through the Spring ApplicationContext
* An implementation of {@link ExitCodeMapper} that can be configured
* through a map from batch exit codes (String) to integer results.
*
* @author Stijn Maller
* @author Lucas Ward
* @author Dave Syer
*/
public class SimpleJvmExitCodeMapper implements JvmExitCodeMapper {
public class SimpleJvmExitCodeMapper implements ExitCodeMapper {
protected Log logger = LogFactory.getLog(getClass());

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.execution.bootstrap;
package org.springframework.batch.execution.bootstrap.support;
/**
* Interface for exiting the JVM. This abstraction is only

View File

@@ -17,7 +17,6 @@ package org.springframework.batch.execution.bootstrap;
import junit.framework.TestCase;
import org.springframework.batch.execution.bootstrap.BatchExecutionRequestEvent;
import org.springframework.context.ApplicationEvent;
/**

View File

@@ -15,10 +15,8 @@
*/
package org.springframework.batch.execution.bootstrap.support;
import org.easymock.MockControl;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.execution.bootstrap.JvmExitCodeMapper;
import org.springframework.batch.execution.bootstrap.support.BatchCommandLineLauncher;
import junit.framework.TestCase;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
@@ -26,17 +24,12 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import junit.framework.TestCase;
/**
* @author Dave Syer
*
*
*/
public class BatchCommandLineLauncherTests extends TestCase {
private static final String DEFAULT_PARENT_KEY = "batchExecutionEnvironment";
private static final String DEFAULT_JOB_CONFIGURATION_PATH = "job-configuration.xml";
private static final String JOB_CONFIGURATION_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";
@@ -44,19 +37,16 @@ public class BatchCommandLineLauncherTests extends TestCase {
private static final String TEST_BATCH_ENVIRONMENT_KEY = "testBatchEnvironment";
private static final String TEST_BATCH_ENVIRONMENT_NO_LAUNCHER_KEY = "testBatchEnvironmentNoLauncher";
BeanFactoryLocator beanFactoryLocator = ContextSingletonBeanFactoryLocator.getInstance();
BeanFactoryLocator beanFactoryLocator = ContextSingletonBeanFactoryLocator
.getInstance();
ClassPathXmlApplicationContext context;
MockJobLauncher mockJobLauncher;
MockSystemExiter mockSystemExiter;
StubJobLauncher jobLauncher;
StubSystemExiter systemExiter;
protected void setUp() throws Exception {
super.setUp();
context = (ClassPathXmlApplicationContext)beanFactoryLocator.useBeanFactory(TEST_BATCH_ENVIRONMENT_KEY).getFactory();
context.getAutowireCapableBeanFactory().autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
System.setProperty(BATCH_EXECUTION_ENVIRONMENT_KEY, TEST_BATCH_ENVIRONMENT_KEY);
System.setProperty(BATCH_EXECUTION_ENVIRONMENT_KEY,
TEST_BATCH_ENVIRONMENT_KEY);
}
protected void tearDown() throws Exception {
@@ -66,65 +56,118 @@ public class BatchCommandLineLauncherTests extends TestCase {
System.clearProperty(BATCH_EXECUTION_ENVIRONMENT_KEY);
}
public void setMockJobLauncher(MockJobLauncher mockJobLauncher){
this.mockJobLauncher = mockJobLauncher;
}
public void testParentWithNoLauncher() {
buildContext(TEST_BATCH_ENVIRONMENT_NO_LAUNCHER_KEY);
assertNotNull(systemExiter);
public void setMockSystemExiter(MockSystemExiter mockSystemExiter) {
this.mockSystemExiter = mockSystemExiter;
}
public void testParentWithNoLauncher(){
context = (ClassPathXmlApplicationContext)beanFactoryLocator.useBeanFactory(TEST_BATCH_ENVIRONMENT_NO_LAUNCHER_KEY).getFactory();
context.getAutowireCapableBeanFactory().autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
System.setProperty(BATCH_EXECUTION_ENVIRONMENT_KEY, TEST_BATCH_ENVIRONMENT_NO_LAUNCHER_KEY);
System.setProperty(BATCH_EXECUTION_ENVIRONMENT_KEY,
TEST_BATCH_ENVIRONMENT_NO_LAUNCHER_KEY);
BatchCommandLineLauncher.main(new String[0]);
assertEquals(JvmExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR, mockSystemExiter.getStatus());
assertEquals(ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR, systemExiter
.getStatus());
}
/**
* Test method for {@link org.springframework.batch.execution.bootstrap.support.BatchCommandLineLauncher#main(java.lang.String[])}.
* Test method for
* {@link org.springframework.batch.execution.bootstrap.support.BatchCommandLineLauncher#main(java.lang.String[])}.
*
* @throws Exception
*/
public void testDefaultNameAndPath() throws Exception {
mockJobLauncher.setReturnValue(ExitStatus.FINISHED);
buildContext(TEST_BATCH_ENVIRONMENT_KEY);
assertNotNull(jobLauncher);
assertNotNull(systemExiter);
jobLauncher.setReturnValue(ExitStatus.FINISHED);
BatchCommandLineLauncher.main(new String[0]);
assertEquals(JvmExitCodeMapper.JVM_EXITCODE_COMPLETED, mockSystemExiter.getStatus());
assertEquals(mockJobLauncher.getLastRunCalled(), MockJobLauncher.RUN_NO_ARGS);
assertEquals(ExitCodeMapper.JVM_EXITCODE_COMPLETED, systemExiter
.getStatus());
assertEquals(jobLauncher.getLastRunCalled(),
StubJobLauncher.RUN_NO_ARGS);
}
public void testCustomJobName(){
public void testCustomJobName() {
mockJobLauncher.setReturnValue(ExitStatus.FINISHED);
buildContext(TEST_BATCH_ENVIRONMENT_KEY);
assertNotNull(jobLauncher);
assertNotNull(systemExiter);
jobLauncher.setReturnValue(ExitStatus.FINISHED);
System.setProperty(JOB_NAME_KEY, "foo");
BatchCommandLineLauncher.main(new String[0]);
assertEquals(JvmExitCodeMapper.JVM_EXITCODE_COMPLETED, mockSystemExiter.getStatus());
assertEquals(mockJobLauncher.getLastRunCalled(), MockJobLauncher.RUN_JOB_NAME);
assertEquals(ExitCodeMapper.JVM_EXITCODE_COMPLETED, systemExiter
.getStatus());
assertEquals(jobLauncher.getLastRunCalled(),
StubJobLauncher.RUN_JOB_NAME);
}
/**
* Test method for {@link org.springframework.batch.execution.bootstrap.support.BatchCommandLineLauncher#main(java.lang.String[])}.
* Test method for
* {@link org.springframework.batch.execution.bootstrap.support.BatchCommandLineLauncher#main(java.lang.String[])}.
*
* @throws Exception
*/
public void testMainWithDefaultArguments() throws Exception {
//can't test this without running the whole test in another jvm.
//BatchCommandLineLauncher.main(new String[0]);
// We can only test this without running the whole test in another jvm
// by using a special SystemExiter in the default configuration because
// otherwise it calls System.exit() by default.
BatchCommandLineLauncher.main(new String[0]);
}
public void testInvalidJobConfig(){
//also not testable without kicking off in a new jvm, since autowiring happens
//after the context is loaded.
/* System.setProperty(JOB_CONFIGURATION_PATH_KEY, "foo");
BatchCommandLineLauncher.main(new String[0]);*/
public void testInvalidJobConfig() {
// To test this without kicking off in a new jvm, we have to autowire
// the launcher (in BatchCommandLineLauncher.start) from the parent,
// *then* the child context.
buildContext(BatchCommandLineLauncher.DEFAULT_PARENT_KEY);
assertNotNull(systemExiter);
System.setProperty(JOB_CONFIGURATION_PATH_KEY, "foo");
BatchCommandLineLauncher.main(new String[0]);
}
private void buildContext(String key) {
ConfigurableApplicationContext context = (ClassPathXmlApplicationContext) beanFactoryLocator
.useBeanFactory(key).getFactory();
context.getAutowireCapableBeanFactory().autowireBeanProperties(this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
}
public static class StubSystemExiter implements SystemExiter {
private int status;
public void exit(int status) {
this.status = status;
}
public int getStatus() {
return status;
}
}
/**
* Public setter for the {@link StubJobLauncher} property.
*
* @param jobLauncher
* the jobLauncher to set
*/
public void setJobLauncher(StubJobLauncher jobLauncher) {
this.jobLauncher = jobLauncher;
}
/**
* Public setter for the {@link StubSystemExiter} property.
*
* @param systemExiter
* the systemExiter to set
*/
public void setSystemExiter(StubSystemExiter systemExiter) {
this.systemExiter = systemExiter;
}
}

View File

@@ -1,35 +0,0 @@
/*
* 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.support;
import org.springframework.batch.execution.bootstrap.SystemExiter;
/**
* @author Lucas Ward
*
*/
class MockSystemExiter implements SystemExiter{
private int status;
public void exit(int status) {
this.status = status;
}
public int getStatus() {
return status;
}
}

View File

@@ -22,7 +22,6 @@ import java.util.Map;
import junit.framework.TestCase;
import org.springframework.batch.execution.bootstrap.JobLauncher;
import org.springframework.batch.execution.bootstrap.JvmExitCodeMapper;
import org.springframework.batch.repeat.ExitStatus;
public class SimpleJvmExitCodeMapperTests extends TestCase {
@@ -52,16 +51,16 @@ public class SimpleJvmExitCodeMapperTests extends TestCase {
public void testGetExitCodeWithpPredefinedCodes() {
assertEquals(
ecm.getExitCode(ExitStatus.FINISHED.getExitCode()),
JvmExitCodeMapper.JVM_EXITCODE_COMPLETED);
ExitCodeMapper.JVM_EXITCODE_COMPLETED);
assertEquals(
ecm.getExitCode(ExitStatus.FAILED.getExitCode()),
JvmExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR);
ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR);
assertEquals(
ecm.getExitCode(JobLauncher.JOB_CONFIGURATION_NOT_PROVIDED),
JvmExitCodeMapper.JVM_EXITCODE_JOB_CONFIGURATION_ERROR);
ExitCodeMapper.JVM_EXITCODE_JOB_CONFIGURATION_ERROR);
assertEquals(
ecm.getExitCode(JobLauncher.NO_SUCH_JOB_CONFIGURATION),
JvmExitCodeMapper.JVM_EXITCODE_JOB_CONFIGURATION_ERROR);
ExitCodeMapper.JVM_EXITCODE_JOB_CONFIGURATION_ERROR);
}
public void testGetExitCodeWithPredefinedCodesOverridden() {
@@ -83,7 +82,7 @@ public class SimpleJvmExitCodeMapperTests extends TestCase {
public void testGetExitCodeWithDefaultCode() {
assertEquals(
ecm.getExitCode("UNDEFINED_CUSTOM_CODE"),
JvmExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR);
ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR);
}

View File

@@ -14,7 +14,7 @@ import org.springframework.batch.repeat.ExitStatus;
* @author Lucas Ward
*
*/
public class MockJobLauncher implements JobLauncher {
public class StubJobLauncher implements JobLauncher {
public static final int RUN_NO_ARGS = 0;
public static final int RUN_JOB_NAME = 1;

View File

@@ -25,7 +25,6 @@ import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.core.executor.ExitCodeExceptionClassifier;
import org.springframework.batch.core.executor.StepInterruptedException;
import org.springframework.batch.core.runtime.JobExecutionContext;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.core.runtime.StepExecutionContext;
@@ -39,7 +38,6 @@ import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemProvider;
import org.springframework.batch.item.provider.ListItemProvider;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.batch.restart.RestartData;

View File

@@ -31,6 +31,6 @@
</constructor-arg>
</bean>
</property>
</bean>
</bean>
</beans>

View File

@@ -9,8 +9,9 @@
<bean id="jobConfigurationRegistry" class="org.springframework.batch.execution.configuration.MapJobConfigurationRegistry"/>
<bean class="org.springframework.batch.execution.bootstrap.support.SimpleJvmExitCodeMapper" />
<bean class="org.springframework.batch.execution.bootstrap.support.MockSystemExiter" />
<bean class="org.springframework.batch.execution.bootstrap.support.SimpleJvmExitCodeMapper" />
<bean
class="org.springframework.batch.execution.bootstrap.support.BatchCommandLineLauncherTests$StubSystemExiter" />
</beans>

View File

@@ -7,12 +7,13 @@
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="simpleContainerLauncher" class="org.springframework.batch.execution.bootstrap.support.MockJobLauncher" />
<bean id="simpleContainerLauncher" class="org.springframework.batch.execution.bootstrap.support.StubJobLauncher" />
<bean id="jobConfigurationRegistry" class="org.springframework.batch.execution.configuration.MapJobConfigurationRegistry"/>
<bean class="org.springframework.batch.execution.bootstrap.support.SimpleJvmExitCodeMapper" />
<bean class="org.springframework.batch.execution.bootstrap.support.MockSystemExiter" />
<bean
class="org.springframework.batch.execution.bootstrap.support.BatchCommandLineLauncherTests$StubSystemExiter" />
</beans>

View File

@@ -1,96 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="simpleFacade" class="org.springframework.batch.execution.facade.SimpleJobExecutorFacade">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobConfigurationLocator" ref="jobConfigurationRegistry"/>
<property name="jobExecutor" ref="jobLifecycle" />
</bean>
<bean id="simpleContainerLauncher" class="org.springframework.batch.execution.bootstrap.SimpleJobLauncher">
<property name="jobExecutorFacade" ref="simpleFacade" />
<property name="jobIdentifierFactory" ref="jobRuntimeInformationFactory"/>
</bean>
<bean id="jobConfigurationRegistry" class="org.springframework.batch.execution.configuration.MapJobConfigurationRegistry"/>
<bean id="jobLifecycle" class="org.springframework.batch.execution.job.DefaultJobExecutor">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="stepExecutorFactory">
<bean class="org.springframework.batch.execution.step.DefaultStepExecutorFactory">
<property name="stepExecutorName" value="stepLifecycle" />
</bean>
</property>
</bean>
<bean id="simpleJob" class="org.springframework.batch.core.configuration.JobConfiguration"
abstract="true">
<property name="restartable" value="true" />
</bean>
<bean id="simpleStep" class="org.springframework.batch.execution.step.simple.SimpleStepConfiguration"
abstract="true">
<property name="allowStartIfComplete" value="true" />
<property name="saveRestartData" value="false" />
<property name="exceptionHandler">
<bean
class="org.springframework.batch.repeat.exception.handler.SimpleLimitExceptionHandler">
<property name="limit" value="5" />
<property name="useParent" value="true"/>
</bean>
</property>
</bean>
<bean id="stepLifecycle" class="org.springframework.batch.execution.step.simple.SimpleStepExecutor" scope="prototype">
<property name="transactionManager" ref="transactionManager" />
<property name="repository" ref="simpleJobRepository" />
</bean>
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="simpleJobRepository" class="org.springframework.batch.execution.repository.SimpleJobRepository">
<constructor-arg ref="jobDao" />
<constructor-arg ref="stepDao" />
</bean>
<bean id="jobDao" class="org.springframework.batch.execution.repository.dao.MapJobDao"/>
<!-- init-method="clear"/-->
<bean id="stepDao" class="org.springframework.batch.execution.repository.dao.MapStepDao" />
<!-- init-method="clear"/-->
<bean id="jobRuntimeInformationFactory"
class="org.springframework.batch.execution.runtime.ScheduledJobIdentifierFactory">
<property name="jobStream" value="TestStream" />
<property name="scheduleDate" value="20070505" />
<property name="jobRun" value="1" />
<bean id="simpleFacade"
class="org.springframework.batch.execution.facade.SimpleJobExecutorFacade">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobConfigurationLocator"
ref="jobConfigurationRegistry" />
<property name="jobExecutor" ref="jobLifecycle" />
</bean>
<bean class="org.springframework.batch.execution.bootstrap.support.SimpleJvmExitCodeMapper" />
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="int[]">
<bean class="org.springframework.batch.support.IntArrayPropertyEditor" />
</entry>
<entry key="java.util.Date">
<bean class="org.springframework.beans.propertyeditors.CustomDateEditor">
<constructor-arg>
<bean class="java.text.SimpleDateFormat">
<constructor-arg value="yyyyMMdd"/>
</bean>
</constructor-arg>
<constructor-arg value="false"/>
</bean>
</entry>
</map>
</property>
</bean>
</beans>
<bean id="simpleContainerLauncher"
class="org.springframework.batch.execution.bootstrap.SimpleJobLauncher">
<property name="jobExecutorFacade" ref="simpleFacade" />
<property name="jobIdentifierFactory"
ref="jobRuntimeInformationFactory" />
</bean>
<bean id="jobConfigurationRegistry"
class="org.springframework.batch.execution.configuration.MapJobConfigurationRegistry" />
<bean id="jobLifecycle"
class="org.springframework.batch.execution.job.DefaultJobExecutor">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="stepExecutorFactory">
<bean
class="org.springframework.batch.execution.step.DefaultStepExecutorFactory">
<property name="stepExecutorName" value="stepLifecycle" />
</bean>
</property>
</bean>
<bean id="simpleJob"
class="org.springframework.batch.core.configuration.JobConfiguration"
abstract="true">
<property name="restartable" value="true" />
</bean>
<bean id="simpleStep"
class="org.springframework.batch.execution.step.simple.SimpleStepConfiguration"
abstract="true">
<property name="allowStartIfComplete" value="true" />
<property name="saveRestartData" value="false" />
<property name="exceptionHandler">
<bean
class="org.springframework.batch.repeat.exception.handler.SimpleLimitExceptionHandler">
<property name="limit" value="5" />
<property name="useParent" value="true" />
</bean>
</property>
</bean>
<bean id="stepLifecycle"
class="org.springframework.batch.execution.step.simple.SimpleStepExecutor"
scope="prototype">
<property name="transactionManager" ref="transactionManager" />
<property name="repository" ref="simpleJobRepository" />
</bean>
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="simpleJobRepository"
class="org.springframework.batch.execution.repository.SimpleJobRepository">
<constructor-arg ref="jobDao" />
<constructor-arg ref="stepDao" />
</bean>
<bean id="jobDao"
class="org.springframework.batch.execution.repository.dao.MapJobDao" />
<!-- init-method="clear"/-->
<bean id="stepDao"
class="org.springframework.batch.execution.repository.dao.MapStepDao" />
<!-- init-method="clear"/-->
<bean id="jobRuntimeInformationFactory"
class="org.springframework.batch.execution.runtime.ScheduledJobIdentifierFactory">
<property name="jobStream" value="TestStream" />
<property name="scheduleDate" value="20070505" />
<property name="jobRun" value="1" />
</bean>
<bean
class="org.springframework.batch.execution.bootstrap.support.SimpleJvmExitCodeMapper" />
<bean
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="int[]">
<bean
class="org.springframework.batch.support.IntArrayPropertyEditor" />
</entry>
<entry key="java.util.Date">
<bean
class="org.springframework.beans.propertyeditors.CustomDateEditor">
<constructor-arg>
<bean class="java.text.SimpleDateFormat">
<constructor-arg value="yyyyMMdd" />
</bean>
</constructor-arg>
<constructor-arg value="false" />
</bean>
</entry>
</map>
</property>
</bean>
<bean
class="org.springframework.batch.execution.bootstrap.support.BatchCommandLineLauncherTests$StubSystemExiter" />
</beans>

View File

@@ -1,42 +0,0 @@
/*
* 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.repeat;
/**
*
* This interface should be implemented when an environment calling the batch famework has specific
* requirements regarding the returncodes returned by the BatchFramework.
*
* @param The type of returncode expected by the environment
* @author Stijn Maller
* @author Lucas Ward
*/
public interface ExitCodeMapper {
String BATCH_EXITCODE_COMPLETED = ExitStatus.FINISHED.getExitCode();
String BATCH_EXITCODE_GENERIC_ERROR = ExitStatus.FAILED.getExitCode();
String BATCH_EXITCODE_NO_SUCH_JOBCONFIGURATION = "NO_SUCH_JOBCONFIGURATION";
/**
* Transform the exitcode known by the batchframework into an exitcode in the
* format of the calling environment.
* @param exitCode The exitcode which is used internally by the batch framework.
* @return The corresponding exitcode as known by the calling environment.
*/
public int getExitCode(String exitCode);
}

View File

@@ -1 +1 @@
<?xml version='1.0' encoding='utf-8'?><purchaseOrders xsi:schemaLocation="http://adsj.accenture.com/purchaseorders purchaseorders.xsd" xmlns="http://adsj.accenture.com/purchaseorders" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><order><customer><name>Gladys Kravitz</name><address>Anytown, PA</address><age>34</age><moo>0</moo><poo>0</poo></customer><date>2003-01-07 08:16:00.0 CST</date><lineItems><lineItem><description>Burnham's Celestial Handbook, Vol 1</description><perUnitOunces>5.0</perUnitOunces><price>21.79</price><quantity>2</quantity></lineItem><lineItem><description>Burnham's Celestial Handbook, Vol 2</description><perUnitOunces>5.0</perUnitOunces><price>19.89</price><quantity>2</quantity></lineItem></lineItems></order><order><customer><name>John Smith</name><address>Chicago, IL</address><age>46</age><moo>0</moo><poo>0</poo></customer><date>2003-01-07 08:16:02.0 CST</date><lineItems><lineItem><description>XmlBeans in Action</description><perUnitOunces>3.0</perUnitOunces><price>41.29</price><quantity>1</quantity></lineItem><lineItem><description>JSR-173</description><perUnitOunces>1.0</perUnitOunces><price>11.99</price><quantity>5</quantity></lineItem><lineItem><description>Teach Yourself XML in 21 days</description><perUnitOunces>1.0</perUnitOunces><price>35.49</price><quantity>1</quantity></lineItem></lineItems></order><order><customer><name>Peter Newman</name><address>Cleveland, OH</address><age>23</age><moo>0</moo><poo>0</poo></customer><date>2003-01-07 08:16:35.0 CST</date><lineItems><lineItem><description>Java 6</description><perUnitOunces>2.0</perUnitOunces><price>12.79</price><quantity>3</quantity></lineItem></lineItems></order></purchaseOrders>
<?xml version='1.0' encoding='utf-8'?><purchaseOrders xsi:schemaLocation="http://adsj.accenture.com/purchaseorders purchaseorders.xsd" xmlns="http://adsj.accenture.com/purchaseorders" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><order><customer><name>Gladys Kravitz</name><address>Anytown, PA</address><age>34</age><moo>0</moo><poo>0</poo></customer><date>2003-01-07 14:16:00.0 GMT</date><lineItems><lineItem><description>Burnham's Celestial Handbook, Vol 1</description><perUnitOunces>5.0</perUnitOunces><price>21.79</price><quantity>2</quantity></lineItem><lineItem><description>Burnham's Celestial Handbook, Vol 2</description><perUnitOunces>5.0</perUnitOunces><price>19.89</price><quantity>2</quantity></lineItem></lineItems></order><order><customer><name>John Smith</name><address>Chicago, IL</address><age>46</age><moo>0</moo><poo>0</poo></customer><date>2003-01-07 14:16:02.0 GMT</date><lineItems><lineItem><description>XmlBeans in Action</description><perUnitOunces>3.0</perUnitOunces><price>41.29</price><quantity>1</quantity></lineItem><lineItem><description>JSR-173</description><perUnitOunces>1.0</perUnitOunces><price>11.99</price><quantity>5</quantity></lineItem><lineItem><description>Teach Yourself XML in 21 days</description><perUnitOunces>1.0</perUnitOunces><price>35.49</price><quantity>1</quantity></lineItem></lineItems></order><order><customer><name>Peter Newman</name><address>Cleveland, OH</address><age>23</age><moo>0</moo><poo>0</poo></customer><date>2003-01-07 14:16:35.0 GMT</date><lineItems><lineItem><description>Java 6</description><perUnitOunces>2.0</perUnitOunces><price>12.79</price><quantity>3</quantity></lineItem></lineItems></order></purchaseOrders>