diff --git a/core/src/main/java/org/springframework/batch/core/domain/JobExecution.java b/core/src/main/java/org/springframework/batch/core/domain/JobExecution.java index 4b6b96d2d..c70869388 100644 --- a/core/src/main/java/org/springframework/batch/core/domain/JobExecution.java +++ b/core/src/main/java/org/springframework/batch/core/domain/JobExecution.java @@ -35,7 +35,7 @@ public class JobExecution extends Entity { private Long jobId; - private int exitCode; + private String exitCode = ""; // Package private constructor for Hibernate JobExecution() {} @@ -85,14 +85,14 @@ public class JobExecution extends Entity { /** * @param exitCode */ - public void setExitCode(int exitCode) { + public void setExitCode(String exitCode) { this.exitCode = exitCode; } /** * @return the exitCode */ - public int getExitCode() { + public String getExitCode() { return exitCode; } } diff --git a/core/src/main/java/org/springframework/batch/core/domain/StepExecution.java b/core/src/main/java/org/springframework/batch/core/domain/StepExecution.java index c5d45288d..f72899529 100644 --- a/core/src/main/java/org/springframework/batch/core/domain/StepExecution.java +++ b/core/src/main/java/org/springframework/batch/core/domain/StepExecution.java @@ -51,7 +51,11 @@ public class StepExecution extends Entity { private Long jobExecutionId; - private int exitCode; + private String exitCode = ""; + + private String exitDescription = ""; + + private Throwable exception; /** * Package private constructor for Hibernate @@ -176,15 +180,30 @@ public class StepExecution extends Entity { /** * @param exitCode */ - public void setExitCode(int exitCode) { + public void setExitCode(String exitCode) { this.exitCode = exitCode; } /** * @return the exitCode */ - public int getExitCode() { + public String getExitCode() { return exitCode; } + public void setException(Throwable exception) { + this.exception = exception; + } + + public Throwable getException() { + return exception; + } + + public void setExitDescription(String exitDescription) { + this.exitDescription = exitDescription; + } + + public String getExitDescription() { + return exitDescription; + } } diff --git a/core/src/main/java/org/springframework/batch/core/executor/JobExecutor.java b/core/src/main/java/org/springframework/batch/core/executor/JobExecutor.java index fb183fea8..96e0cb082 100644 --- a/core/src/main/java/org/springframework/batch/core/executor/JobExecutor.java +++ b/core/src/main/java/org/springframework/batch/core/executor/JobExecutor.java @@ -19,6 +19,7 @@ package org.springframework.batch.core.executor; import org.springframework.batch.core.configuration.JobConfiguration; import org.springframework.batch.core.runtime.JobExecutionContext; import org.springframework.batch.io.exception.BatchCriticalException; +import org.springframework.batch.repeat.ExitStatus; /** * Interface for running a job from its configuration. @@ -30,6 +31,6 @@ import org.springframework.batch.io.exception.BatchCriticalException; */ public interface JobExecutor { - public void run(JobConfiguration configuration, JobExecutionContext jobExecutionContext) throws BatchCriticalException; + public ExitStatus run(JobConfiguration configuration, JobExecutionContext jobExecutionContext) throws BatchCriticalException; } diff --git a/core/src/main/java/org/springframework/batch/core/tasklet/Tasklet.java b/core/src/main/java/org/springframework/batch/core/tasklet/Tasklet.java index 0499ac254..835a40d3b 100644 --- a/core/src/main/java/org/springframework/batch/core/tasklet/Tasklet.java +++ b/core/src/main/java/org/springframework/batch/core/tasklet/Tasklet.java @@ -17,6 +17,7 @@ package org.springframework.batch.core.tasklet; import org.springframework.batch.core.configuration.StepConfiguration; +import org.springframework.batch.repeat.ExitStatus; /** * The primary interface describing the touch-point between the batch developer @@ -46,9 +47,10 @@ public interface Tasklet { * outside of this method will prevent the architecture from gracefully * shutting down and providing such features as transaction rollback. * - * @return boolean indicating whether the processing should continue (i.e. + * @return ExitStatus indicating whether the processing should continue (i.e. * false when data are exhausted). + * @see org.springframework.batch.repeat.ExitStatus */ - public boolean execute() throws Exception; + public ExitStatus execute() throws Exception; } diff --git a/core/src/test/java/org/springframework/batch/core/configuration/StepConfigurationSupportTests.java b/core/src/test/java/org/springframework/batch/core/configuration/StepConfigurationSupportTests.java index 83ec82437..68a0184f0 100644 --- a/core/src/test/java/org/springframework/batch/core/configuration/StepConfigurationSupportTests.java +++ b/core/src/test/java/org/springframework/batch/core/configuration/StepConfigurationSupportTests.java @@ -18,6 +18,7 @@ package org.springframework.batch.core.configuration; import junit.framework.TestCase; import org.springframework.batch.core.tasklet.Tasklet; +import org.springframework.batch.repeat.ExitStatus; /** * @author Dave Syer @@ -58,8 +59,8 @@ public class StepConfigurationSupportTests extends TestCase { public void testGetTasklet() { assertEquals(null, configuration.getTasklet()); Tasklet tasklet = new Tasklet() { - public boolean execute() throws Exception { - return false; + public ExitStatus execute() throws Exception { + return ExitStatus.FINISHED; } }; configuration.setTasklet(tasklet); diff --git a/core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java b/core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java index 8d42d6cfc..0d8ce603a 100644 --- a/core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java +++ b/core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java @@ -74,9 +74,9 @@ public class JobExecutionTests extends TestCase { * Test method for {@link org.springframework.batch.core.domain.JobExecution#getExitCode()}. */ public void testGetExitCode() { - assertEquals(0, execution.getExitCode()); - execution.setExitCode(23); - assertEquals(23, execution.getExitCode()); + assertEquals("", execution.getExitCode()); + execution.setExitCode("23"); + assertEquals("23", execution.getExitCode()); } } diff --git a/core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java b/core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java index b9e8a5d9e..28bfb0cf9 100644 --- a/core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java +++ b/core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java @@ -73,9 +73,9 @@ public class StepExecutionTests extends TestCase { * Test method for {@link org.springframework.batch.core.domain.JobExecution#getExitCode()}. */ public void testGetExitCode() { - assertEquals(0, execution.getExitCode()); - execution.setExitCode(23); - assertEquals(23, execution.getExitCode()); + assertEquals("", execution.getExitCode()); + execution.setExitCode("23"); + assertEquals("23", execution.getExitCode()); } /** @@ -188,3 +188,4 @@ public class StepExecutionTests extends TestCase { } } + diff --git a/execution/src/main/java/org/springframework/batch/execution/JobExecutorFacade.java b/execution/src/main/java/org/springframework/batch/execution/JobExecutorFacade.java index 0da6c32e2..c711cea4f 100644 --- a/execution/src/main/java/org/springframework/batch/execution/JobExecutorFacade.java +++ b/execution/src/main/java/org/springframework/batch/execution/JobExecutorFacade.java @@ -18,6 +18,7 @@ package org.springframework.batch.execution; import org.springframework.batch.core.configuration.NoSuchJobConfigurationException; import org.springframework.batch.core.runtime.JobIdentifier; +import org.springframework.batch.repeat.ExitStatus; /** * Interface which defines a facade for running jobs. The interface is @@ -40,7 +41,7 @@ public interface JobExecutorFacade { * * @throws NoSuchJobConfigurationException */ - void start(JobIdentifier runtimeInformation) throws NoSuchJobConfigurationException; + ExitStatus start(JobIdentifier runtimeInformation) throws NoSuchJobConfigurationException; /** * Stop the job execution that was started with this runtime information. diff --git a/execution/src/main/java/org/springframework/batch/execution/bootstrap/BatchCommandLineLauncher.java b/execution/src/main/java/org/springframework/batch/execution/bootstrap/BatchCommandLineLauncher.java index fed173b97..73e2cafe0 100644 --- a/execution/src/main/java/org/springframework/batch/execution/bootstrap/BatchCommandLineLauncher.java +++ b/execution/src/main/java/org/springframework/batch/execution/bootstrap/BatchCommandLineLauncher.java @@ -35,7 +35,7 @@ public class BatchCommandLineLauncher { private ConfigurableApplicationContext parent; - private JobLauncher launcher; + private SynchronousJobLauncher launcher; /** * Default constructor for the launcher. Sets up the parent context to use @@ -51,7 +51,7 @@ public class BatchCommandLineLauncher { * * @param launcher the launcher to set */ - public void setLauncher(JobLauncher launcher) { + public void setLauncher(SynchronousJobLauncher launcher) { this.launcher = launcher; } @@ -70,10 +70,10 @@ public class BatchCommandLineLauncher { try { if (!launcher.isRunning()) { if (jobName == null) { - launcher.start(); + launcher.run(); } else { - launcher.start(jobName); + launcher.run(jobName); } } } diff --git a/execution/src/main/java/org/springframework/batch/execution/bootstrap/SimpleJobLauncher.java b/execution/src/main/java/org/springframework/batch/execution/bootstrap/SimpleJobLauncher.java index 3943967d1..0024de97c 100644 --- a/execution/src/main/java/org/springframework/batch/execution/bootstrap/SimpleJobLauncher.java +++ b/execution/src/main/java/org/springframework/batch/execution/bootstrap/SimpleJobLauncher.java @@ -16,10 +16,17 @@ package org.springframework.batch.execution.bootstrap; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.configuration.JobConfiguration; import org.springframework.batch.core.configuration.NoSuchJobConfigurationException; import org.springframework.batch.core.runtime.JobIdentifier; +import org.springframework.batch.core.runtime.JobIdentifierFactory; import org.springframework.batch.execution.JobExecutorFacade; +import org.springframework.batch.execution.runtime.ScheduledJobIdentifierFactory; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.context.Lifecycle; +import org.springframework.util.Assert; /** * Simple bootstrapping mechanism for running a single job execution in a @@ -36,11 +43,29 @@ import org.springframework.context.Lifecycle; * @author Dave Syer * @since 2.1 */ -public class SimpleJobLauncher extends AbstractJobLauncher { +public class SimpleJobLauncher implements SynchronousJobLauncher { + + private static final Log logger = LogFactory.getLog(SimpleJobLauncher.class); private volatile Thread processingThread; private volatile boolean running = false; + + private JobExecutorFacade jobExecutorFacade; + + private JobIdentifierFactory jobIdentifierFactory = new ScheduledJobIdentifierFactory();; + + private String jobConfigurationName; + + /** + * Check that mandatory properties are set. + * + * @see #setBatchContainer(JobExecutorFacade) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(jobExecutorFacade); + } /** * Return whether or not the container is currently running. This is done by @@ -51,7 +76,7 @@ public class SimpleJobLauncher extends AbstractJobLauncher { } /** - * Start the provided container. The current thread will first be saved. + * Start the provided facade. The current thread will first be saved. * This may seem odd at first, however, this simple bootstrap requires that * only one thread can kick off a container, and that the first thread that * calls start is the 'processing thread'. If the container has already been @@ -61,26 +86,64 @@ public class SimpleJobLauncher extends AbstractJobLauncher { * * @throws IllegalStateException if JobConfiguration is null. */ - protected void doStart(JobIdentifier jobIdentifier) throws NoSuchJobConfigurationException { + public ExitStatus run(JobIdentifier jobIdentifier) throws NoSuchJobConfigurationException { + Assert.notNull(jobIdentifier, "JobIdentifier must not be null."); + Assert.isTrue(!isRunning(), "SynchronousLaunchers can run only one job at at time."); + /* * There is no reason to kick off a new thread, since only one thread * should be processing at once. However, a handle to the thread should * be maintained to allow for interrupt */ processingThread = Thread.currentThread(); - // TODO: push this out to a method call in parent inside synchronized - // block? + running = true; try { - batchContainer.start(jobIdentifier); + return jobExecutorFacade.start(jobIdentifier); } finally { running = false; - unregister(jobIdentifier); } } + + /** + * Start a job execution with the given name. If a job is already running + * has no effect. + * + * @param name the name to assign to the job + * @throws NoSuchJobConfigurationException + */ + public ExitStatus run(String name) throws NoSuchJobConfigurationException { + JobIdentifier runtimeInformation = jobIdentifierFactory.getJobIdentifier(name); + return this.run(runtimeInformation); + } + + /** + * Start a job execution with default name and other runtime information + * provided by the factory. If a job is already running has no effect. The + * default name is taken from the enclosed {@link JobConfiguration}. + * @throws NoSuchJobConfigurationException if the job configuration cannot be located + * + * @see #setJobRuntimeInformationFactory(JobIdentifierFactory) + * @see org.springframework.context.Lifecycle#start() + */ + public ExitStatus run(){ + if (jobConfigurationName==null) { + return new ExitStatus(false, "JOB_CONFIGURATION_NOT_PROVIDED", "No JobConfiguration was " + + "provided to the launcher."); + } + try { + return this.run(jobConfigurationName); + } + catch (NoSuchJobConfigurationException e) { + logger.error("JobExecutorFacade failed to find a JobConfiguration" + + " for the provided JobIdentifier", e); + return new ExitStatus(false, "NO_SUCH_JOB_CONFIGURATION", "JobExecutor Facade failed" + + "to find a JobConfiguration for the provided JobIdentifier"); + } + } /** * Stop the job if it is running by interrupting its thread. If no job is @@ -89,22 +152,24 @@ public class SimpleJobLauncher extends AbstractJobLauncher { * (non-Javadoc) * @see org.springframework.context.Lifecycle#stop() */ - protected void doStop() { + public void stop() { if (isRunning()) { processingThread.interrupt(); running = false; } } - - /** - * Delegates to {@link #doStop()}. Since there is only one job running in - * this launcher this is OK. - * - * (non-Javadoc) - * @see org.springframework.context.Lifecycle#stop() - */ - protected void doStop(JobIdentifier runtimeInformation) { - doStop(); + + public void setJobExecutorFacade(JobExecutorFacade jobExecutorFacade) { + this.jobExecutorFacade = jobExecutorFacade; + } + + public void setJobIdentifierFactory( + JobIdentifierFactory jobIdentifierFactory) { + this.jobIdentifierFactory = jobIdentifierFactory; + } + + public void setJobConfigurationName(String jobConfigurationName) { + this.jobConfigurationName = jobConfigurationName; } } diff --git a/execution/src/main/java/org/springframework/batch/execution/facade/SimpleJobExecutorFacade.java b/execution/src/main/java/org/springframework/batch/execution/facade/SimpleJobExecutorFacade.java index 70fd06c47..510f14fd5 100644 --- a/execution/src/main/java/org/springframework/batch/execution/facade/SimpleJobExecutorFacade.java +++ b/execution/src/main/java/org/springframework/batch/execution/facade/SimpleJobExecutorFacade.java @@ -31,6 +31,7 @@ import org.springframework.batch.core.runtime.JobIdentifier; import org.springframework.batch.execution.JobExecutorFacade; import org.springframework.batch.execution.NoSuchJobExecutionException; import org.springframework.batch.execution.job.DefaultJobExecutor; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatContext; import org.springframework.batch.statistics.StatisticsProvider; import org.springframework.util.Assert; @@ -113,7 +114,7 @@ public class SimpleJobExecutorFacade implements JobExecutorFacade, StatisticsPro * null * */ - public void start(JobIdentifier jobRuntimeInformation) throws NoSuchJobConfigurationException { + public ExitStatus start(JobIdentifier jobRuntimeInformation) throws NoSuchJobConfigurationException { Assert.notNull(jobRuntimeInformation, "JobRuntimeInformation must not be null."); Assert.notNull(jobRuntimeInformation.getName(), "JobRuntimeInformation name must not be null."); @@ -129,11 +130,13 @@ public class SimpleJobExecutorFacade implements JobExecutorFacade, StatisticsPro final JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation); JobExecutionContext jobExecutionContext = jobExecutionRegistry.register(jobRuntimeInformation, job); + + ExitStatus exitStatus = ExitStatus.FAILED; try { synchronized (mutex) { running++; } - jobExecutor.run(jobConfiguration, jobExecutionContext); + exitStatus = jobExecutor.run(jobConfiguration, jobExecutionContext); } finally { synchronized (mutex) { @@ -144,6 +147,7 @@ public class SimpleJobExecutorFacade implements JobExecutorFacade, StatisticsPro jobExecutionRegistry.unregister(jobRuntimeInformation); } + return exitStatus; } /* diff --git a/execution/src/main/java/org/springframework/batch/execution/job/DefaultJobExecutor.java b/execution/src/main/java/org/springframework/batch/execution/job/DefaultJobExecutor.java index 7b6e9f009..846c212c6 100644 --- a/execution/src/main/java/org/springframework/batch/execution/job/DefaultJobExecutor.java +++ b/execution/src/main/java/org/springframework/batch/execution/job/DefaultJobExecutor.java @@ -51,7 +51,7 @@ public class DefaultJobExecutor implements JobExecutor { private StepExecutorFactory stepExecutorResolver = new DefaultStepExecutorFactory(); - public void run(JobConfiguration configuration, JobExecutionContext jobExecutionContext) + public ExitStatus run(JobConfiguration configuration, JobExecutionContext jobExecutionContext) throws BatchCriticalException { JobInstance job = jobExecutionContext.getJob(); @@ -90,6 +90,8 @@ public class DefaultJobExecutor implements JobExecutor { jobExecution.setExitCode(status.getExitCode()); jobRepository.saveOrUpdate(jobExecution); } + + return status; } private void updateStatus(JobExecutionContext jobExecutionContext, BatchStatus status) { diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java index 876283a45..188e8a361 100644 --- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java @@ -227,7 +227,7 @@ public class SqlStepDao implements StepDao, InitializingBean { Object[] parameters = new Object[] { stepExecution.getId(), new Long(0), stepExecution.getStepId(), stepExecution.getJobExecutionId(), stepExecution.getStartTime(), stepExecution.getEndTime(), stepExecution.getStatus().toString(), stepExecution.getCommitCount(), stepExecution.getTaskCount(), - PropertiesConverter.propertiesToString(stepExecution.getStatistics()), new Integer(stepExecution.getExitCode()) }; + PropertiesConverter.propertiesToString(stepExecution.getStatistics()), stepExecution.getExitCode() }; jdbcTemplate.update(SAVE_STEP_EXECUTION, parameters); } @@ -252,7 +252,7 @@ public class SqlStepDao implements StepDao, InitializingBean { Object[] parameters = new Object[] { stepExecution.getStartTime(), stepExecution.getEndTime(), stepExecution.getStatus().toString(), stepExecution.getCommitCount(), stepExecution.getTaskCount(), PropertiesConverter.propertiesToString(stepExecution.getStatistics()), - new Integer(stepExecution.getExitCode()), + stepExecution.getExitCode(), stepExecution.getId() }; jdbcTemplate.update(UPDATE_STEP_EXECUTION, parameters); @@ -292,7 +292,7 @@ public class SqlStepDao implements StepDao, InitializingBean { stepExecution.setCommitCount(rs.getInt(6)); stepExecution.setTaskCount(rs.getInt(7)); stepExecution.setStatistics(PropertiesConverter.stringToProperties(rs.getString(8))); - stepExecution.setExitCode(rs.getInt(9)); + stepExecution.setExitCode(rs.getString(9)); return stepExecution; } }; diff --git a/execution/src/main/java/org/springframework/batch/execution/step/simple/DefaultStepExecutor.java b/execution/src/main/java/org/springframework/batch/execution/step/simple/DefaultStepExecutor.java index 171810ed2..c32db2c83 100644 --- a/execution/src/main/java/org/springframework/batch/execution/step/simple/DefaultStepExecutor.java +++ b/execution/src/main/java/org/springframework/batch/execution/step/simple/DefaultStepExecutor.java @@ -20,6 +20,7 @@ import org.springframework.batch.core.domain.StepInstance; import org.springframework.batch.core.tasklet.Tasklet; import org.springframework.batch.core.tasklet.Recoverable; import org.springframework.batch.io.Skippable; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; @@ -50,13 +51,13 @@ public class DefaultStepExecutor extends SimpleStepExecutor { * @see org.springframework.batch.execution.step.simple.SimpleStepExecutor#doTaskletProcessing(org.springframework.batch.core.tasklet.Tasklet, * org.springframework.batch.core.domain.StepInstance) */ - protected boolean doTaskletProcessing(Tasklet module, final StepInstance step) throws Exception { + protected ExitStatus doTaskletProcessing(Tasklet module, final StepInstance step) throws Exception { - boolean result = true; + ExitStatus exitStatus = ExitStatus.CONTINUABLE; try { - result = super.doTaskletProcessing(module, step); + exitStatus = super.doTaskletProcessing(module, step); } catch (final Exception e) { @@ -80,7 +81,7 @@ public class DefaultStepExecutor extends SimpleStepExecutor { } - return result; + return exitStatus; } } diff --git a/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java b/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java index 930b5c6c9..3d9042c77 100644 --- a/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java +++ b/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java @@ -247,10 +247,13 @@ public class SimpleStepExecutor implements StepExecutor { }); stepExecution.setExitCode(status.getExitCode()); + stepExecution.setExitDescription(status.getExitDescription()); updateStatus(stepExecutionContext, BatchStatus.COMPLETED); return status; } catch (RuntimeException e) { + + stepExecution.setException(e); if (e.getCause() instanceof StepInterruptedException) { updateStatus(stepExecutionContext, BatchStatus.STOPPED); throw (StepInterruptedException) e.getCause(); @@ -320,11 +323,11 @@ public class SimpleStepExecutor implements StepExecutor { }); // check for interruption before each item as well interruptionPolicy.checkInterrupted(context); - boolean result = doTaskletProcessing(configuration.getTasklet(), stepExecutionContext.getStep()); + ExitStatus exitStatus = doTaskletProcessing(configuration.getTasklet(), stepExecutionContext.getStep()); stepExecutionContext.getStepExecution().incrementTaskCount(); // check for interruption after each item as well interruptionPolicy.checkInterrupted(context); - return new ExitStatus(result); + return exitStatus; } }); } @@ -338,7 +341,7 @@ public class SimpleStepExecutor implements StepExecutor { * @return boolean if there is more processing to do * @throws Exception if there is an error */ - protected boolean doTaskletProcessing(Tasklet tasklet, StepInstance step) throws Exception { + protected ExitStatus doTaskletProcessing(Tasklet tasklet, StepInstance step) throws Exception { return tasklet.execute(); } diff --git a/execution/src/main/java/org/springframework/batch/execution/tasklet/ItemProviderProcessTasklet.java b/execution/src/main/java/org/springframework/batch/execution/tasklet/ItemProviderProcessTasklet.java index 2339eaed8..aaf9b83c5 100644 --- a/execution/src/main/java/org/springframework/batch/execution/tasklet/ItemProviderProcessTasklet.java +++ b/execution/src/main/java/org/springframework/batch/execution/tasklet/ItemProviderProcessTasklet.java @@ -27,6 +27,7 @@ import org.springframework.batch.core.tasklet.Tasklet; import org.springframework.batch.io.Skippable; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemProvider; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatContext; import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; import org.springframework.batch.retry.RetryOperations; @@ -132,14 +133,14 @@ public class ItemProviderProcessTasklet implements Tasklet, Recoverable, Skippab * * @see org.springframework.batch.core.tasklet.Tasklet#execute() */ - public boolean execute() throws Exception { + public ExitStatus execute() throws Exception { if (retryOperations != null) { - return retryOperations.execute(new ItemProviderRetryCallback(itemProvider, itemProcessor)) != null; + return new ExitStatus(retryOperations.execute(new ItemProviderRetryCallback(itemProvider, itemProcessor)) != null); } else { Object data = itemProvider.next(); if (data == null) { - return false; + return ExitStatus.FINISHED; } RepeatContext context = RepeatSynchronizationManager.getContext(); Assert.state(context != null, @@ -149,7 +150,7 @@ public class ItemProviderProcessTasklet implements Tasklet, Recoverable, Skippab // No exception so clear context (we can't recover directly because // the current transaction is going to roll back) context.removeAttribute(ITEM_KEY); - return true; + return ExitStatus.CONTINUABLE; } } diff --git a/execution/src/main/java/org/springframework/batch/execution/tasklet/ReadProcessTasklet.java b/execution/src/main/java/org/springframework/batch/execution/tasklet/ReadProcessTasklet.java index eb64bc20f..887d37e4b 100644 --- a/execution/src/main/java/org/springframework/batch/execution/tasklet/ReadProcessTasklet.java +++ b/execution/src/main/java/org/springframework/batch/execution/tasklet/ReadProcessTasklet.java @@ -17,6 +17,7 @@ package org.springframework.batch.execution.tasklet; import org.springframework.batch.core.tasklet.Tasklet; +import org.springframework.batch.repeat.ExitStatus; /** * Provides the basic batch module for reading and processing data. @@ -39,12 +40,12 @@ public abstract class ReadProcessTasklet implements Tasklet { * from the abstract read method will be returned to the {@link Tasklet}, to indicate * whether or not processing should continue. */ - public final boolean execute() throws Exception { + public final ExitStatus execute() throws Exception { if (!read()) { - return false; + return ExitStatus.FINISHED; } process(); - return true; + return ExitStatus.CONTINUABLE; } /** diff --git a/execution/src/main/resources/schema-db2.sql b/execution/src/main/resources/schema-db2.sql index 2ac110a60..638ab009c 100644 --- a/execution/src/main/resources/schema-db2.sql +++ b/execution/src/main/resources/schema-db2.sql @@ -26,7 +26,7 @@ CREATE TABLE BATCH_JOB_EXECUTION ( START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , STATUS VARCHAR(10), - EXIT_CODE BIGINT); + EXIT_CODE VARCHAR(250)); CREATE TABLE BATCH_STEP ( ID BIGINT PRIMARY KEY , @@ -47,7 +47,7 @@ CREATE TABLE BATCH_STEP_EXECUTION ( COMMIT_COUNT BIGINT , TASK_COUNT BIGINT , TASK_STATISTICS VARCHAR(250), - EXIT_CODE BIGINT, + EXIT_CODE VARCHAR(250), EXIT_MESSAGE VARCHAR(250)); CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; diff --git a/execution/src/main/resources/schema-derby.sql b/execution/src/main/resources/schema-derby.sql index c27ebc8cc..bf2f8d700 100644 --- a/execution/src/main/resources/schema-derby.sql +++ b/execution/src/main/resources/schema-derby.sql @@ -26,7 +26,7 @@ CREATE TABLE BATCH_JOB_EXECUTION ( START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , STATUS VARCHAR(10), - EXIT_CODE BIGINT); + EXIT_CODE VARCHAR(250)); CREATE TABLE BATCH_STEP ( ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, @@ -47,7 +47,7 @@ CREATE TABLE BATCH_STEP_EXECUTION ( COMMIT_COUNT BIGINT , TASK_COUNT BIGINT , TASK_STATISTICS VARCHAR(250), - EXIT_CODE BIGINT, + EXIT_CODE VARCHAR(250), EXIT_MESSAGE VARCHAR(250)); CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; diff --git a/execution/src/main/resources/schema-hsqldb.sql b/execution/src/main/resources/schema-hsqldb.sql index 40dd02f1b..297529fdb 100644 --- a/execution/src/main/resources/schema-hsqldb.sql +++ b/execution/src/main/resources/schema-hsqldb.sql @@ -26,7 +26,7 @@ CREATE TABLE BATCH_JOB_EXECUTION ( START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , STATUS VARCHAR(10), - EXIT_CODE BIGINT); + EXIT_CODE VARCHAR(250)); CREATE TABLE BATCH_STEP ( ID BIGINT IDENTITY PRIMARY KEY , @@ -47,7 +47,7 @@ CREATE TABLE BATCH_STEP_EXECUTION ( COMMIT_COUNT BIGINT , TASK_COUNT BIGINT , TASK_STATISTICS VARCHAR(250), - EXIT_CODE BIGINT, + EXIT_CODE VARCHAR(250), EXIT_MESSAGE VARCHAR(250)); CREATE TABLE BATCH_STEP_EXECUTION_SEQ ( diff --git a/execution/src/main/resources/schema-oracle10g.sql b/execution/src/main/resources/schema-oracle10g.sql index 1f591e38f..038a1d6c2 100644 --- a/execution/src/main/resources/schema-oracle10g.sql +++ b/execution/src/main/resources/schema-oracle10g.sql @@ -26,7 +26,7 @@ CREATE TABLE BATCH_JOB_EXECUTION ( START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , STATUS VARCHAR(10), - EXIT_CODE INT); + EXIT_CODE VARCHAR(250)); CREATE TABLE BATCH_STEP ( ID INT PRIMARY KEY , @@ -47,7 +47,7 @@ CREATE TABLE BATCH_STEP_EXECUTION ( COMMIT_COUNT INT , TASK_COUNT INT , TASK_STATISTICS VARCHAR(250), - EXIT_CODE INT, + EXIT_CODE VARCHAR(250), EXIT_MESSAGE VARCHAR(250)); CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; diff --git a/execution/src/main/resources/schema-postgresql.sql b/execution/src/main/resources/schema-postgresql.sql index 2ac110a60..638ab009c 100644 --- a/execution/src/main/resources/schema-postgresql.sql +++ b/execution/src/main/resources/schema-postgresql.sql @@ -26,7 +26,7 @@ CREATE TABLE BATCH_JOB_EXECUTION ( START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , STATUS VARCHAR(10), - EXIT_CODE BIGINT); + EXIT_CODE VARCHAR(250)); CREATE TABLE BATCH_STEP ( ID BIGINT PRIMARY KEY , @@ -47,7 +47,7 @@ CREATE TABLE BATCH_STEP_EXECUTION ( COMMIT_COUNT BIGINT , TASK_COUNT BIGINT , TASK_STATISTICS VARCHAR(250), - EXIT_CODE BIGINT, + EXIT_CODE VARCHAR(250), EXIT_MESSAGE VARCHAR(250)); CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; diff --git a/execution/src/main/sql/init.sql.vpp b/execution/src/main/sql/init.sql.vpp index 76157be5c..b2c29a1ec 100644 --- a/execution/src/main/sql/init.sql.vpp +++ b/execution/src/main/sql/init.sql.vpp @@ -15,7 +15,7 @@ CREATE TABLE BATCH_JOB_EXECUTION ( START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , STATUS VARCHAR(10), - EXIT_CODE ${BIGINT}); + EXIT_CODE VARCHAR(250)); CREATE TABLE BATCH_STEP ( ID ${BIGINT} $!{IDENTITY} PRIMARY KEY $!{GENERATED}, @@ -36,7 +36,7 @@ CREATE TABLE BATCH_STEP_EXECUTION ( COMMIT_COUNT ${BIGINT} , TASK_COUNT ${BIGINT} , TASK_STATISTICS VARCHAR(250), - EXIT_CODE ${BIGINT}, + EXIT_CODE VARCHAR(250), EXIT_MESSAGE VARCHAR(250)); #sequence( "BATCH_STEP_EXECUTION_SEQ" ) diff --git a/execution/src/test/java/org/springframework/batch/execution/bootstrap/SimpleJobLauncherTests.java b/execution/src/test/java/org/springframework/batch/execution/bootstrap/SimpleJobLauncherTests.java index 4d9fcc372..38af89b16 100644 --- a/execution/src/test/java/org/springframework/batch/execution/bootstrap/SimpleJobLauncherTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/bootstrap/SimpleJobLauncherTests.java @@ -20,70 +20,24 @@ import junit.framework.TestCase; import org.easymock.MockControl; import org.springframework.batch.core.configuration.JobConfiguration; +import org.springframework.batch.core.configuration.NoSuchJobConfigurationException; import org.springframework.batch.core.runtime.JobIdentifier; import org.springframework.batch.core.runtime.JobIdentifierFactory; import org.springframework.batch.core.runtime.SimpleJobIdentifier; import org.springframework.batch.execution.JobExecutorFacade; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.context.ApplicationEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.core.task.TaskExecutor; public class SimpleJobLauncherTests extends TestCase { - public void testAutoStartContainer() throws Exception { - - MockControl containerControl = MockControl.createControl(JobExecutorFacade.class); - JobExecutorFacade mockContainer; - - AbstractJobLauncher bootstrap = new SimpleJobLauncher(); - final SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("foo"); - bootstrap.setJobRuntimeInformationFactory(new JobIdentifierFactory() { - public JobIdentifier getJobIdentifier(String name) { - return runtimeInformation; - } - }); - mockContainer = (JobExecutorFacade) containerControl.getMock(); - bootstrap.setBatchContainer(mockContainer); - - JobConfiguration jobConfiguration = new JobConfiguration("foo"); - bootstrap.setJobConfigurationName(jobConfiguration.getName()); - - mockContainer.start(runtimeInformation); - containerControl.replay(); - - bootstrap.setAutoStart(true); - - bootstrap.onApplicationEvent(new ContextRefreshedEvent(new GenericApplicationContext())); - // It ran and then stopped... - assertFalse(bootstrap.isRunning()); - - containerControl.verify(); - } - - public void testApplicationEventNotContextRefresh() throws Exception { - - MockControl containerControl = MockControl.createControl(JobExecutorFacade.class); - JobExecutorFacade mockContainer; - - AbstractJobLauncher bootstrap = new SimpleJobLauncher(); - mockContainer = (JobExecutorFacade) containerControl.getMock(); - bootstrap.setBatchContainer(mockContainer); - - containerControl.replay(); - - bootstrap.setAutoStart(true); - - bootstrap.onApplicationEvent(new ApplicationEvent(new GenericApplicationContext()) { - }); - assertFalse(bootstrap.isRunning()); - - containerControl.verify(); - } - public void testStartWithNoConfiguration() throws Exception { - final AbstractJobLauncher bootstrap = new SimpleJobLauncher(); + final SimpleJobLauncher launcher = new SimpleJobLauncher(); try { - bootstrap.afterPropertiesSet(); + launcher.afterPropertiesSet(); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { @@ -93,9 +47,9 @@ public class SimpleJobLauncherTests extends TestCase { } public void testInitializeWithNoConfiguration() throws Exception { - final AbstractJobLauncher bootstrap = new SimpleJobLauncher(); + final SimpleJobLauncher launcher = new SimpleJobLauncher(); try { - bootstrap.start(); + launcher.run(); // should do nothing } catch (Exception e) { @@ -103,83 +57,93 @@ public class SimpleJobLauncherTests extends TestCase { } } - public void testStartTwiceNotFatal() throws Exception { - AbstractJobLauncher bootstrap = new SimpleJobLauncher(); + public void testRunTwiceNotFatal() throws Exception { + SimpleJobLauncher launcher = new SimpleJobLauncher(); final SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("foo"); - bootstrap.setJobRuntimeInformationFactory(new JobIdentifierFactory() { + launcher.setJobIdentifierFactory(new JobIdentifierFactory() { public JobIdentifier getJobIdentifier(String name) { return runtimeInformation; } }); - InterruptibleContainer container = new InterruptibleContainer(); - bootstrap.setBatchContainer(container); - bootstrap.setJobConfigurationName(new JobConfiguration("foo").getName()); - bootstrap.start(); - bootstrap.start(); + InterruptibleFacade jobExecutorFacade = new InterruptibleFacade(); + launcher.setJobExecutorFacade(jobExecutorFacade); + launcher.setJobConfigurationName(new JobConfiguration("foo").getName()); + launcher.run(); + launcher.run(); // Both jobs finished running because they were not launched in a new // Thread - assertFalse(bootstrap.isRunning()); + assertFalse(launcher.isRunning()); } public void testInterruptContainer() throws Exception { - final AbstractJobLauncher bootstrap = new SimpleJobLauncher(); + final SimpleJobLauncher launcher = new SimpleJobLauncher(); final SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("foo"); - bootstrap.setJobRuntimeInformationFactory(new JobIdentifierFactory() { + launcher.setJobIdentifierFactory(new JobIdentifierFactory() { public JobIdentifier getJobIdentifier(String name) { return runtimeInformation; } }); - InterruptibleContainer container = new InterruptibleContainer(); - bootstrap.setBatchContainer(container); - bootstrap.setJobConfigurationName(new JobConfiguration("foo").getName()); - - Thread bootstrapThread = new Thread() { + InterruptibleFacade jobExecutorFacade = new InterruptibleFacade(); + launcher.setJobExecutorFacade(jobExecutorFacade); + launcher.setJobConfigurationName(new JobConfiguration("foo").getName()); + + TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); + Runnable launcherRunnable = new Runnable() { public void run() { - bootstrap.start(); + System.out.println("run called"); + launcher.run(); + System.out.println("run finished."); } }; - bootstrapThread.start(); - + taskExecutor.execute(launcherRunnable); + // give the thread a second to start up + System.out.println("first sleep"); Thread.sleep(100); - assertTrue(bootstrap.isRunning()); - bootstrap.stop(); + assertTrue(launcher.isRunning()); + launcher.stop(); Thread.sleep(100); - assertFalse(bootstrap.isRunning()); + assertFalse(launcher.isRunning()); } - public void testStopOnUnstartedContainer() { + public void testStopOnUnranLauncher() { - AbstractJobLauncher bootstrap = new SimpleJobLauncher(); + SimpleJobLauncher launcher = new SimpleJobLauncher(); - assertFalse(bootstrap.isRunning()); - // no exception should be thrown if stop is called on unstarted + assertFalse(launcher.isRunning()); + // no exception should be thrown if stop is called on unran // container // this is to fullfill the contract outlined in Lifecycle#stop(). - bootstrap.stop(); + launcher.stop(); } - private class InterruptibleContainer implements JobExecutorFacade { + private class InterruptibleFacade implements JobExecutorFacade { /* * (non-Javadoc) - * @see org.springframework.batch.container.BatchContainer#start() + * @see org.springframework.batch.container.BatchContainer#run() */ - public void start() { + public void run() { try { // 1 seconds should be long enough to allow the thread to be - // started and - // for interrupt to be called; + // run and for interrupt to be called; + System.out.println("Facade sleep called."); Thread.sleep(300); + //return ExitStatus.FAILED; + } catch (InterruptedException ex) { // thread interrupted, allow to exit normally + //return ExitStatus.FAILED; } + + } - public void start(JobIdentifier runtimeInformation) { - start(); + public ExitStatus start(JobIdentifier runtimeInformation) { + run(); + return ExitStatus.FAILED; } public void stop(JobIdentifier runtimeInformation) { diff --git a/execution/src/test/java/org/springframework/batch/execution/bootstrap/TaskExecutorJobLauncherTests.java b/execution/src/test/java/org/springframework/batch/execution/bootstrap/TaskExecutorJobLauncherTests.java index b773a2e43..d88377169 100644 --- a/execution/src/test/java/org/springframework/batch/execution/bootstrap/TaskExecutorJobLauncherTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/bootstrap/TaskExecutorJobLauncherTests.java @@ -31,6 +31,7 @@ import org.springframework.batch.core.runtime.JobIdentifier; import org.springframework.batch.core.runtime.JobIdentifierFactory; import org.springframework.batch.core.runtime.SimpleJobIdentifier; import org.springframework.batch.execution.JobExecutorFacade; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.interceptor.RepeatOperationsApplicationEvent; import org.springframework.batch.statistics.StatisticsProvider; import org.springframework.batch.support.PropertiesConverter; @@ -142,8 +143,9 @@ public class TaskExecutorJobLauncherTests extends TestCase { } } - public void start(JobIdentifier runtimeInformation) { + public ExitStatus start(JobIdentifier runtimeInformation) { start(); + return ExitStatus.FAILED; } public void stop(JobIdentifier runtimeInformation) { diff --git a/execution/src/test/java/org/springframework/batch/execution/facade/SimpleJobExecutorFacaderTests.java b/execution/src/test/java/org/springframework/batch/execution/facade/SimpleJobExecutorFacaderTests.java index 3f07e3bff..1c9bd774f 100644 --- a/execution/src/test/java/org/springframework/batch/execution/facade/SimpleJobExecutorFacaderTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/facade/SimpleJobExecutorFacaderTests.java @@ -80,8 +80,9 @@ public class SimpleJobExecutorFacaderTests extends TestCase { final SimpleJobIdentifier jobRuntimeInformation = new SimpleJobIdentifier("bar"); jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation); jobExecutor = new JobExecutor() { - public void run(JobConfiguration configuration, JobExecutionContext jobExecutionContext) throws BatchCriticalException { + public ExitStatus run(JobConfiguration configuration, JobExecutionContext jobExecutionContext) throws BatchCriticalException { jobExecutionContext.getJob().setIdentifier(jobRuntimeInformation); + return ExitStatus.FINISHED; } }; JobInstance job = new JobInstance(); @@ -104,7 +105,7 @@ public class SimpleJobExecutorFacaderTests extends TestCase { public void testIsRunning() throws Exception { simpleContainer.setJobExecutor(new JobExecutor() { - public void run(JobConfiguration configuration, JobExecutionContext jobExecutionContext) + public ExitStatus run(JobConfiguration configuration, JobExecutionContext jobExecutionContext) throws BatchCriticalException { while (running) { try { @@ -113,7 +114,11 @@ public class SimpleJobExecutorFacaderTests extends TestCase { catch (InterruptedException e) { throw new BatchCriticalException("Interrupted unexpectedly!"); } + + } + + return ExitStatus.FINISHED; } }); simpleContainer.setJobConfigurationLocator(new JobConfigurationLocator() { diff --git a/execution/src/test/java/org/springframework/batch/execution/job/DefaultJobExecutorTests.java b/execution/src/test/java/org/springframework/batch/execution/job/DefaultJobExecutorTests.java index 2df9f3d35..f9a94d38b 100644 --- a/execution/src/test/java/org/springframework/batch/execution/job/DefaultJobExecutorTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/job/DefaultJobExecutorTests.java @@ -241,7 +241,5 @@ public class DefaultJobExecutorTests extends TestCase { JobExecution jobExecution = (JobExecution) jobDao.findJobExecutions(job).get(0); assertEquals(job.getId(), jobExecution.getJobId()); assertEquals(status, jobExecution.getStatus()); - int exitCode = status==BatchStatus.STOPPED || status==BatchStatus.FAILED ? -1 : 0; - assertEquals(exitCode, jobExecution.getExitCode()); } } diff --git a/execution/src/test/java/org/springframework/batch/execution/step/simple/ChunkOperationsStepConfigurationTests.java b/execution/src/test/java/org/springframework/batch/execution/step/simple/ChunkOperationsStepConfigurationTests.java index 3e44d388e..0342b5279 100644 --- a/execution/src/test/java/org/springframework/batch/execution/step/simple/ChunkOperationsStepConfigurationTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/step/simple/ChunkOperationsStepConfigurationTests.java @@ -18,6 +18,7 @@ package org.springframework.batch.execution.step.simple; import junit.framework.TestCase; import org.springframework.batch.core.tasklet.Tasklet; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.support.RepeatTemplate; /** @@ -42,8 +43,8 @@ public class ChunkOperationsStepConfigurationTests extends TestCase { */ public void testStepExecutorStepConfigurationTasklet() { Tasklet tasklet = new Tasklet() { - public boolean execute() throws Exception { - return false; + public ExitStatus execute() throws Exception { + return ExitStatus.FINISHED; } }; configuration = new ChunkOperationsStepConfiguration(tasklet); diff --git a/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java b/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java index 5208ef06f..9c736d929 100644 --- a/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java @@ -36,6 +36,7 @@ import org.springframework.batch.execution.tasklet.ItemProviderProcessTasklet; 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.policy.SimpleCompletionPolicy; import org.springframework.batch.repeat.support.RepeatTemplate; @@ -129,13 +130,13 @@ public class DefaultStepExecutorTests extends TestCase { final StepExecutionContext stepExecutionContext = new StepExecutionContext(jobExecutionContext, step); stepConfiguration.setTasklet(new Tasklet() { - public boolean execute() throws Exception { + public ExitStatus execute() throws Exception { assertEquals(step, stepExecutionContext.getStep()); assertEquals(1, jobExecutionContext.getChunkContexts().size()); assertEquals(1, jobExecutionContext.getStepContexts().size()); assertNotNull(StepSynchronizationManager.getContext().getJobIdentifier()); processed.add("foo"); - return true; + return ExitStatus.CONTINUABLE; } }); @@ -166,7 +167,7 @@ public class DefaultStepExecutorTests extends TestCase { Tasklet module = new Tasklet(){ - public boolean execute() throws Exception { + public ExitStatus execute() throws Exception { int counter = 0; counter++; @@ -174,7 +175,7 @@ public class DefaultStepExecutorTests extends TestCase { throw new Exception(); } - return true; + return ExitStatus.CONTINUABLE; } }; diff --git a/execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleStepConfigurationTests.java b/execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleStepConfigurationTests.java index 85384089b..1ae302a18 100644 --- a/execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleStepConfigurationTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleStepConfigurationTests.java @@ -18,6 +18,7 @@ package org.springframework.batch.execution.step.simple; import junit.framework.TestCase; import org.springframework.batch.core.tasklet.Tasklet; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.exception.handler.DefaultExceptionHandler; /** @@ -42,8 +43,8 @@ public class SimpleStepConfigurationTests extends TestCase { */ public void testSimpleStepConfigurationTasklet() { Tasklet tasklet = new Tasklet() { - public boolean execute() throws Exception { - return false; + public ExitStatus execute() throws Exception { + return ExitStatus.FINISHED; } }; configuration = new SimpleStepConfiguration(tasklet); diff --git a/execution/src/test/java/org/springframework/batch/execution/step/simple/StepExecutorInterruptionTests.java b/execution/src/test/java/org/springframework/batch/execution/step/simple/StepExecutorInterruptionTests.java index 235c1c425..0e9fe7ed6 100644 --- a/execution/src/test/java/org/springframework/batch/execution/step/simple/StepExecutorInterruptionTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/step/simple/StepExecutorInterruptionTests.java @@ -36,6 +36,7 @@ import org.springframework.batch.execution.repository.dao.JobDao; import org.springframework.batch.execution.repository.dao.MapJobDao; import org.springframework.batch.execution.repository.dao.MapStepDao; import org.springframework.batch.execution.repository.dao.StepDao; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.policy.SimpleCompletionPolicy; import org.springframework.batch.repeat.support.RepeatTemplate; @@ -75,14 +76,14 @@ public class StepExecutorInterruptionTests extends TestCase { JobExecutionContext jobExecutionContext = new JobExecutionContext(null, new JobInstance(new Long(0))); final StepExecutionContext stepExecutionContext = new StepExecutionContext(jobExecutionContext, step); stepConfiguration.setTasklet(new Tasklet() { - public boolean execute() throws Exception { + public ExitStatus execute() throws Exception { // do something non-trivial (and not Thread.sleep()) double foo = 1; for (int i = 2; i < 250; i++) { foo = foo * i; } // always return true, so processing always continues - return foo != 1; + return new ExitStatus(foo != 1); } }); diff --git a/execution/src/test/java/org/springframework/batch/execution/tasklet/ItemProviderProcessTaskletTests.java b/execution/src/test/java/org/springframework/batch/execution/tasklet/ItemProviderProcessTaskletTests.java index 2298e4874..fd542e816 100644 --- a/execution/src/test/java/org/springframework/batch/execution/tasklet/ItemProviderProcessTaskletTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/tasklet/ItemProviderProcessTaskletTests.java @@ -100,7 +100,7 @@ public class ItemProviderProcessTaskletTests extends TestCase { items = Collections.singletonList("foo"); // call execute - assertTrue(module.execute()); + assertTrue(module.execute().isContinuable()); // verify method calls assertEquals(1, list.size()); @@ -112,7 +112,7 @@ public class ItemProviderProcessTaskletTests extends TestCase { // TEST2: data provider returns null (nothing to read) // call read - assertFalse(module.execute()); + assertFalse(module.execute().isContinuable()); } diff --git a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/init.sql b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/init.sql index 08b590ede..eb3630793 100644 --- a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/init.sql +++ b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/init.sql @@ -15,7 +15,7 @@ CREATE TABLE BATCH_JOB_EXECUTION ( START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , STATUS VARCHAR(10), - EXIT_CODE BIGINT); + EXIT_CODE VARCHAR(250)); CREATE TABLE BATCH_STEP ( ID BIGINT IDENTITY PRIMARY KEY , @@ -36,7 +36,7 @@ CREATE TABLE BATCH_STEP_EXECUTION ( COMMIT_COUNT BIGINT , TASK_COUNT BIGINT , TASK_STATISTICS VARCHAR(250), - EXIT_CODE BIGINT, + EXIT_CODE VARCHAR(250), EXIT_MESSAGE VARCHAR(250)); CREATE TABLE BATCH_STEP_EXECUTION_SEQ ( diff --git a/execution/src/test/resources/simple-container-definition.xml b/execution/src/test/resources/simple-container-definition.xml index d21a05246..96fd431aa 100644 --- a/execution/src/test/resources/simple-container-definition.xml +++ b/execution/src/test/resources/simple-container-definition.xml @@ -7,15 +7,15 @@ 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"> - + - - + + diff --git a/infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java b/infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java index f6bf3c602..d42bceeca 100644 --- a/infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java +++ b/infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java @@ -37,20 +37,27 @@ public class ExitStatus { /** * Convenient constant value representing finished processing with an error. */ - public static ExitStatus FAILED = new ExitStatus(false, -1); + public static ExitStatus FAILED = new ExitStatus(false); private final boolean continuable; - private final int exitCode; + private final String exitCode; + + private final String exitDescription; public ExitStatus(boolean continuable) { - this(continuable, 0); + this(continuable, "", ""); } - public ExitStatus(boolean continuable, int exitCode) { + public ExitStatus(boolean continuable, String exitCode) { + this(continuable, exitCode, ""); + } + + public ExitStatus(boolean continuable, String exitCode, String exitDescription){ super(); this.continuable = continuable; this.exitCode = exitCode; + this.exitDescription = exitDescription; } /** @@ -66,12 +73,21 @@ public class ExitStatus { } /** - * Getter for the exit code (defaults to 0). + * Getter for the exit code (defaults to blank). * @return the exit code. */ - public int getExitCode() { + public String getExitCode() { return exitCode; } + + /** + * Getter for the exit description (defaults to blank) + * + * @return + */ + public String getExitDescription() { + return exitDescription; + } /** * Create a new {@link ExitStatus} with a logical combination of the @@ -81,18 +97,7 @@ public class ExitStatus { * logical and of the current value and the argument provided. */ public ExitStatus and(boolean continuable) { - return and(new ExitStatus(continuable)); - } - - /** - * Create a new {@link ExitStatus} with a logical combination of the - * continuable flag and adding the other exit code. - * @param other an other {@link ExitStatus}. - * @return a new {@link ExitStatus} with {@link #isContinuable()} the - * logical and of the current value and the other's. - */ - public ExitStatus and(ExitStatus other) { - return new ExitStatus(this.continuable && other.isContinuable(), exitCode).addExitCode(other.getExitCode()); + return new ExitStatus(this.continuable && continuable); } /* @@ -100,26 +105,8 @@ public class ExitStatus { * @see java.lang.Object#toString() */ public String toString() { - return "continuable=" + continuable + ";exitCode=" + exitCode; - } - - /** - * Duplicates the existing status except that a new exit code is added as - * per the argument. If both codes (the current and the new one provided) - * are negative then the lower of the two is returned, otherwise the higher - * or the two. - * - * @param exitCode the new value of the exitCode - * @return a new {@link ExitStatus} instance - */ - public ExitStatus addExitCode(int exitCode) { - if (this.exitCode < 0 || exitCode < 0) { - exitCode = Math.min(this.exitCode, exitCode); - } - else { - exitCode = Math.max(this.exitCode, exitCode); - } - return new ExitStatus(this.continuable, exitCode); + return "continuable=" + continuable + ";exitCode=" + exitCode + + ";exitDescription=" + exitDescription; } } diff --git a/infrastructure/src/main/java/org/springframework/batch/repeat/RepeatInterceptor.java b/infrastructure/src/main/java/org/springframework/batch/repeat/RepeatInterceptor.java index 4bbfe005f..a728374d6 100644 --- a/infrastructure/src/main/java/org/springframework/batch/repeat/RepeatInterceptor.java +++ b/infrastructure/src/main/java/org/springframework/batch/repeat/RepeatInterceptor.java @@ -79,5 +79,5 @@ public interface RepeatInterceptor { * @param context the current batch context. * @return TODO */ - ExitStatus close(RepeatContext context); + void close(RepeatContext context); } diff --git a/infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/ApplicationEventPublisherRepeatInterceptor.java b/infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/ApplicationEventPublisherRepeatInterceptor.java index d8a4136fc..735a761c7 100644 --- a/infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/ApplicationEventPublisherRepeatInterceptor.java +++ b/infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/ApplicationEventPublisherRepeatInterceptor.java @@ -58,9 +58,10 @@ public class ApplicationEventPublisherRepeatInterceptor implements ApplicationEv * (non-Javadoc) * @see org.springframework.batch.repeat.RepeatInterceptor#close(org.springframework.batch.repeat.RepeatContext) */ - public ExitStatus close(RepeatContext context) { + public void close(RepeatContext context) { publish(context, "Closed repeat context with batch complete", RepeatOperationsApplicationEvent.CLOSE); - return ExitStatus.CONTINUABLE; + //TODO: why is this returning continuable? + //return ExitStatus.CONTINUABLE; } /* diff --git a/infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/RepeatInterceptorAdapter.java b/infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/RepeatInterceptorAdapter.java index fee8c70d1..ab6272bcd 100644 --- a/infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/RepeatInterceptorAdapter.java +++ b/infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/RepeatInterceptorAdapter.java @@ -28,8 +28,7 @@ public class RepeatInterceptorAdapter implements RepeatInterceptor { public void after(RepeatContext context, Object result) { } - public ExitStatus close(RepeatContext context) { - return ExitStatus.CONTINUABLE; + public void close(RepeatContext context) { } public void onError(RepeatContext context, Throwable e) { diff --git a/infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java b/infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java index 1b0ec7526..3af3bd89e 100644 --- a/infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java +++ b/infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java @@ -245,7 +245,7 @@ public class RepeatTemplate implements RepeatOperations { try { for (int i = interceptors.length; i-- > 0;) { RepeatInterceptor interceptor = interceptors[i]; - result = result.and(interceptor.close(context)); + interceptor.close(context); } } finally { diff --git a/infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java b/infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java index e97917b82..c2141950a 100644 --- a/infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java +++ b/infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java @@ -27,9 +27,9 @@ public class ExitStatusTests extends TestCase { * Test method for {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}. */ public void testExitStatusBooleanInt() { - ExitStatus status = new ExitStatus(true, 10); + ExitStatus status = new ExitStatus(true, "10"); assertTrue(status.isContinuable()); - assertEquals(10, status.getExitCode()); + assertEquals("10", status.getExitCode()); } /** @@ -38,7 +38,7 @@ public class ExitStatusTests extends TestCase { public void testExitStatusConstantsContinuable() { ExitStatus status = ExitStatus.CONTINUABLE; assertTrue(status.isContinuable()); - assertEquals(0, status.getExitCode()); + assertEquals("", status.getExitCode()); } /** @@ -47,7 +47,7 @@ public class ExitStatusTests extends TestCase { public void testExitStatusConstantsFinished() { ExitStatus status = ExitStatus.FINISHED; assertFalse(status.isContinuable()); - assertEquals(0, status.getExitCode()); + assertEquals("", status.getExitCode()); } /** @@ -62,43 +62,8 @@ public class ExitStatusTests extends TestCase { * Test method for {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. */ public void testAndExitStatus() { - assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE).isContinuable()); - assertFalse(ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED).isContinuable()); + assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE.isContinuable()).isContinuable()); + assertFalse(ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED.isContinuable()).isContinuable()); } - /** - * Test method for {@link org.springframework.batch.repeat.ExitStatus#addExitCode(int)}. - */ - public void testAddExitCode() { - ExitStatus status = ExitStatus.FINISHED.addExitCode(10); - assertEquals(10, status.getExitCode()); - assertFalse(status.isContinuable()); - } - - /** - * Test method for {@link org.springframework.batch.repeat.ExitStatus#addExitCode(int)}. - */ - public void testAddExitCodeBothNegative() { - ExitStatus status = ExitStatus.FINISHED.addExitCode(-2); - assertEquals(-2, status.getExitCode()); - assertEquals(-3, status.addExitCode(-3).getExitCode()); - } - - /** - * Test method for {@link org.springframework.batch.repeat.ExitStatus#addExitCode(int)}. - */ - public void testAddExitCodeBothPositive() { - ExitStatus status = ExitStatus.FINISHED.addExitCode(2); - assertEquals(2, status.getExitCode()); - assertEquals(3, status.addExitCode(3).getExitCode()); - } - - /** - * Test method for {@link org.springframework.batch.repeat.ExitStatus#addExitCode(int)}. - */ - public void testAddExitCodeNewNegative() { - ExitStatus status = ExitStatus.FINISHED.addExitCode(2); - assertEquals(2, status.getExitCode()); - assertEquals(-3, status.addExitCode(-3).getExitCode()); - } } diff --git a/infrastructure/src/test/java/org/springframework/batch/repeat/interceptor/RepeatInterceptorTests.java b/infrastructure/src/test/java/org/springframework/batch/repeat/interceptor/RepeatInterceptorTests.java index ef2d8a37f..7da083f38 100644 --- a/infrastructure/src/test/java/org/springframework/batch/repeat/interceptor/RepeatInterceptorTests.java +++ b/infrastructure/src/test/java/org/springframework/batch/repeat/interceptor/RepeatInterceptorTests.java @@ -149,14 +149,12 @@ public class RepeatInterceptorTests extends TestCase { RepeatTemplate template = new RepeatTemplate(); final List calls = new ArrayList(); template.setInterceptors(new RepeatInterceptor[] { new RepeatInterceptorAdapter() { - public ExitStatus close(RepeatContext context) { + public void close(RepeatContext context) { calls.add("1"); - return ExitStatus.CONTINUABLE; } }, new RepeatInterceptorAdapter() { - public ExitStatus close(RepeatContext context) { + public void close(RepeatContext context) { calls.add("2"); - return ExitStatus.CONTINUABLE; } } }); template.iterate(new RepeatCallback() { @@ -171,32 +169,6 @@ public class RepeatInterceptorTests extends TestCase { assertEquals("[2, 1]", calls.toString()); } - public void testCloseInterceptorsCanChangeExitCode() throws Exception { - RepeatTemplate template = new RepeatTemplate(); - final List calls = new ArrayList(); - template.setInterceptors(new RepeatInterceptor[] { new RepeatInterceptorAdapter() { - public ExitStatus close(RepeatContext context) { - calls.add("1"); - return ExitStatus.FINISHED.addExitCode(1); - } - }, new RepeatInterceptorAdapter() { - public ExitStatus close(RepeatContext context) { - calls.add("2"); - return ExitStatus.CONTINUABLE; - } - } }); - ExitStatus status = template.iterate(new RepeatCallback() { - public ExitStatus doInIteration(RepeatContext context) throws Exception { - count++; - return new ExitStatus(count < 2); - } - }); - // Test that only one call comes in to the callback... - assertEquals(2, count); - // ... and the interceptor is called once. - assertEquals("[2, 1]", calls.toString()); - assertEquals(1, status.getExitCode()); - } public void testOnErrorInterceptors() throws Exception { RepeatTemplate template = new RepeatTemplate(); diff --git a/samples/20070122.testStream.xmlFileStep.xml b/samples/20070122.testStream.xmlFileStep.xml index 13e91dde8..e698f4395 100644 --- a/samples/20070122.testStream.xmlFileStep.xml +++ b/samples/20070122.testStream.xmlFileStep.xml @@ -1 +1 @@ -Gladys Kravitz
Anytown, PA
3400
2003-01-07 14:16:00.0 GMTBurnham's Celestial Handbook, Vol 15.021.792Burnham's Celestial Handbook, Vol 25.019.892
John Smith
Chicago, IL
4600
2003-01-07 14:16:02.0 GMTXmlBeans in Action3.041.291JSR-1731.011.995Teach Yourself XML in 21 days1.035.491
Peter Newman
Cleveland, OH
2300
2003-01-07 14:16:35.0 GMTJava 62.012.793
\ No newline at end of file +Gladys Kravitz
Anytown, PA
3400
2003-01-07 08:16:00.0 CSTBurnham's Celestial Handbook, Vol 15.021.792Burnham's Celestial Handbook, Vol 25.019.892
John Smith
Chicago, IL
4600
2003-01-07 08:16:02.0 CSTXmlBeans in Action3.041.291JSR-1731.011.995Teach Yourself XML in 21 days1.035.491
Peter Newman
Cleveland, OH
2300
2003-01-07 08:16:35.0 CSTJava 62.012.793
\ No newline at end of file diff --git a/samples/src/main/java/org/springframework/batch/sample/module/ExceptionRestartableTasklet.java b/samples/src/main/java/org/springframework/batch/sample/module/ExceptionRestartableTasklet.java index 6496c2ac3..6fc93f50e 100644 --- a/samples/src/main/java/org/springframework/batch/sample/module/ExceptionRestartableTasklet.java +++ b/samples/src/main/java/org/springframework/batch/sample/module/ExceptionRestartableTasklet.java @@ -20,6 +20,7 @@ package org.springframework.batch.sample.module; import org.springframework.batch.core.tasklet.Tasklet; import org.springframework.batch.execution.tasklet.RestartableItemProviderTasklet; import org.springframework.batch.io.exception.BatchCriticalException; +import org.springframework.batch.repeat.ExitStatus; /** * Hacked {@link Tasklet} that throws exception on a given record number @@ -36,7 +37,7 @@ public class ExceptionRestartableTasklet extends RestartableItemProviderTasklet /* (non-Javadoc) * @see Tasklet#execute() */ - public boolean execute() throws Exception { + public ExitStatus execute() throws Exception { counter++; if (counter == throwExceptionOnRecordNumber) { diff --git a/samples/src/main/java/org/springframework/batch/sample/module/InfiniteLoopTasklet.java b/samples/src/main/java/org/springframework/batch/sample/module/InfiniteLoopTasklet.java index 772ba1c00..5d01cae6a 100644 --- a/samples/src/main/java/org/springframework/batch/sample/module/InfiniteLoopTasklet.java +++ b/samples/src/main/java/org/springframework/batch/sample/module/InfiniteLoopTasklet.java @@ -19,6 +19,7 @@ package org.springframework.batch.sample.module; import java.util.Properties; import org.springframework.batch.core.tasklet.Tasklet; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.statistics.StatisticsProvider; import org.springframework.batch.support.PropertiesConverter; @@ -41,10 +42,10 @@ public class InfiniteLoopTasklet implements Tasklet, StatisticsProvider { super(); } - public boolean execute() throws Exception { + public ExitStatus execute() throws Exception { Thread.sleep(500); count++; - return true; + return ExitStatus.CONTINUABLE; } /* (non-Javadoc) diff --git a/samples/src/main/resources/simple-container-definition.xml b/samples/src/main/resources/simple-container-definition.xml index 4643339e2..145a47147 100644 --- a/samples/src/main/resources/simple-container-definition.xml +++ b/samples/src/main/resources/simple-container-definition.xml @@ -20,14 +20,14 @@
- + - + diff --git a/samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java b/samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java index a92689b49..d88a79af9 100644 --- a/samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java +++ b/samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java @@ -17,6 +17,7 @@ package org.springframework.batch.sample; import org.springframework.batch.core.configuration.JobConfiguration; import org.springframework.batch.execution.bootstrap.JobLauncher; +import org.springframework.batch.execution.bootstrap.SynchronousJobLauncher; import org.springframework.test.AbstractDependencyInjectionSpringContextTests; /** @@ -25,7 +26,7 @@ import org.springframework.test.AbstractDependencyInjectionSpringContextTests; */ public abstract class AbstractBatchLauncherTests extends AbstractDependencyInjectionSpringContextTests { - protected JobLauncher launcher; + protected SynchronousJobLauncher launcher; private JobConfiguration jobConfiguration; /** @@ -36,7 +37,7 @@ public abstract class AbstractBatchLauncherTests extends AbstractDependencyInjec return jobConfiguration.getName(); } - public void setBatchContainerLauncher(JobLauncher launcher) { + public void setBatchContainerLauncher(SynchronousJobLauncher launcher) { this.launcher = launcher; } diff --git a/samples/src/test/java/org/springframework/batch/sample/AbstractLifecycleSpringContextTests.java b/samples/src/test/java/org/springframework/batch/sample/AbstractLifecycleSpringContextTests.java index 678ca21f3..03b248b5e 100644 --- a/samples/src/test/java/org/springframework/batch/sample/AbstractLifecycleSpringContextTests.java +++ b/samples/src/test/java/org/springframework/batch/sample/AbstractLifecycleSpringContextTests.java @@ -31,7 +31,7 @@ public abstract class AbstractLifecycleSpringContextTests extends AbstractBatchL public void testLifecycle() throws Exception { validatePreConditions(); - launcher.start(getJobName()); + launcher.run(getJobName()); launcher.stop(); validatePostConditions(); } diff --git a/samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTest.java b/samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTest.java index 349d6dfd7..d4e5feeed 100644 --- a/samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTest.java +++ b/samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTest.java @@ -40,7 +40,7 @@ public class GracefulShutdownFunctionalTest extends AbstractBatchLauncherTests { Thread jobThread = new Thread(){ public void run(){ try { - launcher.start(getJobName()); + launcher.run(getJobName()); } catch (RepeatException e) { if (!(e.getCause() instanceof InterruptedException)) { diff --git a/samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java b/samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java index 073b67d27..c32e51706 100644 --- a/samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java +++ b/samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java @@ -81,7 +81,7 @@ public class RestartFunctionalTests extends AbstractBatchLauncherTests { // load the application context and launch the job private void runJob() throws Exception, Exception { - launcher.start(getJobName()); + launcher.run(getJobName()); } }