1 /*
2 * Copyright 2006-2007 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.springframework.batch.repeat.exception;
18
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import org.springframework.batch.repeat.RepeatContext;
25 import org.springframework.beans.factory.InitializingBean;
26
27 /**
28 * Simple implementation of exception handler which looks for given exception
29 * types. If one of the types is found then a counter is incremented and the
30 * limit is checked to determine if it has been exceeded and the Throwable
31 * should be re-thrown. Also allows to specify list of 'fatal' exceptions that
32 * are never subject to counting, but are immediately re-thrown. The fatal list
33 * has higher priority so the two lists needn't be exclusive.
34 *
35 * @author Dave Syer
36 * @author Robert Kasanicky
37 */
38 public class SimpleLimitExceptionHandler implements ExceptionHandler, InitializingBean {
39
40 private RethrowOnThresholdExceptionHandler delegate = new RethrowOnThresholdExceptionHandler();
41
42 private Collection<Class<? extends Throwable>> exceptionClasses = Collections
43 .<Class<? extends Throwable>> singleton(Exception.class);
44
45 private Collection<Class<? extends Throwable>> fatalExceptionClasses = Collections
46 .<Class<? extends Throwable>> singleton(Error.class);
47
48 private int limit = 0;
49
50 /**
51 * Apply the provided properties to create a delegate handler.
52 *
53 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
54 */
55 @Override
56 public void afterPropertiesSet() throws Exception {
57 if (limit <= 0) {
58 return;
59 }
60 Map<Class<? extends Throwable>, Integer> thresholds = new HashMap<Class<? extends Throwable>, Integer>();
61 for (Class<? extends Throwable> type : exceptionClasses) {
62 thresholds.put(type, limit);
63 }
64 // do the fatalExceptionClasses last so they override the others
65 for (Class<? extends Throwable> type : fatalExceptionClasses) {
66 thresholds.put(type, 0);
67 }
68 delegate.setThresholds(thresholds);
69 }
70
71 /**
72 * Flag to indicate the the exception counters should be shared between
73 * sibling contexts in a nested batch (i.e. inner loop). Default is false.
74 * Set this flag to true if you want to count exceptions for the whole
75 * (outer) loop in a typical container.
76 *
77 * @param useParent true if the parent context should be used to store the
78 * counters.
79 */
80 public void setUseParent(boolean useParent) {
81 delegate.setUseParent(useParent);
82 }
83
84 /**
85 * Convenience constructor for the {@link SimpleLimitExceptionHandler} to
86 * set the limit.
87 *
88 * @param limit the limit
89 */
90 public SimpleLimitExceptionHandler(int limit) {
91 this();
92 this.limit = limit;
93 }
94
95 /**
96 * Default constructor for the {@link SimpleLimitExceptionHandler}.
97 */
98 public SimpleLimitExceptionHandler() {
99 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 }