EMMA Coverage Report (generated Fri Jan 30 13:20:29 EST 2009)
[all classes][org.springframework.batch.retry.policy]

COVERAGE SUMMARY FOR SOURCE FILE [AbstractStatefulRetryPolicy.java]

nameclass, %method, %block, %line, %
AbstractStatefulRetryPolicy.java100% (1/1)100% (7/7)100% (120/120)100% (28/28)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AbstractStatefulRetryPolicy100% (1/1)100% (7/7)100% (120/120)100% (28/28)
AbstractStatefulRetryPolicy (): void 100% (1/1)100% (13/13)100% (3/3)
addRecoverableExceptionClass (Class, Set): void 100% (1/1)100% (31/31)100% (4/4)
handleRetryExhausted (RetryContext): Object 100% (1/1)100% (2/2)100% (1/1)
recoverForException (Throwable): boolean 100% (1/1)100% (39/39)100% (12/12)
setRecoverableExceptionClasses (Class []): void 100% (1/1)100% (22/22)100% (5/5)
setRetryContextCache (RetryContextCache): void 100% (1/1)100% (4/4)100% (2/2)
shouldRethrow (RetryContext): boolean 100% (1/1)100% (9/9)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.retry.policy;
18 
19import java.util.HashSet;
20import java.util.Iterator;
21import java.util.Set;
22 
23import org.springframework.batch.retry.ExhaustedRetryException;
24import org.springframework.batch.retry.RetryContext;
25import org.springframework.batch.retry.RetryPolicy;
26 
27/**
28 * Base class for stateful retry policies: those that operate in the context of
29 * a callback that is called once per retry execution (usually to enforce that
30 * it is only called once per transaction). Stateful policies need to remember
31 * the context for the operation that failed (e.g. the data item that was being
32 * processed), and decide based on its history what to do in the current
33 * context. For example: the retry operation includes receiving a message, and
34 * we need it to roll back and be re-delivered so that we can have another crack
35 * at it.
36 * 
37 * @see RetryPolicy#handleRetryExhausted(RetryContext)
38 * @see AbstractStatelessRetryPolicy
39 * 
40 * @author Dave Syer
41 * 
42 */
43public abstract class AbstractStatefulRetryPolicy implements RetryPolicy {
44 
45        private volatile Set recoverableExceptionClasses = new HashSet();
46 
47        protected RetryContextCache retryContextCache = new MapRetryContextCache();
48 
49        /**
50         * Optional setter for the retry context cache. The default value is a
51         * {@link MapRetryContextCache}.
52         * 
53         * @param retryContextCache
54         */
55        public void setRetryContextCache(RetryContextCache retryContextCache) {
56                this.retryContextCache = retryContextCache;
57        }
58 
59        /**
60         * Return null. Subclasses should provide a recovery path if possible.
61         * 
62         * @see org.springframework.batch.retry.RetryPolicy#handleRetryExhausted(org.springframework.batch.retry.RetryContext)
63         */
64        public Object handleRetryExhausted(RetryContext context) throws ExhaustedRetryException {
65                return null;
66        }
67 
68        /**
69         * For a stateful policy the default is to always rethrow. This is the
70         * cautious approach: we assume that the failed processing may have written
71         * data to a transactional resource, so we rethrow and force a rollback. Any
72         * recovery path that may be available has to be taken on the next attempt,
73         * before any processing has taken place.
74         * 
75         * @return true unless the last exception registered was recoverable.
76         */
77        public boolean shouldRethrow(RetryContext context) {
78                return !recoverForException(context.getLastThrowable());
79        }
80 
81        /**
82         * Set the recoverable exceptions. Any exception on the list, or subclasses
83         * thereof, will be recoverable. If it is encountered in a retry block it
84         * will not be rethrown. Others will be rethrown. The recovery action (if
85         * any) is left to subclasses - normally they would override
86         * {@link #handleRetryExhausted(RetryContext)}.
87         * 
88         * @param retryableExceptionClasses defaults to {@link Exception}.
89         */
90        public final void setRecoverableExceptionClasses(Class[] retryableExceptionClasses) {
91                Set temp = new HashSet();
92                for (int i = 0; i < retryableExceptionClasses.length; i++) {
93                        addRecoverableExceptionClass(retryableExceptionClasses[i], temp);
94                }
95                this.recoverableExceptionClasses = temp;
96        }
97 
98        private void addRecoverableExceptionClass(Class retryableExceptionClass, Set set) {
99                if (!Throwable.class.isAssignableFrom(retryableExceptionClass)) {
100                        throw new IllegalArgumentException("Class '" + retryableExceptionClass.getName()
101                                        + "' is not a subtype of Throwable.");
102                }
103                set.add(retryableExceptionClass);
104        }
105 
106        protected boolean recoverForException(Throwable ex) {
107 
108                // Default is false (but this shouldn't really happen in practice -
109                // maybe in tests):
110                if (ex == null) {
111                        return false;
112                }
113 
114                Class exceptionClass = ex.getClass();
115                if (recoverableExceptionClasses.contains(exceptionClass)) {
116                        return true;
117                }
118 
119                // check for subclasses
120                for (Iterator iterator = recoverableExceptionClasses.iterator(); iterator.hasNext();) {
121                        Class cls = (Class) iterator.next();
122                        if (cls.isAssignableFrom(exceptionClass)) {
123                                addRecoverableExceptionClass(exceptionClass, this.recoverableExceptionClasses);
124                                return true;
125                        }
126                }
127 
128                return false;
129        }
130 
131}

[all classes][org.springframework.batch.retry.policy]
EMMA 2.0.5312 (C) Vladimir Roubtsov