IN PROGRESS - issue BATCH-894: RFC: move ExitStatus up into Core?

Replaced infrastrucure status with local enum and moved ExitStatus into core.   TODO: maybe get rid of continuable.
This commit is contained in:
dsyer
2008-11-07 18:40:58 +00:00
parent 9ac28ef106
commit 8b2d02f5d9
107 changed files with 475 additions and 411 deletions

View File

@@ -0,0 +1,270 @@
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core;
import java.io.Serializable;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.util.StringUtils;
/**
* Value object used to carry information about the status of a
* {@link RepeatOperations}.
*
* ExitStatus is immutable and therefore thread-safe.
*
* @author Dave Syer
*
*/
public class ExitStatus implements Serializable {
/**
* Convenient constant value representing unknown state - assumed not
* continuable.
*/
public static final ExitStatus UNKNOWN = new ExitStatus(false, "UNKNOWN");
/**
* Convenient constant value representing unfinished processing.
*/
public static final ExitStatus CONTINUABLE = new ExitStatus(true, "CONTINUABLE");
/**
* Convenient constant value representing continuable state where processing
* is still taking place, so no further action is required. Used for
* asynchronous execution scenarios where the processing is happening in
* another thread or process and the caller is not required to wait for the
* result.
*/
public static final ExitStatus EXECUTING = new ExitStatus(true, "EXECUTING");
/**
* Convenient constant value representing finished processing.
*/
public static final ExitStatus FINISHED = new ExitStatus(false, "COMPLETED");
/**
* Convenient constant value representing job that did no processing (e.g.
* because it was already complete).
*/
public static final ExitStatus NOOP = new ExitStatus(false, "NOOP");
/**
* Convenient constant value representing finished processing with an error.
*/
public static final ExitStatus FAILED = new ExitStatus(false, "FAILED");
/**
* Convenient constant value representing finished processing with interrupted status.
*/
public static final ExitStatus INTERRUPTED = new ExitStatus(false, "INTERRUPTED");
private final boolean continuable;
private final String exitCode;
private final String exitDescription;
public ExitStatus(boolean continuable) {
this(continuable, "", "");
}
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;
}
/**
* Flag to signal that processing can continue. This is distinct from any
* flag that might indicate that a batch is complete, or terminated, since a
* batch might be only a small part of a larger whole, which is still not
* finished.
*
* @return true if processing can continue.
*/
public boolean isContinuable() {
return continuable;
}
/**
* Getter for the exit code (defaults to blank).
*
* @return the exit code.
*/
public String getExitCode() {
return exitCode;
}
/**
* Getter for the exit description (defaults to blank)
*/
public String getExitDescription() {
return exitDescription;
}
/**
* 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.
* @return a new {@link ExitStatus} with {@link #isContinuable()} the
* 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);
}
/**
* Create a new {@link ExitStatus} with a logical combination of the
* continuable flag, and a concatenation of the descriptions. If either
* value has a higher severity then its exit code will be used in the
* result. In the case of equal severity, the exit code is only replaced if
* the result is continuable or the input is not continuable.<br/>
* <br/>
*
* Severity is defined by the exit code:
* <ul>
* <li>Codes beginning with NOOP have severity 1</li>
* <li>Codes beginning with INTERRUPTED have severity 2</li>
* <li>Codes beginning with FAILED have severity 3</li>
* <li>Codes beginning with UNKNOWN have severity 4</li>
* </ul>
* Others have severity 0.<br/>
*
* If the input is null just return this.
*
* @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.
*/
public ExitStatus and(ExitStatus status) {
if (status == null) {
return this;
}
ExitStatus result = and(status.continuable).addExitDescription(status.exitDescription);
if (severity(status) > severity(this)) {
result = result.replaceExitCode(status.exitCode);
}
else {
if (severity(this) == severity(status) && (result.continuable || !status.continuable)) {
result = result.replaceExitCode(status.exitCode);
}
}
return result;
}
/**
* @param status
* @return
*/
private int severity(ExitStatus status) {
if (status.exitCode.startsWith(NOOP.exitCode)) {
return 0;
}
if (status.exitCode.startsWith(INTERRUPTED.exitCode)) {
return 1;
}
if (status.exitCode.startsWith(FAILED.exitCode)) {
return 2;
}
if (status.exitCode.startsWith(UNKNOWN.exitCode)) {
return 3;
}
return 0;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
public String toString() {
return String.format("continuable=%s;exitCode=%s;exitDescription=%s", continuable, exitCode, exitDescription);
}
/**
* Compare the fields one by one.
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
return toString().equals(obj.toString());
}
/**
* Compatible with the equals implementation.
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return toString().hashCode();
}
/**
* 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
* @return a new {@link ExitStatus} with the same properties but a new exit
* code.
*/
public ExitStatus replaceExitCode(String code) {
return new ExitStatus(continuable, code, exitDescription);
}
/**
* Check if this status represents a running process.
*
* @return true if the exit code is "RUNNING" or "UNKNOWN"
*/
public boolean isRunning() {
return "RUNNING".equals(this.exitCode) || "UNKNOWN".equals(this.exitCode);
}
/**
* Add an exit description to an existing {@link ExitStatus}. If there is
* already a description present the two will be concatenated with a
* semicolon.
*
* @param description the description to add
* @return a new {@link ExitStatus} with the same properties but a new exit
* description
*/
public ExitStatus addExitDescription(String description) {
StringBuffer buffer = new StringBuffer();
boolean changed = StringUtils.hasText(description) && !exitDescription.equals(description);
if (StringUtils.hasText(exitDescription)) {
buffer.append(exitDescription);
if (changed) {
buffer.append("; ");
}
}
if (changed) {
buffer.append(description);
}
return new ExitStatus(continuable, exitCode, buffer.toString());
}
}

View File

