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 java.util.Collection; 020import java.util.Collections; 021import java.util.HashMap; 022import java.util.Map; 023 024import org.springframework.batch.repeat.RepeatContext; 025import org.springframework.beans.factory.InitializingBean; 026 027/** 028 * Simple implementation of exception handler which looks for given exception 029 * types. If one of the types is found then a counter is incremented and the 030 * limit is checked to determine if it has been exceeded and the Throwable 031 * should be re-thrown. Also allows to specify list of 'fatal' exceptions that 032 * are never subject to counting, but are immediately re-thrown. The fatal list 033 * has higher priority so the two lists needn't be exclusive. 034 * 035 * @author Dave Syer 036 * @author Robert Kasanicky 037 */ 038public class SimpleLimitExceptionHandler implements ExceptionHandler, InitializingBean { 039 040 private RethrowOnThresholdExceptionHandler delegate = new RethrowOnThresholdExceptionHandler(); 041 042 private Collection<Class<? extends Throwable>> exceptionClasses = Collections 043 .<Class<? extends Throwable>> singleton(Exception.class); 044 045 private Collection<Class<? extends Throwable>> fatalExceptionClasses = Collections 046 .<Class<? extends Throwable>> singleton(Error.class); 047 048 private int limit = 0; 049 050 /** 051 * Apply the provided properties to create a delegate handler. 052 * 053 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() 054 */ 055 @Override 056 public void afterPropertiesSet() throws Exception { 057 if (limit <= 0) { 058 return; 059 } 060 Map<Class<? extends Throwable>, Integer> thresholds = new HashMap<Class<? extends Throwable>, Integer>(); 061 for (Class<? extends Throwable> type : exceptionClasses) { 062 thresholds.put(type, limit); 063 } 064 // do the fatalExceptionClasses last so they override the others 065 for (Class<? extends Throwable> type : fatalExceptionClasses) { 066 thresholds.put(type, 0); 067 } 068 delegate.setThresholds(thresholds); 069 } 070 071 /** 072 * Flag to indicate the the exception counters should be shared between 073 * sibling contexts in a nested batch (i.e. inner loop). Default is false. 074 * Set this flag to true if you want to count exceptions for the whole 075 * (outer) loop in a typical container. 076 * 077 * @param useParent true if the parent context should be used to store the 078 * counters. 079 */ 080 public void setUseParent(boolean useParent) { 081 delegate.setUseParent(useParent); 082 } 083 084 /** 085 * Convenience constructor for the {@link SimpleLimitExceptionHandler} to 086 * set the limit. 087 * 088 * @param limit the limit 089 */ 090 public SimpleLimitExceptionHandler(int limit) { 091 this(); 092 this.limit = limit; 093 } 094 095 /** 096 * Default constructor for the {@link SimpleLimitExceptionHandler}. 097 */ 098 public SimpleLimitExceptionHandler() { 099 super(); 100 } 101 102 /** 103 * Rethrows only if the limit is breached for this context on the exception 104 * type specified. 105 * 106 * @see #setExceptionClasses(Collection) 107 * @see #setLimit(int) 108 * 109 * @see org.springframework.batch.repeat.exception.ExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, 110 * Throwable) 111 */ 112 @Override 113 public void handleException(RepeatContext context, Throwable throwable) throws Throwable { 114 delegate.handleException(context, throwable); 115 } 116 117 /** 118 * The limit on the given exception type within a single context before it 119 * is rethrown. 120 * 121 * @param limit the limit 122 */ 123 public void setLimit(final int limit) { 124 this.limit = limit; 125 } 126 127 /** 128 * Setter for the exception classes that this handler counts. Defaults to 129 * {@link Exception}. If more exceptionClasses are specified handler uses 130 * single counter that is incremented when one of the recognized exception 131 * exceptionClasses is handled. 132 * @param classes exceptionClasses 133 */ 134 public void setExceptionClasses(Collection<Class<? extends Throwable>> classes) { 135 this.exceptionClasses = classes; 136 } 137 138 /** 139 * Setter for the exception classes that shouldn't be counted, but rethrown 140 * immediately. This list has higher priority than 141 * {@link #setExceptionClasses(Collection)}. 142 * 143 * @param fatalExceptionClasses defaults to {@link Error} 144 */ 145 public void setFatalExceptionClasses(Collection<Class<? extends Throwable>> fatalExceptionClasses) { 146 this.fatalExceptionClasses = fatalExceptionClasses; 147 } 148 149}