From 5bc4040efd9b75625f0cbc1b669a199013492687 Mon Sep 17 00:00:00 2001 From: dsyer Date: Thu, 16 Jul 2009 07:13:40 +0000 Subject: [PATCH] RESOLVED - issue BATCH-1336: Add -restart and -next options to CommandLineJobRunner --- .../launch/support/CommandLineJobRunner.java | 51 +++++++++-- .../support/CommandLineJobRunnerTests.java | 85 ++++++++++++++++--- .../core/launch/support/job-with-locator.xml | 22 +++++ .../sample/AbstractBatchLauncherTests.java | 3 + 4 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/job-with-locator.xml diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/CommandLineJobRunner.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/CommandLineJobRunner.java index ce74b7cbf..d47447acb 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/CommandLineJobRunner.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/CommandLineJobRunner.java @@ -149,7 +149,10 @@ public class CommandLineJobRunner { private JobLocator jobLocator; - private SystemExiter systemExiter = new JvmSystemExiter(); + // Package private for unit test + private static SystemExiter systemExiter = new JvmSystemExiter(); + + private static String message = ""; private JobParametersConverter jobParametersConverter = new DefaultJobParametersConverter(); @@ -182,13 +185,35 @@ public class CommandLineJobRunner { this.exitCodeMapper = exitCodeMapper; } + /** + * Static setter for the {@link SystemExiter} so it can be adjusted before + * dependency injection. Typically overridden by + * {@link #setSystemExiter(SystemExiter)}. + * + * @param systemExitor + */ + public static void presetSystemExiter(SystemExiter systemExiter) { + CommandLineJobRunner.systemExiter = systemExiter; + } + + /** + * Retrieve the error message set by an instance of + * {@link CommandLineJobRunner} as it exits. Empty if the last job launched + * was successful. + * + * @return the error message + */ + public static String getErrorMessage() { + return message; + } + /** * Injection setter for the {@link SystemExiter}. * * @param systemExitor */ - public void setSystemExiter(SystemExiter systemExitor) { - this.systemExiter = systemExitor; + public void setSystemExiter(SystemExiter systemExiter) { + CommandLineJobRunner.systemExiter = systemExiter; } /** @@ -231,10 +256,10 @@ public class CommandLineJobRunner { context.getAutowireCapableBeanFactory().autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); - Assert.notNull(launcher, "A JobLauncher must be provided. Please add one to the configuration."); + Assert.state(launcher != null, "A JobLauncher must be provided. Please add one to the configuration."); if (opts.contains("-restart") || opts.contains("-next")) { Assert - .notNull(jobExplorer, + .state(jobExplorer != null, "A JobExplorer must be provided for a restart or start next operation. Please add one to the configuration."); } @@ -264,7 +289,9 @@ public class CommandLineJobRunner { } catch (Throwable e) { - logger.error("Job Terminated in error:", e); + String message = "Job Terminated in error: " + e.getMessage(); + logger.error(message, e); + CommandLineJobRunner.message = message; return exitCodeMapper.intValue(ExitStatus.FAILED.getExitCode()); } finally { @@ -287,6 +314,10 @@ public class CommandLineJobRunner { JobParameters jobParameters = null; + if (lastInstances.isEmpty()) { + throw new JobParametersNotFoundException("No job instance found for job=" + jobName); + } + while (!lastInstances.isEmpty()) { for (JobInstance jobInstance : lastInstances) { @@ -308,10 +339,10 @@ public class CommandLineJobRunner { start += count; lastInstances = jobExplorer.getJobInstances(jobName, start, count); - } + } if (jobParameters == null) { - throw new JobParametersNotFoundException("No job parameters found for failed execution of job=" + jobName); + throw new JobParametersNotFoundException("No failed or stopped execution found for job=" + jobName); } return jobParameters; @@ -402,7 +433,9 @@ public class CommandLineJobRunner { } if (jobPath == null || jobName == null) { - logger.error("At least 2 arguments are required: JobPath and JobName."); + String message = "At least 2 arguments are required: JobPath and JobName."; + logger.error(message); + CommandLineJobRunner.message = message; command.exit(1); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java index b87983c83..63be98f18 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java @@ -27,7 +27,6 @@ import java.util.Set; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.ExitStatus; @@ -50,14 +49,10 @@ import org.springframework.util.ClassUtils; */ public class CommandLineJobRunnerTests { - private static final String JOB = ClassUtils.addResourcePathToPackagePath(CommandLineJobRunnerTests.class, + private String jobPath = ClassUtils.addResourcePathToPackagePath(CommandLineJobRunnerTests.class, "job-with-environment.xml"); - private static final String JOB_NAME = "test-job"; - - private String jobPath = JOB; - - private String jobName = JOB_NAME; + private String jobName = "test-job"; private String jobKey = "job.Key=myKey"; @@ -82,6 +77,14 @@ public class CommandLineJobRunnerTests { assertEquals(0, StubSystemExiter.getStatus()); } + @Test + public void testWithJobLocator() { + jobPath = ClassUtils.addResourcePathToPackagePath(CommandLineJobRunnerTests.class, "job-with-locator.xml"); + CommandLineJobRunner.main(new String[] { jobPath, jobName, jobKey }); + assertTrue("Injected JobParametersConverter not used instead of default", StubJobParametersConverter.called); + assertEquals(0, StubSystemExiter.getStatus()); + } + @Test public void testJobAlreadyRunning() throws Throwable { StubJobLauncher.throwExecutionRunningException = true; @@ -90,11 +93,13 @@ public class CommandLineJobRunnerTests { } @Test - @Ignore public void testInvalidArgs() { String[] args = new String[] {}; + CommandLineJobRunner.presetSystemExiter(new StubSystemExiter()); CommandLineJobRunner.main(args); assertEquals(1, StubSystemExiter.status); + String errorMessage = CommandLineJobRunner.getErrorMessage(); + assertTrue("Wrong error message: " + errorMessage, errorMessage.contains("Config locations must not be null")); } @Test @@ -102,6 +107,9 @@ public class CommandLineJobRunnerTests { String[] args = new String[] { jobPath, "no-such-job" }; CommandLineJobRunner.main(args); assertEquals(1, StubSystemExiter.status); + String errorMessage = CommandLineJobRunner.getErrorMessage(); + assertTrue("Wrong error message: " + errorMessage, errorMessage + .contains("No bean named 'no-such-job' is defined")); } @Test @@ -123,16 +131,59 @@ public class CommandLineJobRunnerTests { } @Test - public void testNext() throws Throwable { - String[] args = new String[] { jobPath, "-next", jobName }; + public void testRestartNotFailed() throws Throwable { + String[] args = new String[] { jobPath, "-restart", jobName }; JobParameters jobParameters = new JobParametersBuilder().addString("foo", "bar").toJobParameters(); - StubJobExplorer.jobInstances = Arrays.asList(new JobInstance(1L, jobParameters, jobName)); + StubJobExplorer.jobInstances = Arrays.asList(new JobInstance(2L, jobParameters, jobName)); + CommandLineJobRunner.main(args); + assertEquals(1, StubSystemExiter.status); + String errorMessage = CommandLineJobRunner.getErrorMessage(); + assertTrue("Wrong error message: " + errorMessage, errorMessage + .contains("No failed or stopped execution found")); + } + + @Test + public void testRestartNoParameters() throws Throwable { + String[] args = new String[] { jobPath, "-restart", jobName }; + StubJobExplorer.jobInstances = new ArrayList(); + CommandLineJobRunner.main(args); + assertEquals(1, StubSystemExiter.status); + String errorMessage = CommandLineJobRunner.getErrorMessage(); + assertTrue("Wrong error message: " + errorMessage, errorMessage.contains("No job instance found for job")); + } + + @Test + public void testNext() throws Throwable { + String[] args = new String[] { jobPath, "-next", jobName, "bar=foo" }; + JobParameters jobParameters = new JobParametersBuilder().addString("foo", "bar").addString("bar", "foo") + .toJobParameters(); + StubJobExplorer.jobInstances = Arrays.asList(new JobInstance(2L, jobParameters, jobName)); CommandLineJobRunner.main(args); assertEquals(0, StubSystemExiter.status); - jobParameters = new JobParametersBuilder().addString("foo", "spam").toJobParameters(); + jobParameters = new JobParametersBuilder().addString("foo", "spam").addString("bar", "foo").toJobParameters(); assertEquals(jobParameters, StubJobLauncher.jobParameters); } + @Test + public void testNextFirstInSequence() throws Throwable { + String[] args = new String[] { jobPath, "-next", jobName }; + StubJobExplorer.jobInstances = new ArrayList(); + CommandLineJobRunner.main(args); + assertEquals(0, StubSystemExiter.status); + JobParameters jobParameters = new JobParametersBuilder().addString("foo", "spam").toJobParameters(); + assertEquals(jobParameters, StubJobLauncher.jobParameters); + } + + @Test + public void testNextWithNoParameters() { + jobPath = ClassUtils.addResourcePathToPackagePath(CommandLineJobRunnerTests.class, "job-with-locator.xml"); + CommandLineJobRunner.main(new String[] { jobPath, "-next", "test-job2", jobKey }); + assertEquals(1, StubSystemExiter.getStatus()); + String errorMessage = CommandLineJobRunner.getErrorMessage(); + assertTrue("Wrong error message: " + errorMessage, errorMessage + .contains(" No job parameters incrementer found")); + } + @Test public void testDestroyCallback() throws Throwable { String[] args = new String[] { jobPath, jobName }; @@ -207,6 +258,9 @@ public class CommandLineJobRunnerTests { if (jobInstance.getId() == 0) { return Arrays.asList(createJobInstance(jobInstance, BatchStatus.FAILED)); } + if (jobInstance.getId() == 1) { + return null; + } return Arrays.asList(createJobInstance(jobInstance, BatchStatus.COMPLETED)); } @@ -223,7 +277,12 @@ public class CommandLineJobRunnerTests { } public List getJobInstances(String jobName, int start, int count) { - return jobInstances; + if (jobInstances == null) { + return new ArrayList(); + } + List result = jobInstances; + jobInstances = null; + return result; } public StepExecution getStepExecution(Long jobExecutionId, Long stepExecutionId) { diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/job-with-locator.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/job-with-locator.xml new file mode 100644 index 000000000..a7867ef15 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/job-with-locator.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java index 612116148..3c4eb4653 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java @@ -16,6 +16,8 @@ package org.springframework.batch.sample; +import static org.junit.Assert.assertEquals; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Assert; @@ -87,6 +89,7 @@ public abstract class AbstractBatchLauncherTests implements ApplicationContextAw public void testLaunchJob() throws Exception { jobExecution = getLauncher().run(job, jobParameters); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); } /**