1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.batch.repeat.exception;
18
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.Map.Entry;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.springframework.classify.Classifier;
26 import org.springframework.classify.SubclassClassifier;
27 import org.springframework.batch.repeat.RepeatContext;
28 import org.springframework.batch.repeat.context.RepeatContextCounter;
29 import org.springframework.util.ObjectUtils;
30
31
32
33
34
35
36
37
38
39
40 public class RethrowOnThresholdExceptionHandler implements ExceptionHandler {
41
42 protected static final IntegerHolder ZERO = new IntegerHolder(0);
43
44 protected final Log logger = LogFactory.getLog(RethrowOnThresholdExceptionHandler.class);
45
46 private Classifier<? super Throwable, IntegerHolder> exceptionClassifier = new Classifier<Throwable, IntegerHolder>() {
47 @Override
48 public RethrowOnThresholdExceptionHandler.IntegerHolder classify(Throwable classifiable) {
49 return ZERO;
50 }
51 };
52
53 private boolean useParent = false;
54
55
56
57
58
59
60
61
62 public void setUseParent(boolean useParent) {
63 this.useParent = useParent;
64 }
65
66
67
68
69
70
71 public RethrowOnThresholdExceptionHandler() {
72 super();
73 }
74
75
76
77
78
79
80 public void setThresholds(Map<Class<? extends Throwable>, Integer> thresholds) {
81 Map<Class<? extends Throwable>, IntegerHolder> typeMap = new HashMap<Class<? extends Throwable>, IntegerHolder>();
82 for (Entry<Class<? extends Throwable>, Integer> entry : thresholds.entrySet()) {
83 typeMap.put(entry.getKey(), new IntegerHolder(entry.getValue()));
84 }
85 exceptionClassifier = new SubclassClassifier<Throwable, IntegerHolder>(typeMap, ZERO);
86 }
87
88
89
90
91
92
93
94
95
96 @Override
97 public void handleException(RepeatContext context, Throwable throwable) throws Throwable {
98
99 IntegerHolder key = exceptionClassifier.classify(throwable);
100
101 RepeatContextCounter counter = getCounter(context, key);
102 counter.increment();
103 int count = counter.getCount();
104 int threshold = key.getValue();
105 if (count > threshold) {
106 throw throwable;
107 }
108
109 }
110
111 private RepeatContextCounter getCounter(RepeatContext context, IntegerHolder key) {
112 String attribute = RethrowOnThresholdExceptionHandler.class.getName() + "." + key;
113
114 return new RepeatContextCounter(context, attribute, useParent);
115 }
116
117
118
119
120
121 private static class IntegerHolder {
122
123 private final int value;
124
125
126
127
128 public IntegerHolder(int value) {
129 this.value = value;
130 }
131
132
133
134
135
136 public int getValue() {
137 return value;
138 }
139
140
141
142
143
144
145 @Override
146 public String toString() {
147 return ObjectUtils.getIdentityHexString(this) + "." + value;
148 }
149
150 }
151
152 }