@@ -27,7 +27,6 @@ import java.util.List;
import java.util.Set;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.ExitStatus;
/**
* Batch domain object representing the execution of a job.

View File

@@ -23,7 +23,6 @@ import java.util.Date;
import java.util.List;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.util.Assert;
/**

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.batch.core;
import org.springframework.batch.repeat.ExitStatus;
/**
* Listener interface for the lifecycle of a {@link Step}.

View File

@@ -21,6 +21,7 @@ import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionException;
@@ -35,7 +36,6 @@ import org.springframework.batch.core.listener.CompositeExecutionJobListener;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.batch.core.job.flow.support;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.job.flow.support.util.PatternMatcher;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.util.StringUtils;
/**

View File

@@ -19,6 +19,7 @@ import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
@@ -26,7 +27,6 @@ import org.springframework.batch.core.configuration.JobLocator;
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
import org.springframework.batch.core.converter.JobParametersConverter;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;

View File

@@ -21,7 +21,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.core.ExitStatus;
/**
* An implementation of {@link ExitCodeMapper} that can be configured through a

View File

@@ -18,9 +18,9 @@ package org.springframework.batch.core.listener;
import java.util.Arrays;
import java.util.Iterator;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.core.Ordered;
/**

View File

@@ -18,6 +18,7 @@ package org.springframework.batch.core.listener;
import java.util.List;
import org.springframework.batch.core.ChunkListener;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.ItemProcessListener;
import org.springframework.batch.core.ItemReadListener;
import org.springframework.batch.core.ItemWriteListener;
@@ -26,7 +27,6 @@ import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.core.StepListener;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.repeat.ExitStatus;
/**
* @author Dave Syer

View File

@@ -15,9 +15,9 @@
*/
package org.springframework.batch.core.listener;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.repeat.ExitStatus;
/**
* @author Dave Syer

View File

@@ -18,12 +18,12 @@ package org.springframework.batch.core.listener;
import java.util.List;
import org.springframework.batch.core.ChunkListener;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.ItemReadListener;
import org.springframework.batch.core.ItemWriteListener;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.core.StepListener;
import org.springframework.batch.repeat.ExitStatus;
/**
* Basic no-op implementations of all {@link StepListener} implementations.

View File

@@ -10,7 +10,6 @@ import org.springframework.batch.core.partition.PartitionHandler;
import org.springframework.batch.core.partition.StepExecutionSplitter;
import org.springframework.batch.core.step.AbstractStep;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.util.Assert;
/**
@@ -70,7 +69,7 @@ public class PartitionStep extends AbstractStep {
* @see Step#execute(StepExecution)
*/
@Override
protected ExitStatus doExecute(StepExecution stepExecution) throws Exception {
protected void doExecute(StepExecution stepExecution) throws Exception {
// Wait for task completion and then aggregate the results
Collection<StepExecution> executions = partitionHandler.handle(stepExecutionSplitter, stepExecution);
@@ -79,8 +78,6 @@ public class PartitionStep extends AbstractStep {
throw new JobExecutionException("Partition handler returned an incomplete step");
}
return stepExecution.getExitStatus();
}
}

View File

