1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.batch.core.step.factory;
18
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.Map;
23
24 import org.springframework.batch.core.SkipListener;
25 import org.springframework.batch.core.Step;
26 import org.springframework.batch.core.step.builder.FaultTolerantStepBuilder;
27 import org.springframework.batch.core.step.builder.SimpleStepBuilder;
28 import org.springframework.batch.core.step.builder.StepBuilder;
29 import org.springframework.batch.core.step.item.KeyGenerator;
30 import org.springframework.batch.core.step.skip.SkipPolicy;
31 import org.springframework.retry.RetryListener;
32 import org.springframework.retry.RetryPolicy;
33 import org.springframework.retry.backoff.BackOffPolicy;
34 import org.springframework.retry.policy.MapRetryContextCache;
35 import org.springframework.retry.policy.RetryContextCache;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class FaultTolerantStepFactoryBean<T, S> extends SimpleStepFactoryBean<T, S> {
52
53 private Map<Class<? extends Throwable>, Boolean> skippableExceptionClasses = new HashMap<Class<? extends Throwable>, Boolean>();
54
55 private Collection<Class<? extends Throwable>> noRollbackExceptionClasses = new HashSet<Class<? extends Throwable>>();
56
57 private Map<Class<? extends Throwable>, Boolean> retryableExceptionClasses = new HashMap<Class<? extends Throwable>, Boolean>();
58
59 private int cacheCapacity = 0;
60
61 private int retryLimit = 0;
62
63 private int skipLimit = 0;
64
65 private SkipPolicy skipPolicy;
66
67 private BackOffPolicy backOffPolicy;
68
69 private RetryListener[] retryListeners;
70
71 private RetryPolicy retryPolicy;
72
73 private RetryContextCache retryContextCache;
74
75 private KeyGenerator keyGenerator;
76
77 private boolean processorTransactional = true;
78
79
80
81
82
83
84
85 public void setKeyGenerator(KeyGenerator keyGenerator) {
86 this.keyGenerator = keyGenerator;
87 }
88
89
90
91
92
93
94
95 public void setRetryPolicy(RetryPolicy retryPolicy) {
96 this.retryPolicy = retryPolicy;
97 }
98
99
100
101
102
103
104
105 public void setRetryLimit(int retryLimit) {
106 this.retryLimit = retryLimit;
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 public void setCacheCapacity(int cacheCapacity) {
123 this.cacheCapacity = cacheCapacity;
124 }
125
126
127
128
129
130
131
132 public void setRetryContextCache(RetryContextCache retryContextCache) {
133 this.retryContextCache = retryContextCache;
134 }
135
136
137
138
139
140
141 public void setRetryableExceptionClasses(Map<Class<? extends Throwable>, Boolean> retryableExceptionClasses) {
142 this.retryableExceptionClasses = retryableExceptionClasses;
143 }
144
145
146
147
148
149
150 public void setBackOffPolicy(BackOffPolicy backOffPolicy) {
151 this.backOffPolicy = backOffPolicy;
152 }
153
154
155
156
157
158
159 public void setRetryListeners(RetryListener... retryListeners) {
160 this.retryListeners = retryListeners;
161 }
162
163
164
165
166
167
168
169
170 public void setSkipLimit(int skipLimit) {
171 this.skipLimit = skipLimit;
172 }
173
174
175
176
177
178
179
180
181 public void setSkipPolicy(SkipPolicy skipPolicy) {
182 this.skipPolicy = skipPolicy;
183 }
184
185
186
187
188
189
190
191
192
193
194 public void setSkippableExceptionClasses(Map<Class<? extends Throwable>, Boolean> exceptionClasses) {
195 this.skippableExceptionClasses = exceptionClasses;
196 }
197
198
199
200
201
202
203
204
205
206
207 public void setNoRollbackExceptionClasses(Collection<Class<? extends Throwable>> noRollbackExceptionClasses) {
208 this.noRollbackExceptionClasses = noRollbackExceptionClasses;
209 }
210
211
212
213
214 public void setProcessorTransactional(boolean processorTransactional) {
215 this.processorTransactional = processorTransactional;
216 }
217
218 @Override
219 protected SimpleStepBuilder<T, S> createBuilder(String name) {
220 return new FaultTolerantStepBuilder<T, S>(new StepBuilder(name));
221 }
222
223 @Override
224 protected void applyConfiguration(SimpleStepBuilder<T, S> builder) {
225
226 FaultTolerantStepBuilder<T, S> faultTolerantBuilder = (FaultTolerantStepBuilder<T, S>) builder;
227
228 if (retryContextCache == null && cacheCapacity > 0) {
229 retryContextCache = new MapRetryContextCache(cacheCapacity);
230 }
231 faultTolerantBuilder.retryContextCache(retryContextCache);
232 for (SkipListener<T, S> listener : BatchListenerFactoryHelper.<SkipListener<T, S>> getListeners(getListeners(),
233 SkipListener.class)) {
234 faultTolerantBuilder.listener(listener);
235 }
236
237 if (retryListeners != null) {
238 for (RetryListener listener : retryListeners) {
239 faultTolerantBuilder.listener(listener);
240 }
241 }
242
243 faultTolerantBuilder.skipPolicy(skipPolicy);
244 faultTolerantBuilder.skipLimit(skipLimit);
245 for (Class<? extends Throwable> type : skippableExceptionClasses.keySet()) {
246 if (skippableExceptionClasses.get(type)) {
247 faultTolerantBuilder.skip(type);
248 }
249 else {
250 faultTolerantBuilder.noSkip(type);
251 }
252 }
253
254 if (!processorTransactional) {
255 faultTolerantBuilder.processorNonTransactional();
256 }
257
258 faultTolerantBuilder.retryContextCache(retryContextCache);
259 faultTolerantBuilder.keyGenerator(keyGenerator);
260 faultTolerantBuilder.retryPolicy(retryPolicy);
261 faultTolerantBuilder.retryLimit(retryLimit);
262 faultTolerantBuilder.backOffPolicy(backOffPolicy);
263 for (Class<? extends Throwable> type : retryableExceptionClasses.keySet()) {
264 if (retryableExceptionClasses.get(type)) {
265 faultTolerantBuilder.retry(type);
266 }
267 else {
268 faultTolerantBuilder.noRetry(type);
269 }
270 }
271
272 for (Class<? extends Throwable> type : noRollbackExceptionClasses) {
273 faultTolerantBuilder.noRollback(type);
274 }
275 super.applyConfiguration(builder);
276
277 }
278
279 }