RESOLVED - issue BATCH-467: Remove ExitStatusExceptionClassifier / Rewrite SimpleExitStatusExceptionClassifier as a JobListener

Removed the interface and implementation, checked that defautl behaviour is same using unit test ItemOrientedStepTests
This commit is contained in:
dsyer
2008-03-25 09:08:14 +00:00
parent f0d7c7135e
commit 37d35f42eb
7 changed files with 90 additions and 250 deletions

View File

@@ -1,44 +0,0 @@
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.step;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.support.ExceptionClassifier;
/**
* Extension of the {@link ExceptionClassifier} that explicitly deals with
* returns an {@link ExitStatus}. This is useful for mapping from an exception
* type to an exit status with a customised code or detailed message.
*
* @author Lucas Ward
*
*/
public interface ExitStatusExceptionClassifier extends ExceptionClassifier {
public static final String FATAL_EXCEPTION = "FATAL_EXCEPTION";
public static final String JOB_INTERRUPTED = "JOB_INTERRUPTED";
/**
* Typesafe version of classify that explicitly returns an
* {@link ExitStatus} object.
*
* @param throwable
* @return ExitStatus representing the ExitCode and Message for the given
* exception.
*/
public ExitStatus classifyForExitCode(Throwable throwable);
}

View File

@@ -1,82 +0,0 @@
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.step;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.launch.support.ExitCodeMapper;
import org.springframework.batch.core.repository.NoSuchJobException;
import org.springframework.batch.repeat.ExitStatus;
/**
* <p>
* Simple implementation of {@link ExitStatusExceptionClassifier} that returns
* basic String exit codes, and defaults to the class name of the throwable for
* the message. Most users will want to write their own implementation that
* creates more specific exit codes for different exception types.
* </p>
*
* @author Lucas Ward
*
*/
public class SimpleExitStatusExceptionClassifier implements
ExitStatusExceptionClassifier {
/* (non-Javadoc)
* @see org.springframework.batch.core.executor.ExitCodeExceptionClassifier#classifyForExitCode(java.lang.Throwable)
*/
public ExitStatus classifyForExitCode(Throwable throwable) {
return (ExitStatus) classify(throwable);
}
/* (non-Javadoc)
* @see org.springframework.batch.common.ExceptionClassifier#classify(java.lang.Throwable)
*/
public Object classify(Throwable throwable) {
ExitStatus exitStatus = ExitStatus.FAILED;
if (throwable instanceof JobInterruptedException) {
exitStatus = new ExitStatus(false, JOB_INTERRUPTED,
JobInterruptedException.class.getName());
} else if( throwable instanceof NoSuchJobException ) {
exitStatus = new ExitStatus(false, ExitCodeMapper.NO_SUCH_JOB);
} else {
String message = "";
if (throwable!=null) {
StringWriter writer = new StringWriter();
throwable.printStackTrace(new PrintWriter(writer));
message = writer.toString();
}
exitStatus = new ExitStatus(false, FATAL_EXCEPTION, message);
}
return exitStatus;
}
/*
* (non-Javadoc)
*
* @see org.springframework.batch.common.ExceptionClassifier#getDefault()
*/
public Object getDefault() {
// return without message since we don't know what the exception is
return new ExitStatus(false, FATAL_EXCEPTION);
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.batch.core.step.item;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import org.apache.commons.logging.Log;
@@ -25,11 +27,11 @@ import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepListener;
import org.springframework.batch.core.UnexpectedJobExecutionException;
import org.springframework.batch.core.launch.support.ExitCodeMapper;
import org.springframework.batch.core.listener.CompositeStepListener;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.NoSuchJobException;
import org.springframework.batch.core.step.AbstractStep;
import org.springframework.batch.core.step.ExitStatusExceptionClassifier;
import org.springframework.batch.core.step.SimpleExitStatusExceptionClassifier;
import org.springframework.batch.core.step.StepExecutionSynchronizer;
import org.springframework.batch.core.step.StepExecutionSyncronizerFactory;
import org.springframework.batch.core.step.StepInterruptionPolicy;
@@ -71,12 +73,15 @@ public class ItemOrientedStep extends AbstractStep {
private static final Log logger = LogFactory.getLog(ItemOrientedStep.class);
/**
* Exit code for interrupted status.
*/
public static final String JOB_INTERRUPTED = "JOB_INTERRUPTED";
private RepeatOperations chunkOperations = new RepeatTemplate();
private RepeatOperations stepOperations = new RepeatTemplate();
private ExitStatusExceptionClassifier exceptionClassifier = new SimpleExitStatusExceptionClassifier();
// default to checking current thread for interruption.
private StepInterruptionPolicy interruptionPolicy = new ThreadStepInterruptionPolicy();
@@ -212,16 +217,6 @@ public class ItemOrientedStep extends AbstractStep {
this.interruptionPolicy = interruptionPolicy;
}
/**
* Setter for the {@link ExitStatusExceptionClassifier} that will be used to
* classify any exception that causes a job to fail.
*
* @param exceptionClassifier
*/
public void setExceptionClassifier(ExitStatusExceptionClassifier exceptionClassifier) {
this.exceptionClassifier = exceptionClassifier;
}
/**
* Mostly useful for testing, but could be used to remove dependence on
* backport concurrency utilities. Public setter for the
@@ -421,20 +416,21 @@ public class ItemOrientedStep extends AbstractStep {
}
/**
* @param stepExecution
* @param fatalException
* @param e
* @return
* @throws JobInterruptedException
* @param stepExecution the current {@link StepExecution}
* @param fatalException the {@link ExceptionHolder} containing information about failures in meta-data
* @param e the cause of teh failure
* @return an {@link ExitStatus}
*/
private ExitStatus processFailure(final StepExecution stepExecution, final ExceptionHolder fatalException,
Throwable e) throws JobInterruptedException {
ExitStatus status;
// classify exception so an exit code can be stored.
status = exceptionClassifier.classifyForExitCode(e);
Throwable e) {
// Default classification marks this as a failure and adds the exception
// type and message
ExitStatus status = getDefaultExitStatusForFailure(e);
if (!fatalException.hasException()) {
try {
// classify exception so an exit code can be stored.
status = status.and(listener.onErrorInStep(stepExecution, e));
}
catch (RuntimeException ex) {
@@ -448,6 +444,34 @@ public class ItemOrientedStep extends AbstractStep {
return status;
}
/**
* Default mapping from throwable to {@link ExitStatus}. Clients can modify
* the exit code using a {@link StepListener}.
*
* @param throwable the cause of teh failure
* @return an {@link ExitStatus}
*/
private ExitStatus getDefaultExitStatusForFailure(Throwable throwable) {
ExitStatus exitStatus;
if (throwable instanceof JobInterruptedException) {
exitStatus = new ExitStatus(false, JOB_INTERRUPTED, JobInterruptedException.class.getName());
}
else if (throwable instanceof NoSuchJobException) {
exitStatus = new ExitStatus(false, ExitCodeMapper.NO_SUCH_JOB);
}
else {
String message = "";
if (throwable != null) {
StringWriter writer = new StringWriter();
throwable.printStackTrace(new PrintWriter(writer));
message = writer.toString();
}
exitStatus = ExitStatus.FAILED.addExitDescription(message);
}
return exitStatus;
}
/**
* Execute a bunch of identical business logic operations all within a
* transaction. The transaction is programmatically started and stopped