@@ -3,8 +3,8 @@ package org.springframework.batch.core.partition.support;
import java.util.Collection;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.util.Assert;
/**

View File

@@ -8,11 +8,11 @@ import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.partition.PartitionHandler;
import org.springframework.batch.core.partition.StepExecutionSplitter;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;

View File

@@ -10,9 +10,9 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.OptimisticLockingFailureException;

View File

@@ -8,9 +8,9 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;

View File

@@ -21,8 +21,8 @@ import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
import org.springframework.batch.repeat.CompletionPolicy;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.util.Assert;
@@ -74,10 +74,9 @@ public class StepExecutionSimpleCompletionPolicy extends StepExecutionListenerSu
* @param result
* @return true if the commit interval has been reached or the result
* indicates completion
* @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext,
* org.springframework.batch.repeat.ExitStatus)
* @see CompletionPolicy#isComplete(RepeatContext, RepeatStatus)
*/
public boolean isComplete(RepeatContext context, ExitStatus result) {
public boolean isComplete(RepeatContext context, RepeatStatus result) {
Assert.state(delegate != null, "The delegate resource has not been initialised. "
+ "Remember to register this object as a StepListener.");
return delegate.isComplete(context, result);

View File

@@ -18,11 +18,12 @@ package org.springframework.batch.core.scope;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatCallback;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatStatus;
/**
* Convenient base class for clients who need to do something in a repeat
@@ -52,7 +53,7 @@ public abstract class StepContextRepeatCallback implements RepeatCallback {
*
* @see RepeatCallback#doInIteration(RepeatContext)
*/
public ExitStatus doInIteration(RepeatContext context) throws Exception {
public RepeatStatus doInIteration(RepeatContext context) throws Exception {
ChunkContext chunkContext = attributeQueue.poll();
if (chunkContext == null) {
@@ -64,7 +65,9 @@ public abstract class StepContextRepeatCallback implements RepeatCallback {
// otherwise step-scoped beans will be re-initialised for each chunk.
StepSynchronizationManager.register(stepContext);
try {
return doInStepContext(context, stepContext);
ExitStatus exitStatus = doInStepContext(context, stepContext);
stepContext.getStepExecution().setExitStatus(exitStatus);
return RepeatStatus.continueIf(exitStatus.isContinuable());
}
finally {
// Still some stuff to do with the data in this chunk,

View File

@@ -22,6 +22,7 @@ import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
@@ -34,7 +35,6 @@ import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.scope.StepContext;
import org.springframework.batch.core.scope.StepSynchronizationManager;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@@ -47,12 +47,13 @@ import org.springframework.util.Assert;
* @author Ben Hale
* @author Robert Kasanicky
*/
public abstract class AbstractStep implements Step, InitializingBean, BeanNameAware {
public abstract class AbstractStep implements Step, InitializingBean,
BeanNameAware {
/**
* Exit code for interrupted status.
*/
public static final String JOB_INTERRUPTED = "JOB_INTERRUPTED";
public static final String JOB_INTERRUPTED = "INTERRUPTED";
private static final Log logger = LogFactory.getLog(AbstractStep.class);
@@ -113,7 +114,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
/**
* Public setter for the startLimit.
*
* @param startLimit the startLimit to set
* @param startLimit
* the startLimit to set
*/
public void setStartLimit(int startLimit) {
this.startLimit = startLimit;
@@ -127,7 +129,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
* Public setter for flag that determines whether the step should start
* again if it is already complete. Defaults to false.
*
* @param allowStartIfComplete the value of the flag to set
* @param allowStartIfComplete
* the value of the flag to set
*/
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
this.allowStartIfComplete = allowStartIfComplete;
@@ -143,21 +146,23 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
}
/**
* Extension point for subclasses to execute business logic.
* Extension point for subclasses to execute business logic. Subclasses
* should set the {@link ExitStatus} on the {@link StepExecution} before
* returning.
*
* @param stepExecution the current step context
* @return {@link ExitStatus} to show whether the step is finished
* processing.
* @param stepExecution
* the current step context
* @throws Exception
*/
protected abstract ExitStatus doExecute(StepExecution stepExecution) throws Exception;
protected abstract void doExecute(StepExecution stepExecution) throws Exception;
/**
* Extension point for subclasses to provide callbacks to their
* collaborators at the beginning of a step, to open or acquire resources.
* Does nothing by default.
*
* @param ctx the {@link ExecutionContext} to use
* @param ctx
* the {@link ExecutionContext} to use
* @throws Exception
*/
protected void open(ExecutionContext ctx) throws Exception {
@@ -166,9 +171,10 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
/**
* Extension point for subclasses to provide callbacks to their
* collaborators at the end of a step (right at the end of the finally
* block), to close or release resources. Does nothing by default.
* block), to close or release resources. Does nothing by default.
*
* @param ctx the {@link ExecutionContext} to use
* @param ctx
* the {@link ExecutionContext} to use
* @throws Exception
*/
protected void close(ExecutionContext ctx) throws Exception {
@@ -177,10 +183,11 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
/**
* Template method for step execution logic - calls abstract methods for
* resource initialization ({@link #open(ExecutionContext)}), execution
* logic ({@link #doExecute(StepExecution)}) and resource closing ({@link #close(ExecutionContext)}).
* logic ({@link #doExecute(StepExecution)}) and resource closing (
* {@link #close(ExecutionContext)}).
*/
public final void execute(StepExecution stepExecution) throws JobInterruptedException,
UnexpectedJobExecutionException {
public final void execute(StepExecution stepExecution)
throws JobInterruptedException, UnexpectedJobExecutionException {
stepExecution.setStartTime(new Date());
stepExecution.setStatus(BatchStatus.STARTED);
getJobRepository().update(stepExecution);
@@ -195,7 +202,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
getCompositeListener().beforeStep(stepExecution);
open(stepExecution.getExecutionContext());
exitStatus = doExecute(stepExecution);
doExecute(stepExecution);
exitStatus = stepExecution.getExitStatus();
// Check if someone is trying to stop us
if (stepExecution.isTerminateOnly()) {
@@ -208,66 +216,68 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
try {
getJobRepository().update(stepExecution);
getJobRepository().updateExecutionContext(stepExecution);
}
catch (Exception e) {
} catch (Exception e) {
commitException = e;
exitStatus = exitStatus.and(ExitStatus.UNKNOWN);
}
}
catch (Throwable e) {
} catch (Throwable e) {
logger.error("Encountered an error executing the step: " + e.getClass() + ": " + e.getMessage(), e);
logger.error("Encountered an error executing the step: "
+ e.getClass() + ": " + e.getMessage(), e);
stepExecution.setStatus(determineBatchStatus(e));
exitStatus = getDefaultExitStatusForFailure(e);
stepExecution.addFailureException(e);
try {
getJobRepository().updateExecutionContext(stepExecution);
}
catch (Exception ex) {
logger.error("Encountered an error on listener error callback.", ex);
} catch (Exception ex) {
logger.error(
"Encountered an error on listener error callback.", ex);
stepExecution.addFailureException(ex);
}
}
finally {
} finally {
try {
exitStatus = exitStatus.and(getCompositeListener().afterStep(stepExecution));
}
catch (Exception e){
exitStatus = exitStatus.and(getCompositeListener().afterStep(
stepExecution));
} catch (Exception e) {
logger.error("Exception in afterStep callback", e);
}
stepExecution.setExitStatus(exitStatus);
stepExecution.setEndTime(new Date());
try {
getJobRepository().update(stepExecution);
}
catch (Exception e) {
} catch (Exception e) {
if (commitException == null) {
commitException = e;
}
else {
logger.error("Exception while updating step execution after commit exception", e);
} else {
logger
.error(
"Exception while updating step execution after commit exception",
e);
}
}
try {
close(stepExecution.getExecutionContext());
}
catch (Exception e) {
logger.error("Exception while closing step execution resources", e);
} catch (Exception e) {
logger.error(
"Exception while closing step execution resources", e);
stepExecution.addFailureException(e);
}
StepSynchronizationManager.release();
if (commitException != null) {
stepExecution.setStatus(BatchStatus.UNKNOWN);
logger.error("Encountered an error saving batch meta data."
+ "This job is now in an unknown state and should not be restarted.", commitException);
logger
.error(
"Encountered an error saving batch meta data."
+ "This job is now in an unknown state and should not be restarted.",
commitException);
stepExecution.addFailureException(commitException);
}
}
@@ -279,11 +289,10 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
private static BatchStatus determineBatchStatus(Throwable e) {
if (e instanceof FatalException) {
return BatchStatus.UNKNOWN;
}
else if (e instanceof JobInterruptedException || e.getCause() instanceof JobInterruptedException) {
} else if (e instanceof JobInterruptedException
|| e.getCause() instanceof JobInterruptedException) {
return BatchStatus.STOPPED;
}
else {
} else {
return BatchStatus.FAILED;
}
}
@@ -292,7 +301,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
* Register a step listener for callbacks at the appropriate stages in a
* step execution.
*
* @param listener a {@link StepExecutionListener}
* @param listener
* a {@link StepExecutionListener}
*/
public void registerStepExecutionListener(StepExecutionListener listener) {
this.listener.register(listener);
@@ -301,7 +311,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
/**
* Register each of the objects as listeners.
*
* @param listeners an array of listener objects of known types.
* @param listeners
* an array of listener objects of known types.
*/
public void setStepExecutionListeners(StepExecutionListener[] listeners) {
for (int i = 0; i < listeners.length; i++) {
@@ -319,7 +330,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
/**
* Public setter for {@link JobRepository}.
*
* @param jobRepository is a mandatory dependence (no default).
* @param jobRepository
* is a mandatory dependence (no default).
*/
public void setJobRepository(JobRepository jobRepository) {
this.jobRepository = jobRepository;
@@ -333,18 +345,21 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
* Default mapping from throwable to {@link ExitStatus}. Clients can modify
* the exit code using a {@link StepExecutionListener}.
*
* @param ex the cause of the failure
* @param ex
* the cause of the failure
* @return an {@link ExitStatus}
*/
private ExitStatus getDefaultExitStatusForFailure(Throwable ex) {
ExitStatus exitStatus;
if (ex instanceof JobInterruptedException || ex.getCause() instanceof JobInterruptedException) {
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, ex.getClass().getName());
}
else {
if (ex instanceof JobInterruptedException
|| ex.getCause() instanceof JobInterruptedException) {
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, ex
.getClass().getName());
} else {
StringWriter writer = new StringWriter();
ex.printStackTrace(new PrintWriter(writer));
String message = writer.toString();

View File

@@ -16,10 +16,10 @@
package org.springframework.batch.core.step;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
import org.springframework.batch.item.NoWorkFoundException;
import org.springframework.batch.repeat.ExitStatus;
/**
* Fails the step if no items have been processed ( item count is 0).

View File

@@ -19,16 +19,17 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.step.skip.ItemSkipPolicy;
import org.springframework.batch.core.step.skip.NonSkippableReadException;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatCallback;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.batch.retry.RetryOperations;
import org.springframework.batch.support.Classifier;
import org.springframework.core.AttributeAccessor;
@@ -84,18 +85,20 @@ public class FaultTolerantChunkOrientedTasklet<I, O> extends AbstractFaultTolera
if (inputs.isEmpty() && outputs.isEmpty()) {
result = getRepeatOperations().iterate(new RepeatCallback() {
public ExitStatus doInIteration(final RepeatContext context) throws Exception {
RepeatStatus continuable = getRepeatOperations().iterate(new RepeatCallback() {
public RepeatStatus doInIteration(final RepeatContext context) throws Exception {
I item = read(contribution, skippedReads);
if (item == null) {
return ExitStatus.FINISHED;
return RepeatStatus.FINISHED;
}
inputs.add(item);
contribution.incrementReadCount();
return ExitStatus.CONTINUABLE;
return RepeatStatus.CONTINUABLE;
}
});
result = continuable.isContinuable() ? ExitStatus.CONTINUABLE : ExitStatus.FINISHED;
}

View File

@@ -6,16 +6,17 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.step.skip.ItemSkipPolicy;
import org.springframework.batch.core.step.skip.SkipListenerFailedException;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatCallback;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.batch.retry.RetryOperations;
import org.springframework.batch.support.Classifier;
import org.springframework.core.AttributeAccessor;
@@ -56,19 +57,20 @@ public class NonbufferingFaultTolerantChunkOrientedTasklet<I, O> extends
final List<I> inputs = new ArrayList<I>();
final List<Exception> skippedReads = getBufferedList(attributes, SKIPPED_READS_KEY);
result = getRepeatOperations().iterate(new RepeatCallback() {
public ExitStatus doInIteration(final RepeatContext context) throws Exception {
RepeatStatus continuable = getRepeatOperations().iterate(new RepeatCallback() {
public RepeatStatus doInIteration(final RepeatContext context) throws Exception {
I item = read(contribution, skippedReads);
if (item == null) {
return ExitStatus.FINISHED;
return RepeatStatus.FINISHED;
}
inputs.add(item);
contribution.incrementReadCount();
return ExitStatus.CONTINUABLE;
return RepeatStatus.CONTINUABLE;
}
});
result = continuable.isContinuable() ? ExitStatus.CONTINUABLE : ExitStatus.FINISHED;
// filter inputs marked for skipping
final Map<I, Exception> skippedInputs = getBufferedSkips(attributes, SKIPPED_INPUTS_KEY);

View File

@@ -3,15 +3,16 @@ package org.springframework.batch.core.step.item;
import java.util.ArrayList;
import java.util.List;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatCallback;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.core.AttributeAccessor;
/**
@@ -40,20 +41,22 @@ public class SimpleChunkOrientedTasklet<I, O> extends AbstractItemOrientedTaskle
ExitStatus result = ExitStatus.CONTINUABLE;
final List<I> inputs = new ArrayList<I>();
result = repeatOperations.iterate(new RepeatCallback() {
RepeatStatus continuable = repeatOperations.iterate(new RepeatCallback() {
public ExitStatus doInIteration(final RepeatContext context) throws Exception {
public RepeatStatus doInIteration(final RepeatContext context) throws Exception {
I item = doRead();
if (item == null) {
return ExitStatus.FINISHED;
return RepeatStatus.FINISHED;
}
inputs.add(item);
contribution.incrementReadCount();
return ExitStatus.CONTINUABLE;
return RepeatStatus.CONTINUABLE;
}
});
result = continuable.isContinuable() ? ExitStatus.CONTINUABLE : ExitStatus.FINISHED;
// If there is no input we don't have to do anything more
if (inputs.isEmpty()) {
return result;

View File

@@ -17,8 +17,8 @@ package org.springframework.batch.core.step.tasklet;
import java.util.concurrent.Callable;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.AttributeAccessor;
import org.springframework.util.Assert;

View File

@@ -2,11 +2,11 @@ package org.springframework.batch.core.step.tasklet;
import java.util.Map;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.util.Assert;
/**
* Maps exit codes to {@link org.springframework.batch.repeat.ExitStatus}
* Maps exit codes to {@link org.springframework.batch.core.ExitStatus}
* according to injected map. The injected map is required to contain a value
* for 'else' key, this value will be returned if the injected map
* does not contain value for the exit code returned by the system process.
@@ -30,7 +30,7 @@ public class ConfigurableSystemProcessExitCodeMapper implements SystemProcessExi
/**
* @param mappings <code>Integer</code> exit code keys to
* {@link org.springframework.batch.repeat.ExitStatus} values.
* {@link org.springframework.batch.core.ExitStatus} values.
*/
public void setMappings(Map<Object, ExitStatus> mappings) {
Assert.notNull(mappings.get(ELSE_KEY));

View File

@@ -15,9 +15,9 @@
*/
package org.springframework.batch.core.step.tasklet;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.item.adapter.AbstractMethodInvokingDelegator;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.core.AttributeAccessor;
/**

View File

@@ -1,6 +1,6 @@
package org.springframework.batch.core.step.tasklet;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.core.ExitStatus;
/**
* Simple {@link SystemProcessExitCodeMapper} implementation that performs following mapping:

View File

@@ -7,11 +7,11 @@ import java.util.concurrent.FutureTask;
import org.apache.commons.lang.time.StopWatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;

View File

@@ -1,7 +1,7 @@
package org.springframework.batch.core.step.tasklet;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.step.tasklet.SystemCommandTasklet;
import org.springframework.batch.repeat.ExitStatus;
/**
* Maps the exit code of a system process to ExitStatus value

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.batch.core.step.tasklet;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.core.AttributeAccessor;
/**

View File

@@ -18,6 +18,7 @@ package org.springframework.batch.core.step.tasklet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
@@ -35,7 +36,6 @@ import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.CompositeItemStream;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.batch.repeat.support.RepeatTemplate;
@@ -100,30 +100,37 @@ public class TaskletStep extends AbstractStep {
*/
public TaskletStep(String name) {
super(name);
synchronizer = new StepExecutionSynchronizerFactory().getStepExecutionSynchronizer();
synchronizer = new StepExecutionSynchronizerFactory()
.getStepExecutionSynchronizer();
}
/**
* Public setter for the {@link PlatformTransactionManager}.
*
* @param transactionManager the transaction manager to set
* @param transactionManager
* the transaction manager to set
*/
public void setTransactionManager(PlatformTransactionManager transactionManager) {
public void setTransactionManager(
PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* Public setter for the {@link TransactionAttribute}.
* @param transactionAttribute the {@link TransactionAttribute} to set
*
* @param transactionAttribute
* the {@link TransactionAttribute} to set
*/
public void setTransactionAttribute(TransactionAttribute transactionAttribute) {
public void setTransactionAttribute(
TransactionAttribute transactionAttribute) {
this.transactionAttribute = transactionAttribute;
}
/**
* Public setter for the {@link Tasklet}.
*
* @param tasklet the {@link Tasklet} to set
* @param tasklet
* the {@link Tasklet} to set
*/
public void setTasklet(Tasklet tasklet) {
this.tasklet = tasklet;
@@ -139,7 +146,8 @@ public class TaskletStep extends AbstractStep {
* This is a good way to get access to job parameters and execution context
* if the tasklet is parameterised.
*
* @param listeners an array of listener objects of known types.
* @param listeners
* an array of listener objects of known types.
*/
public void setStepExecutionListeners(StepExecutionListener[] listeners) {
for (int i = 0; i < listeners.length; i++) {
@@ -156,7 +164,8 @@ public class TaskletStep extends AbstractStep {
* which itself is a {@link ItemStream}, you need to register the delegate
* here.
*
* @param streams an array of {@link ItemStream} objects.
* @param streams
* an array of {@link ItemStream} objects.
*/
public void setStreams(ItemStream[] streams) {
for (int i = 0; i < streams.length; i++) {
@@ -179,7 +188,8 @@ public class TaskletStep extends AbstractStep {
* processing. Should be set up by the caller through a factory. Defaults to
* a plain {@link RepeatTemplate}.
*
* @param stepOperations a {@link RepeatOperations} instance.
* @param stepOperations
* a {@link RepeatOperations} instance.
*/
public void setStepOperations(RepeatOperations stepOperations) {
this.stepOperations = stepOperations;
@@ -190,7 +200,8 @@ public class TaskletStep extends AbstractStep {
* check whether an external request has been made to interrupt the job
* execution.
*
* @param interruptionPolicy a {@link StepInterruptionPolicy}
* @param interruptionPolicy
* a {@link StepInterruptionPolicy}
*/
public void setInterruptionPolicy(StepInterruptionPolicy interruptionPolicy) {
this.interruptionPolicy = interruptionPolicy;
@@ -201,7 +212,8 @@ public class TaskletStep extends AbstractStep {
* backport concurrency utilities. Public setter for the
* {@link StepExecutionSynchronizer}.
*
* @param synchronizer the {@link StepExecutionSynchronizer} to set
* @param synchronizer
* the {@link StepExecutionSynchronizer} to set
*/
public void setSynchronizer(StepExecutionSynchronizer synchronizer) {
this.synchronizer = synchronizer;
@@ -216,26 +228,29 @@ public class TaskletStep extends AbstractStep {
* the current context governing the step execution, which would normally be
* available to the caller through the step's {@link ExecutionContext}.<br/>
*
* @throws JobInterruptedException if the step or a chunk is interrupted
* @throws RuntimeException if there is an exception during a chunk
* execution
* @throws JobInterruptedException
* if the step or a chunk is interrupted
* @throws RuntimeException
* if there is an exception during a chunk execution
*
*/
@Override
protected ExitStatus doExecute(StepExecution stepExecution) throws Exception {
protected void doExecute(StepExecution stepExecution) throws Exception {
stream.update(stepExecution.getExecutionContext());
getJobRepository().updateExecutionContext(stepExecution);
return stepOperations.iterate(new StepContextRepeatCallback(stepExecution) {
stepOperations.iterate(new StepContextRepeatCallback(stepExecution) {
@Override
public ExitStatus doInStepContext(RepeatContext repeatContext, StepContext stepContext) throws Exception {
public ExitStatus doInStepContext(RepeatContext repeatContext,
StepContext stepContext) throws Exception {
StepExecution stepExecution = stepContext.getStepExecution();
ExceptionHolder fatalException = new ExceptionHolder();
StepContribution contribution = stepExecution.createStepContribution();
StepContribution contribution = stepExecution
.createStepContribution();
stepExecution.getExecutionContext().clearDirtyFlag();
// Before starting a new transaction, check for
@@ -244,7 +259,8 @@ public class TaskletStep extends AbstractStep {
ExitStatus exitStatus = ExitStatus.CONTINUABLE;
TransactionStatus transaction = transactionManager.getTransaction(transactionAttribute);
TransactionStatus transaction = transactionManager
.getTransaction(transactionAttribute);
boolean locked = false;
@@ -252,8 +268,7 @@ public class TaskletStep extends AbstractStep {
try {
exitStatus = tasklet.execute(contribution, stepContext);
}
finally {
} finally {
// Apply the contribution to the step
// even if unsuccessful
logger.debug("Applying contribution: " + contribution);
@@ -269,8 +284,7 @@ public class TaskletStep extends AbstractStep {
try {
synchronizer.lock(stepExecution);
locked = true;
}
catch (InterruptedException e) {
} catch (InterruptedException e) {
stepExecution.setStatus(BatchStatus.STOPPED);
Thread.currentThread().interrupt();
}
@@ -286,44 +300,45 @@ public class TaskletStep extends AbstractStep {
stream.update(stepExecution.getExecutionContext());
try {
getJobRepository().updateExecutionContext(stepExecution);
}
catch (Exception e) {
getJobRepository()
.updateExecutionContext(stepExecution);
} catch (Exception e) {
fatalException.setException(e);
stepExecution.setStatus(BatchStatus.UNKNOWN);
throw new FatalException("Fatal error detected during save of step execution context", e);
throw new FatalException(
"Fatal error detected during save of step execution context",
e);
}
try {
transactionManager.commit(transaction);
}
catch (Exception e) {
} catch (Exception e) {
fatalException.setException(e);
stepExecution.setStatus(BatchStatus.UNKNOWN);
logger.error("Fatal error detected during commit.");
throw new FatalException("Fatal error detected during commit", e);
throw new FatalException(
"Fatal error detected during commit", e);
}
try {
logger.debug("Saving step execution after commit: " + stepExecution);
logger.debug("Saving step execution after commit: "
+ stepExecution);
getJobRepository().update(stepExecution);
}
catch (Exception e) {
} catch (Exception e) {
fatalException.setException(e);
stepExecution.setStatus(BatchStatus.UNKNOWN);
throw new FatalException("Fatal error detected during update of step execution", e);
throw new FatalException(
"Fatal error detected during update of step execution",
e);
}
}
catch (Error e) {
} catch (Error e) {
processRollback(stepExecution, fatalException, transaction);
throw e;
}
catch (Exception e) {
} catch (Exception e) {
processRollback(stepExecution, fatalException, transaction);
throw e;
}
finally {
} finally {
// only release the lock if we acquired it
if (locked) {
synchronizer.release(stepExecution);
@@ -348,8 +363,8 @@ public class TaskletStep extends AbstractStep {
* @param fatalException
* @param transaction
*/
private void processRollback(final StepExecution stepExecution, final ExceptionHolder fatalException,
TransactionStatus transaction) {
private void processRollback(final StepExecution stepExecution,
final ExceptionHolder fatalException, TransactionStatus transaction) {
/*
* Any exception thrown within the transaction should automatically
@@ -359,8 +374,7 @@ public class TaskletStep extends AbstractStep {
try {
transactionManager.rollback(transaction);
}
catch (Exception e) {
} catch (Exception e) {
/*
* If we already failed to commit, it doesn't help to do this again
* - it's better to allow the CommitFailedException to propagate

View File

@@ -0,0 +1,256 @@
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.apache.commons.lang.SerializationUtils;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
/**
* @author Dave Syer
*
*/
public class ExitStatusTests {
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#ExitStatus(boolean, String)}
* .
*/
@Test
public void testExitStatusBooleanInt() {
ExitStatus status = new ExitStatus(true, "10");
assertTrue(status.isContinuable());
assertEquals("10", status.getExitCode());
}
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#ExitStatus(boolean, String)}
* .
*/
@Test
public void testExitStatusConstantsContinuable() {
ExitStatus status = ExitStatus.CONTINUABLE;
assertTrue(status.isContinuable());
assertEquals("CONTINUABLE", status.getExitCode());
}
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#ExitStatus(boolean, String)}
* .
*/
@Test
public void testExitStatusConstantsFinished() {
ExitStatus status = ExitStatus.FINISHED;
assertFalse(status.isContinuable());
assertEquals("COMPLETED", status.getExitCode());
}
/**
* Test equality of exit statuses.
*
* @throws Exception
*/
@Test
public void testEqualsWithSameProperties() throws Exception {
assertEquals(ExitStatus.CONTINUABLE, new ExitStatus(true, "CONTINUABLE"));
}
@Test
public void testEqualsSelf() {
ExitStatus status = new ExitStatus(true, "test");
assertEquals(status, status);
}
@Test
public void testEquals() {
assertEquals(new ExitStatus(true, "test"), new ExitStatus(true, "test"));
}
/**
* Test equality of exit statuses.
*
* @throws Exception
*/
@Test
public void testEqualsWithNull() throws Exception {
assertFalse(ExitStatus.CONTINUABLE.equals(null));
}
/**
* Test equality of exit statuses.
*
* @throws Exception
*/
@Test
public void testHashcode() throws Exception {
assertEquals(ExitStatus.CONTINUABLE.toString().hashCode(), ExitStatus.CONTINUABLE.hashCode());
}
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#and(boolean)}.
*/
@Test
public void testAndBoolean() {
assertTrue(ExitStatus.CONTINUABLE.and(true).isContinuable());
assertFalse(ExitStatus.CONTINUABLE.and(false).isContinuable());
ExitStatus status = new ExitStatus(false, "CUSTOM_CODE", "CUSTOM_DESCRIPTION");
assertTrue(status.and(true).getExitCode() == "CUSTOM_CODE");
assertTrue(status.and(true).getExitDescription() == "CUSTOM_DESCRIPTION");
}
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#and(org.springframework.batch.core.ExitStatus)}
* .
*/
@Test
public void testAndExitStatusStillContinuable() {
assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE).isContinuable());
assertFalse(ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED).isContinuable());
assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE).getExitCode().equals(
ExitStatus.CONTINUABLE.getExitCode()));
}
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#and(org.springframework.batch.core.ExitStatus)}
* .
*/
@Test
public void testAndExitStatusWhenFinishedAddedToContinuable() {
assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED).getExitCode());
}
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#and(org.springframework.batch.core.ExitStatus)}
* .
*/
@Test
public void testAndExitStatusWhenContinuableAddedToFinished() {
assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(ExitStatus.CONTINUABLE).getExitCode());
}
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#and(org.springframework.batch.core.ExitStatus)}
* .
*/
@Test
public void testAndExitStatusWhenCustomContinuableAddedToContinuable() {
assertEquals("CUSTOM", ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE.replaceExitCode("CUSTOM"))
.getExitCode());
}
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#and(org.springframework.batch.core.ExitStatus)}
* .
*/
@Test
public void testAndExitStatusFailedPlusFinished() {
assertEquals("FAILED", ExitStatus.FINISHED.and(ExitStatus.FAILED).getExitCode());
assertEquals("FAILED", ExitStatus.FAILED.and(ExitStatus.FINISHED).getExitCode());
}
/**
* Test method for
* {@link org.springframework.batch.core.ExitStatus#and(org.springframework.batch.core.ExitStatus)}
* .
*/
@Test
public void testAndExitStatusWhenCustomContinuableAddedToFinished() {
assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(
ExitStatus.CONTINUABLE.replaceExitCode("CUSTOM")).getExitCode());
}
@Test
public void testAddExitCode() throws Exception {
ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO");
assertTrue(ExitStatus.CONTINUABLE != status);
assertTrue(status.isContinuable());
assertEquals("FOO", status.getExitCode());
}
@Test
public void testAddExitCodeToExistingStatus() throws Exception {
ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO").replaceExitCode("BAR");
assertTrue(ExitStatus.CONTINUABLE != status);
assertTrue(status.isContinuable());
assertEquals("BAR", status.getExitCode());
}
@Test
public void testAddExitCodeToSameStatus() throws Exception {
ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode(ExitStatus.CONTINUABLE.getExitCode());
assertTrue(ExitStatus.CONTINUABLE != status);
assertTrue(status.isContinuable());
assertEquals(ExitStatus.CONTINUABLE.getExitCode(), status.getExitCode());
}
@Test
public void testAddExitDescription() throws Exception {
ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo");
assertTrue(ExitStatus.CONTINUABLE != status);
assertTrue(status.isContinuable());
assertEquals("Foo", status.getExitDescription());
}
@Test
public void testAddExitDescriptionToSameStatus() throws Exception {
ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo").addExitDescription("Foo");
assertTrue(ExitStatus.CONTINUABLE != status);
assertTrue(status.isContinuable());
assertEquals("Foo", status.getExitDescription());
}
@Test
public void testAddEmptyExitDescription() throws Exception {
ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo").addExitDescription(null);
assertEquals("Foo", status.getExitDescription());
}
@Test
public void testAddExitCodeWithDescription() throws Exception {
ExitStatus status = new ExitStatus(true, "BAR", "Bar").replaceExitCode("FOO");
assertEquals("FOO", status.getExitCode());
assertEquals("Bar", status.getExitDescription());
}
@Test
public void testUnkownIsRunning() throws Exception {
assertTrue(ExitStatus.UNKNOWN.isRunning());
}
@Test
public void testSerializable() throws Exception {
ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO");
byte[] bytes = SerializationUtils.serialize(status);
Object object = SerializationUtils.deserialize(bytes);
assertTrue(object instanceof ExitStatus);
ExitStatus restored = (ExitStatus) object;
assertTrue(restored.isContinuable());
assertEquals(status.getExitCode(), restored.getExitCode());
}
}

View File

@@ -22,7 +22,6 @@ import java.util.List;
import org.apache.commons.lang.SerializationUtils;
import org.junit.Test;
import org.springframework.batch.repeat.ExitStatus;
/**
* @author Dave Syer

View File

@@ -26,7 +26,6 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.ExitStatus;
/**
* @author Dave Syer

View File

@@ -1,8 +1,8 @@
package org.springframework.batch.core.configuration.xml;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.core.AttributeAccessor;
public class TestTasklet extends AbstractTestComponent implements Tasklet {

View File

@@ -35,6 +35,7 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionException;
import org.springframework.batch.core.JobExecutionListener;
@@ -57,7 +58,6 @@ import org.springframework.batch.core.repository.dao.StepExecutionDao;
import org.springframework.batch.core.repository.support.SimpleJobRepository;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.ExitStatus;
/**
* Tests for DefaultJobLifecycle. MapJobDao and MapStepExecutionDao are used

View File

@@ -26,6 +26,7 @@ import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.JobParameters;
@@ -42,7 +43,6 @@ import org.springframework.batch.core.job.flow.support.state.StepState;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
/**

View File

@@ -30,6 +30,7 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
@@ -38,7 +39,6 @@ import org.springframework.batch.core.job.JobSupport;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.core.task.TaskExecutor;
/**

View File

@@ -23,6 +23,7 @@ import java.util.Properties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
@@ -30,7 +31,6 @@ import org.springframework.batch.core.converter.DefaultJobParametersConverter;
import org.springframework.batch.core.converter.JobParametersConverter;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.util.ClassUtils;
/**

View File

@@ -21,9 +21,9 @@ import java.util.Map;
import junit.framework.TestCase;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.launch.support.ExitCodeMapper;
import org.springframework.batch.core.launch.support.SimpleJvmExitCodeMapper;
import org.springframework.batch.repeat.ExitStatus;
public class SimpleJvmExitCodeMapperTests extends TestCase {

View File

@@ -20,9 +20,9 @@ import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.repeat.ExitStatus;
/**
* @author Dave Syer

View File

@@ -23,8 +23,8 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.repeat.ExitStatus;
/**
* @author Dave Syer

View File

@@ -23,6 +23,7 @@ import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
@@ -31,7 +32,6 @@ import org.springframework.batch.core.partition.StepExecutionSplitter;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;

View File

@@ -8,9 +8,9 @@ import java.util.Collections;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.repeat.ExitStatus;
public class StepExecutionAggregatorTests {

View File

@@ -10,13 +10,13 @@ import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionException;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.partition.StepExecutionSplitter;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.core.task.TaskRejectedException;

View File

@@ -31,11 +31,11 @@ import javax.sql.DataSource;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

View File

@@ -14,11 +14,11 @@ import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.transaction.annotation.Transactional;

View File

@@ -8,7 +8,7 @@ import org.junit.Test;
import java.util.List;
import java.util.Map;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.annotation.Transactional;

View File

@@ -4,9 +4,9 @@ import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

View File

@@ -20,10 +20,11 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatStatus;
/**
* @author Dave Syer
@@ -44,7 +45,8 @@ public class StepContextRepeatCallbackTests {
return ExitStatus.NOOP;
}
};
assertEquals(ExitStatus.NOOP, callback.doInIteration(null));
assertEquals(RepeatStatus.FINISHED, callback.doInIteration(null));
assertEquals(ExitStatus.NOOP, stepExecution.getExitStatus());
}
@Test

View File

@@ -12,13 +12,13 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.util.Assert;
/**
@@ -55,10 +55,11 @@ public class AbstractStepTests {
events.add("open");
}
protected ExitStatus doExecute(StepExecution context) throws Exception {
@Override
protected void doExecute(StepExecution context) throws Exception {
assertSame(execution, context);
events.add("doExecute");
return ExitStatus.FINISHED;
context.setExitStatus(ExitStatus.FINISHED);
}
protected void close(ExecutionContext ctx) throws Exception {
@@ -139,8 +140,7 @@ public class AbstractStepTests {
public void testBeanName() throws Exception {
AbstractStep step = new AbstractStep() {
@Override
protected ExitStatus doExecute(StepExecution stepExecution) throws Exception {
return null;
protected void doExecute(StepExecution stepExecution) throws Exception {
}
};
assertNull(step.getName());
@@ -152,8 +152,7 @@ public class AbstractStepTests {
public void testName() throws Exception {
AbstractStep step = new AbstractStep() {
@Override
protected ExitStatus doExecute(StepExecution stepExecution) throws Exception {
return null;
protected void doExecute(StepExecution stepExecution) throws Exception {
}
};
assertNull(step.getName());
@@ -196,7 +195,7 @@ public class AbstractStepTests {
public void testFailure() throws Exception {
tested = new EventTrackingStep() {
@Override
protected ExitStatus doExecute(StepExecution context) throws Exception {
protected void doExecute(StepExecution context) throws Exception {
super.doExecute(context);
throw new RuntimeException("crash!");
}
@@ -234,9 +233,9 @@ public class AbstractStepTests {
public void testStoppedStep() throws Exception {
tested = new EventTrackingStep() {
@Override
protected ExitStatus doExecute(StepExecution context) throws Exception {
protected void doExecute(StepExecution context) throws Exception {
context.setTerminateOnly();
return super.doExecute(context);
super.doExecute(context);
}
};
tested.setJobRepository(repository);
@@ -257,7 +256,7 @@ public class AbstractStepTests {
assertEquals("close", events.get(i++));
assertEquals(7, events.size());
assertEquals("JOB_INTERRUPTED", execution.getExitStatus().getExitCode());
assertEquals("INTERRUPTED", execution.getExitStatus().getExitCode());
assertTrue("Execution context modifications made by listener should be persisted", repository.saved
.containsKey("afterStep"));
@@ -270,9 +269,8 @@ public class AbstractStepTests {
public void testFailureInSavingExecutionContext() throws Exception {
tested = new EventTrackingStep() {
@Override
protected ExitStatus doExecute(StepExecution context) throws Exception {
protected void doExecute(StepExecution context) throws Exception {
super.doExecute(context);
return ExitStatus.FINISHED;
}
};
repository = new JobRepositoryStub() {

View File

@@ -28,9 +28,9 @@ import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.launch.EmptyItemWriter;
import org.springframework.batch.core.step.JobRepositorySupport;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatCallback;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
/**
@@ -70,10 +70,10 @@ public class RepeatOperationsStepFactoryBeanTests extends TestCase {
factory.setStepOperations(new RepeatOperations() {
public ExitStatus iterate(RepeatCallback callback) {
public RepeatStatus iterate(RepeatCallback callback) {
list = new ArrayList<String>();
list.add("foo");
return ExitStatus.FINISHED;
return RepeatStatus.FINISHED;
}
});

View File

@@ -8,6 +8,7 @@ import static org.springframework.batch.core.BatchStatus.*;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobInterruptedException;
@@ -26,7 +27,6 @@ import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamSupport;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.core.AttributeAccessor;
import org.springframework.transaction.TransactionException;

View File

@@ -21,8 +21,8 @@ import static org.junit.Assert.fail;
import java.util.concurrent.Callable;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.step.tasklet.CallableTaskletAdapter;
import org.springframework.batch.repeat.ExitStatus;
public class CallableTaskletAdapterTests {

View File

@@ -8,8 +8,8 @@ import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.step.tasklet.ConfigurableSystemProcessExitCodeMapper;
import org.springframework.batch.repeat.ExitStatus;
/**
* Tests for {@link ConfigurableSystemProcessExitCodeMapper}

View File

@@ -3,8 +3,8 @@ package org.springframework.batch.core.step.tasklet;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.step.tasklet.SimpleSystemProcessExitCodeMapper;
import org.springframework.batch.repeat.ExitStatus;
/**
* Tests for {@link SimpleSystemProcessExitCodeMapper}.

View File

@@ -19,8 +19,8 @@ import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter;
import org.springframework.batch.repeat.ExitStatus;
/**
* @author Dave Syer

View File

@@ -10,6 +10,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobInterruptedException;
@@ -18,7 +19,6 @@ import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.step.tasklet.SystemCommandException;
import org.springframework.batch.core.step.tasklet.SystemCommandTasklet;
import org.springframework.batch.core.step.tasklet.SystemProcessExitCodeMapper;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.util.Assert;

View File

@@ -29,6 +29,7 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
@@ -54,7 +55,6 @@ import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamSupport;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.policy.DefaultResultCompletionPolicy;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.repeat.support.RepeatTemplate;