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

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