diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java index a09fe3adf..7307797e6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java @@ -335,7 +335,7 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw exitStatus = new ExitStatus(false, JOB_INTERRUPTED, JobInterruptedException.class.getName()); } else if (ex instanceof NoSuchJobException || ex.getCause() instanceof NoSuchJobException) { - exitStatus = new ExitStatus(false, ExitCodeMapper.NO_SUCH_JOB); + exitStatus = new ExitStatus(false, ExitCodeMapper.NO_SUCH_JOB, ex.getClass().getName()); } else { StringWriter writer = new StringWriter(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java index 62fed8182..9e63e8420 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java @@ -1,10 +1,15 @@ package org.springframework.batch.core.step; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.util.ArrayList; import java.util.List; -import junit.framework.TestCase; - +import org.junit.Before; +import org.junit.Test; import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobInstance; @@ -18,7 +23,7 @@ import org.springframework.util.Assert; /** * Tests for {@link AbstractStep}. */ -public class AbstractStepTests extends TestCase { +public class AbstractStepTests { AbstractStep tested = new EventTrackingStep(); @@ -123,13 +128,15 @@ public class AbstractStepTests extends TestCase { } - protected void setUp() throws Exception { + @Before + public void setUp() throws Exception { tested.setJobRepository(repository); } /** * Typical step execution scenario. */ + @Test public void testExecute() throws Exception { tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); tested.execute(execution); @@ -155,6 +162,7 @@ public class AbstractStepTests extends TestCase { /** * Exception during business processing. */ + @Test public void testFailure() throws Exception { tested = new EventTrackingStep() { protected ExitStatus doExecute(StepExecution stepExecution) throws Exception { @@ -181,6 +189,8 @@ public class AbstractStepTests extends TestCase { assertEquals(7, events.size()); assertEquals(ExitStatus.FAILED.getExitCode(), execution.getExitStatus().getExitCode()); + String exitDescription = execution.getExitStatus().getExitDescription(); + assertTrue("Wrong message: "+exitDescription, exitDescription.contains("crash")); assertTrue("Execution context modifications made by listener should be persisted", repository.saved .containsKey("afterStep")); @@ -189,6 +199,7 @@ public class AbstractStepTests extends TestCase { /** * Exception during business processing. */ + @Test public void testStoppedStep() throws Exception { tested = new EventTrackingStep() { protected ExitStatus doExecute(StepExecution stepExecution) throws Exception { @@ -223,6 +234,7 @@ public class AbstractStepTests extends TestCase { /** * Exception during business processing. */ + @Test public void testFailureInSavingExecutionContext() throws Exception { tested = new EventTrackingStep() { protected ExitStatus doExecute(StepExecution stepExecution) throws Exception { @@ -254,6 +266,7 @@ public class AbstractStepTests extends TestCase { /** * JobRepository is a required property. */ + @Test public void testAfterPropertiesSet() throws Exception { tested.setJobRepository(null); try { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java index db9dab7c9..2902a5a95 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java @@ -39,8 +39,7 @@ public class ExitStatus implements Serializable { /** * Convenient constant value representing unfinished processing. */ - public static final ExitStatus CONTINUABLE = new ExitStatus(true, - "CONTINUABLE"); + public static final ExitStatus CONTINUABLE = new ExitStatus(true, "CONTINUABLE"); /** * Convenient constant value representing continuable state where processing @@ -81,8 +80,7 @@ public class ExitStatus implements Serializable { this(continuable, exitCode, ""); } - public ExitStatus(boolean continuable, String exitCode, - String exitDescription) { + public ExitStatus(boolean continuable, String exitCode, String exitDescription) { super(); this.continuable = continuable; this.exitCode = exitCode; @@ -121,14 +119,12 @@ public class ExitStatus implements Serializable { * Create a new {@link ExitStatus} with a logical combination of the * continuable flag. * - * @param continuable - * true if the caller thinks it is safe to continue. + * @param continuable true if the caller thinks it is safe to continue. * @return a new {@link ExitStatus} with {@link #isContinuable()} the - * logical and of the current value and the argument provided. + * logical and of the current value and the argument provided. */ public ExitStatus and(boolean continuable) { - return new ExitStatus(this.continuable && continuable, this.exitCode, - this.exitDescription); + return new ExitStatus(this.continuable && continuable, this.exitCode, this.exitDescription); } /** @@ -139,17 +135,15 @@ public class ExitStatus implements Serializable { * * If the input is null just return this. * - * @param status - * an {@link ExitStatus} to combine with this one. + * @param status an {@link ExitStatus} to combine with this one. * @return a new {@link ExitStatus} with {@link #isContinuable()} the - * logical and of the current value and the argument provided. + * logical and of the current value and the argument provided. */ public ExitStatus and(ExitStatus status) { if (status == null) { return this; } - ExitStatus result = and(status.continuable).addExitDescription( - status.exitDescription); + ExitStatus result = and(status.continuable).addExitDescription(status.exitDescription); if (result.continuable || !status.continuable) { result = result.replaceExitCode(status.exitCode); } @@ -162,8 +156,7 @@ public class ExitStatus implements Serializable { * @see java.lang.Object#toString() */ public String toString() { - return "continuable=" + continuable + ";exitCode=" + exitCode - + ";exitDescription=" + exitDescription; + return "continuable=" + continuable + ";exitCode=" + exitCode + ";exitDescription=" + exitDescription; } /** @@ -188,13 +181,12 @@ public class ExitStatus implements Serializable { } /** - * Add an exit code to an existing {@link ExitStatus}. If there is already - * a code present tit will be replaced. + * Add an exit code to an existing {@link ExitStatus}. If there is already a + * code present tit will be replaced. * - * @param code - * the code to add + * @param code the code to add * @return a new {@link ExitStatus} with the same properties but a new exit - * code. + * code. */ public ExitStatus replaceExitCode(String code) { return new ExitStatus(continuable, code, exitDescription); @@ -206,8 +198,7 @@ public class ExitStatus implements Serializable { * @return true if the exit code is "RUNNING" or "UNKNOWN" */ public boolean isRunning() { - return "RUNNING".equals(this.exitCode) - || "UNKNOWN".equals(this.exitCode); + return "RUNNING".equals(this.exitCode) || "UNKNOWN".equals(this.exitCode); } /** @@ -215,18 +206,23 @@ public class ExitStatus implements Serializable { * already a description present the two will be concatenated with a * semicolon. * - * @param description - * the description to add + * @param description the description to add * @return a new {@link ExitStatus} with the same properties but a new exit - * description + * description */ public ExitStatus addExitDescription(String description) { - if (StringUtils.hasText(exitDescription) - && StringUtils.hasText(description) - && !exitDescription.equals(description)) { - description = exitDescription + "; " + description; + StringBuffer buffer = new StringBuffer(); + boolean changed = StringUtils.hasText(description) && !exitDescription.equals(description); + if (StringUtils.hasText(exitDescription)) { + buffer.append(exitDescription); + if (changed) { + buffer.append("; "); + } } - return new ExitStatus(continuable, exitCode, description); + if (changed) { + buffer.append(description); + } + return new ExitStatus(continuable, exitCode, buffer.toString()); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java index befb46ee9..aef162b70 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java @@ -183,6 +183,11 @@ public class ExitStatusTests extends TestCase { assertEquals("Foo", status.getExitDescription()); } + public void testAddEmptyExitDescription() throws Exception { + ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo").addExitDescription(null); + assertEquals("Foo", status.getExitDescription()); + } + public void testAddExitCodeWithDescription() throws Exception { ExitStatus status = new ExitStatus(true, "BAR", "Bar").replaceExitCode("FOO"); assertEquals("FOO", status.getExitCode());