EMMA Coverage Report (generated Fri Aug 21 15:59:46 BST 2009)
[all classes][org.springframework.batch.core.step.item]

COVERAGE SUMMARY FOR SOURCE FILE [BatchRetryTemplate.java]

nameclass, %method, %block, %line, %
BatchRetryTemplate.java100% (4/4)80%  (20/25)86%  (335/390)84%  (75.6/90)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class BatchRetryTemplate100% (1/1)64%  (9/14)77%  (120/155)74%  (25/34)
execute (RetryCallback): Object 0%   (0/1)0%   (0/5)0%   (0/1)
execute (RetryCallback, RecoveryCallback): Object 0%   (0/1)0%   (0/6)0%   (0/1)
execute (RetryCallback, RetryState): Object 0%   (0/1)0%   (0/6)0%   (0/1)
registerListener (RetryListener): void 0%   (0/1)0%   (0/9)0%   (0/3)
setBackOffPolicy (BackOffPolicy): void 0%   (0/1)0%   (0/9)0%   (0/3)
BatchRetryTemplate (): void 100% (1/1)100% (14/14)100% (3/3)
createState (List): List 100% (1/1)100% (23/23)100% (4/4)
createState (List, Classifier): List 100% (1/1)100% (24/24)100% (4/4)
execute (RetryCallback, Collection): Object 100% (1/1)100% (12/12)100% (2/2)
execute (RetryCallback, RecoveryCallback, Collection): Object 100% (1/1)100% (13/13)100% (2/2)
execute (RetryCallback, RecoveryCallback, RetryState): Object 100% (1/1)100% (7/7)100% (1/1)
setListeners (RetryListener []): void 100% (1/1)100% (9/9)100% (3/3)
setRetryContextCache (RetryContextCache): void 100% (1/1)100% (9/9)100% (3/3)
setRetryPolicy (RetryPolicy): void 100% (1/1)100% (9/9)100% (3/3)
     
class BatchRetryTemplate$InnerRetryTemplate100% (1/1)100% (7/7)89%  (164/184)87%  (36.6/42)
handleRetryExhausted (RecoveryCallback, RetryContext, RetryState): Object 100% (1/1)64%  (36/56)68%  (11.6/17)
BatchRetryTemplate$InnerRetryTemplate (): void 100% (1/1)100% (3/3)100% (1/1)
BatchRetryTemplate$InnerRetryTemplate (BatchRetryTemplate$InnerRetryTemplate)... 100% (1/1)100% (3/3)100% (1/1)
canRetry (RetryPolicy, RetryContext): boolean 100% (1/1)100% (24/24)100% (5/5)
close (RetryPolicy, RetryContext, RetryState, boolean): void 100% (1/1)100% (33/33)100% (7/7)
open (RetryPolicy, RetryState): RetryContext 100% (1/1)100% (32/32)100% (5/5)
registerThrowable (RetryPolicy, RetryState, RetryContext, Exception): void 100% (1/1)100% (33/33)100% (7/7)
     
class BatchRetryTemplate$BatchRetryContext100% (1/1)100% (2/2)100% (35/35)100% (10/10)
BatchRetryTemplate$BatchRetryContext (RetryContext, Collection): void 100% (1/1)100% (32/32)100% (9/9)
access$0 (BatchRetryTemplate$BatchRetryContext): Collection 100% (1/1)100% (3/3)100% (1/1)
     
