001/*
002 * Copyright 2006-2007 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.batch.repeat.exception;
018
019import org.apache.commons.logging.Log;
020import org.apache.commons.logging.LogFactory;
021import org.springframework.classify.Classifier;
022import org.springframework.classify.ClassifierSupport;
023import org.springframework.batch.repeat.RepeatContext;
024import org.springframework.batch.repeat.RepeatException;
025
026/**
027 * Implementation of {@link ExceptionHandler} based on an {@link Classifier}.
028 * The classifier determines whether to log the exception or rethrow it. The
029 * keys in the classifier must be the same as the static enum in this class.
030 * 
031 * @author Dave Syer
032 * 
033 */
034public class LogOrRethrowExceptionHandler implements ExceptionHandler {
035
036        /**
037         * Logging levels for the handler.
038         * 
039         * @author Dave Syer
040         * 
041         */
042        public static enum Level {
043
044                /**
045                 * Key for {@link Classifier} signalling that the throwable should be
046                 * rethrown. If the throwable is not a RuntimeException it is wrapped in
047                 * a {@link RepeatException}.
048                 */
049                RETHROW,
050
051                /**
052                 * Key for {@link Classifier} signalling that the throwable should be
053                 * logged at debug level.
054                 */
055                DEBUG,
056
057                /**
058                 * Key for {@link Classifier} signalling that the throwable should be
059                 * logged at warn level.
060                 */
061                WARN,
062
063                /**
064                 * Key for {@link Classifier} signalling that the throwable should be
065                 * logged at error level.
066                 */
067                ERROR
068
069        }
070
071        protected final Log logger = LogFactory.getLog(LogOrRethrowExceptionHandler.class);
072
073        private Classifier<Throwable, Level> exceptionClassifier = new ClassifierSupport<Throwable, Level>(Level.RETHROW);
074
075        /**
076         * Setter for the {@link Classifier} used by this handler. The default is to
077         * map all throwable instances to {@link Level#RETHROW}.
078         * 
079         * @param exceptionClassifier the ExceptionClassifier to use
080         */
081        public void setExceptionClassifier(Classifier<Throwable, Level> exceptionClassifier) {
082                this.exceptionClassifier = exceptionClassifier;
083        }
084
085        /**
086         * Classify the throwables and decide whether to rethrow based on the
087         * result. The context is not used.
088         * 
089         * @throws Throwable thrown if {@link LogOrRethrowExceptionHandler#exceptionClassifier}
090         * is classified as {@link Level#RETHROW}.
091         * 
092         * @see ExceptionHandler#handleException(RepeatContext, Throwable)
093         */
094    @Override
095        public void handleException(RepeatContext context, Throwable throwable) throws Throwable {
096
097                Level key = exceptionClassifier.classify(throwable);
098                if (Level.ERROR.equals(key)) {
099                        logger.error("Exception encountered in batch repeat.", throwable);
100                }
101                else if (Level.WARN.equals(key)) {
102                        logger.warn("Exception encountered in batch repeat.", throwable);
103                }
104                else if (Level.DEBUG.equals(key) && logger.isDebugEnabled()) {
105                        logger.debug("Exception encountered in batch repeat.", throwable);
106                }
107                else if (Level.RETHROW.equals(key)) {
108                        throw throwable;
109                }
110
111        }
112
113}