class BatchRetryTemplate$BatchRetryState100% (1/1)100% (2/2)100% (16/16)100% (4/4)
BatchRetryTemplate$BatchRetryState (BatchRetryTemplate, Collection): void 100% (1/1)100% (13/13)100% (3/3)
access$0 (BatchRetryTemplate$BatchRetryState): Collection 100% (1/1)100% (3/3)100% (1/1)

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 
17package org.springframework.batch.core.step.item;
18 
19import java.util.ArrayList;
20import java.util.Collection;
21import java.util.Iterator;
22import java.util.List;
23 
24import org.springframework.batch.classify.Classifier;
25import org.springframework.batch.retry.ExhaustedRetryException;
26import org.springframework.batch.retry.RecoveryCallback;
27import org.springframework.batch.retry.RetryCallback;
28import org.springframework.batch.retry.RetryContext;
29import org.springframework.batch.retry.RetryListener;
30import org.springframework.batch.retry.RetryOperations;
31import org.springframework.batch.retry.RetryPolicy;
32import org.springframework.batch.retry.RetryState;
33import org.springframework.batch.retry.backoff.BackOffPolicy;
34import org.springframework.batch.retry.context.RetryContextSupport;
35import org.springframework.batch.retry.policy.RetryContextCache;
36import org.springframework.batch.retry.support.DefaultRetryState;
37import org.springframework.batch.retry.support.RetrySynchronizationManager;
38import org.springframework.batch.retry.support.RetryTemplate;
39 
40/**
41 * A special purpose retry template that deals specifically with multi-valued
42 * stateful retry. This is useful in the case where the operation to be retried
43 * operates on multiple items, and when it fails there is no way to decide which
44 * (if any) of the items was responsible. The {@link RetryState} used in the
45 * execute methods is composite, and when a failure occurs, all of the keys in
46 * the composite are "tarred with the same brush". Subsequent attempts to
47 * execute with any of the keys that have failed previously results in a new
48 * attempt and the previous state is used to check the {@link RetryPolicy}. If
49 * one of the failed items eventually succeeds then the others in the current
50 * composite for that attempt will be cleared from the context cache (as
51 * normal), but there may still be entries in the cache for the original failed
52 * items. This might mean that an item that did not cause a failure is never
53 * retried because other items in the same batch fail fatally first.
54 * 
55 * @author Dave Syer
56 * 
57 */
58public class BatchRetryTemplate implements RetryOperations {
59 
60        private class BatchRetryState extends DefaultRetryState {
61 
62                private final Collection<RetryState> keys;
63 
64                public BatchRetryState(Collection<RetryState> keys) {
65                        super(keys);
66                        this.keys = new ArrayList<RetryState>(keys);
67                }
68 
69        }
70 
71        private static class BatchRetryContext extends RetryContextSupport {
72 
73                private final Collection<RetryContext> contexts;
74 
75                public BatchRetryContext(RetryContext parent, Collection<RetryContext> contexts) {
76 
77                        super(parent);
78 
79                        this.contexts = contexts;
80                        int count = 0;
81 
82                        for (RetryContext context : contexts) {
83                                int retryCount = context.getRetryCount();
84                                if (retryCount > count) {
85                                        count = retryCount;
86                                        registerThrowable(context.getLastThrowable());
87                                }
88                        }
89 
90                }
91 
92        }
93 
94        private static class InnerRetryTemplate extends RetryTemplate {
95 
96                @Override
97                protected boolean canRetry(RetryPolicy retryPolicy, RetryContext context) {
98 
99                        BatchRetryContext batchContext = (BatchRetryContext) context;
100 
101                        for (RetryContext nextContext : batchContext.contexts) {
102                                if (!super.canRetry(retryPolicy, nextContext)) {
103                                        return false;
104                                }
105                        }
106 
107                        return true;
108 
109                }
110 
111                @Override
112                protected RetryContext open(RetryPolicy retryPolicy, RetryState state) {
113 
114                        BatchRetryState batchState = (BatchRetryState) state;
115 
116                        Collection<RetryContext> contexts = new ArrayList<RetryContext>();
117                        for (RetryState retryState : batchState.keys) {
118                                contexts.add(super.open(retryPolicy, retryState));
119                        }
120 
121                        return new BatchRetryContext(RetrySynchronizationManager.getContext(), contexts);
122 
123                }
124 
125                @Override
126                protected void registerThrowable(RetryPolicy retryPolicy, RetryState state, RetryContext context, Exception e) {
127 
128                        BatchRetryState batchState = (BatchRetryState) state;
129                        BatchRetryContext batchContext = (BatchRetryContext) context;
130 
131                        Iterator<RetryContext> contextIterator = batchContext.contexts.iterator();
132                        for (RetryState retryState : batchState.keys) {
133                                RetryContext nextContext = contextIterator.next();
134                                super.registerThrowable(retryPolicy, retryState, nextContext, e);
135                        }
136 
137                }
138 
139                @Override
140                protected void close(RetryPolicy retryPolicy, RetryContext context, RetryState state, boolean succeeded) {
141 
142                        BatchRetryState batchState = (BatchRetryState) state;
143                        BatchRetryContext batchContext = (BatchRetryContext) context;
144 
145                        Iterator<RetryContext> contextIterator = batchContext.contexts.iterator();
146                        for (RetryState retryState : batchState.keys) {
147                                RetryContext nextContext = contextIterator.next();
148                                super.close(retryPolicy, nextContext, retryState, succeeded);
149                        }
150 
151                }
152 
153                @Override
154                protected <T> T handleRetryExhausted(RecoveryCallback<T> recoveryCallback, RetryContext context,
155                                RetryState state) throws Exception {
156 
157                        BatchRetryState batchState = (BatchRetryState) state;
158                        BatchRetryContext batchContext = (BatchRetryContext) context;
159 
160                        // Accumulate exceptions to be thrown so all the keys get a crack
161                        Exception rethrowable = null;
162                        ExhaustedRetryException exhausted = null;
163 
164                        Iterator<RetryContext> contextIterator = batchContext.contexts.iterator();
165                        for (RetryState retryState : batchState.keys) {
166 
167                                RetryContext nextContext = contextIterator.next();
168 
169                                try {
170                                        super.handleRetryExhausted(null, nextContext, retryState);
171                                }
172                                catch (ExhaustedRetryException e) {
173                                        exhausted = e;
174                                }
175                                catch (Exception e) {
176                                        rethrowable = e;
177                                }
178 
179                        }
180 
181                        if (recoveryCallback != null) {
182                                return recoveryCallback.recover(context);
183                        }
184 
185                        if (exhausted != null) {
186                                throw exhausted;
187                        }
188 
189                        throw rethrowable;
190 
191                }
192 
193        }
194 
195        private final InnerRetryTemplate delegate = new InnerRetryTemplate();
196 
197        private final RetryTemplate regular = new RetryTemplate();
198 
199        public <T> T execute(RetryCallback<T> retryCallback, Collection<RetryState> states) throws ExhaustedRetryException,
200                        Exception {
201                RetryState batchState = new BatchRetryState(states);
202                return delegate.execute(retryCallback, batchState);
203        }
204 
205        public <T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback,
206                        Collection<RetryState> states) throws ExhaustedRetryException, Exception {
207                RetryState batchState = new BatchRetryState(states);
208                return delegate.execute(retryCallback, recoveryCallback, batchState);
209        }
210        
211        public final <T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback,
212                        RetryState retryState) throws Exception, ExhaustedRetryException {
213                return regular.execute(retryCallback, recoveryCallback, retryState);
214        }
215 
216        public final <T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback) throws Exception {
217                return regular.execute(retryCallback, recoveryCallback);
218        }
219 
220        public final <T> T execute(RetryCallback<T> retryCallback, RetryState retryState) throws Exception,
221                        ExhaustedRetryException {
222                return regular.execute(retryCallback, retryState);
223        }
224 
225        public final <T> T execute(RetryCallback<T> retryCallback) throws Exception {
226                return regular.execute(retryCallback);
227        }
228 
229        public static List<RetryState> createState(List<?> keys) {
230                List<RetryState> states = new ArrayList<RetryState>();
231                for (Object key : keys) {
232                        states.add(new DefaultRetryState(key));
233                }
234                return states;
235        }
236 
237        public static List<RetryState> createState(List<?> keys, Classifier<? super Throwable, Boolean> classifier) {
238                List<RetryState> states = new ArrayList<RetryState>();
239                for (Object key : keys) {
240                        states.add(new DefaultRetryState(key, classifier));
241                }
242                return states;
243        }
244 
245        public void registerListener(RetryListener listener) {
246                delegate.registerListener(listener);
247                regular.registerListener(listener);
248        }
249 
250        public void setBackOffPolicy(BackOffPolicy backOffPolicy) {
251                delegate.setBackOffPolicy(backOffPolicy);
252                regular.setBackOffPolicy(backOffPolicy);
253        }
254 
255        public void setListeners(RetryListener[] listeners) {
256                delegate.setListeners(listeners);
257                regular.setListeners(listeners);
258        }
259 
260        public void setRetryContextCache(RetryContextCache retryContextCache) {
261                delegate.setRetryContextCache(retryContextCache);
262                regular.setRetryContextCache(retryContextCache);
263        }
264 
265        public void setRetryPolicy(RetryPolicy retryPolicy) {
266                delegate.setRetryPolicy(retryPolicy);
267                regular.setRetryPolicy(retryPolicy);
268        }
269 
270}

[all classes][org.springframework.batch.core.step.item]
EMMA 2.0.5312 (C) Vladimir Roubtsov