%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.jetspeed.util.interceptors.MethodReplayInterceptor |
|
|
1 | /* |
|
2 | * Licensed to the Apache Software Foundation (ASF) under one or more |
|
3 | * contributor license agreements. See the NOTICE file distributed with |
|
4 | * this work for additional information regarding copyright ownership. |
|
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 |
|
6 | * (the "License"); you may not use this file except in compliance with |
|
7 | * the License. You may obtain a copy of the License at |
|
8 | * |
|
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
10 | * |
|
11 | * Unless required by applicable law or agreed to in writing, software |
|
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 | * See the License for the specific language governing permissions and |
|
15 | * limitations under the License. |
|
16 | */ |
|
17 | package org.apache.jetspeed.util.interceptors; |
|
18 | ||
19 | import org.aopalliance.intercept.MethodInterceptor; |
|
20 | import org.aopalliance.intercept.MethodInvocation; |
|
21 | import org.apache.commons.logging.Log; |
|
22 | import org.apache.commons.logging.LogFactory; |
|
23 | ||
24 | /** |
|
25 | * Generic aspect that will attempt to replay a method invocation if one of a |
|
26 | * set of specified exceptions is thrown from its execution. |
|
27 | * |
|
28 | * @author a336317 |
|
29 | */ |
|
30 | 0 | public class MethodReplayInterceptor implements MethodInterceptor |
31 | { |
|
32 | ||
33 | /** Log reference */ |
|
34 | 0 | private Log log = LogFactory.getLog(MethodReplayInterceptor.class); |
35 | ||
36 | /** Serialization version identifier */ |
|
37 | private static final long serialVersionUID = -1316279974504594833L; |
|
38 | ||
39 | /** |
|
40 | * How many times we should attempt to retry the method invocation if it |
|
41 | * fails |
|
42 | */ |
|
43 | private int retryCount; |
|
44 | ||
45 | /** How long we should wait before retrying - specified in milliseconds * */ |
|
46 | private int retryInterval; |
|
47 | ||
48 | /** |
|
49 | * Object which decides whether or not a method invocation should be |
|
50 | * replayed |
|
51 | */ |
|
52 | private TransactionalMethodReplayDecisionMaker replayDecisionMaker; |
|
53 | ||
54 | /** |
|
55 | * Encloses <code>super.invoke()</code> in a try/catch block, where the |
|
56 | * catch block contains additional retry logic. |
|
57 | */ |
|
58 | public Object invoke(MethodInvocation invocation) throws Throwable |
|
59 | { |
|
60 | // TODO Make this more elegant - this logic can be simpler |
|
61 | try |
|
62 | { |
|
63 | 0 | return invocation.proceed(); |
64 | 0 | } catch (Exception exp) |
65 | { |
|
66 | ||
67 | // determine whether to retry or just throw the exception back up |
|
68 | 0 | if (!this.isReplayable(invocation, exp)) { throw exp; } |
69 | ||
70 | // TODO should this be at level WARN/ERROR? |
|
71 | 0 | if (log.isDebugEnabled()) |
72 | { |
|
73 | 0 | log |
74 | .debug("Invocation for method [" |
|
75 | + invocation.getMethod().toString() |
|
76 | + "] failed. Will attempt to replay method invocation [" |
|
77 | + retryCount + "] times with an interval of [" |
|
78 | + retryInterval + "] milliseconds"); |
|
79 | } |
|
80 | ||
81 | 0 | int retryCounter = 1; |
82 | 0 | Exception lastExp = null; |
83 | ||
84 | 0 | while ((retryCounter < retryCount)) |
85 | { |
|
86 | ||
87 | try |
|
88 | { |
|
89 | 0 | if (log.isDebugEnabled()) |
90 | { |
|
91 | 0 | log |
92 | .debug("Sleeping for [" |
|
93 | + retryInterval |
|
94 | + "] milliseconds before replaying invocation for method [" |
|
95 | + invocation.getMethod().toString() |
|
96 | + "]."); |
|
97 | } |
|
98 | 0 | Thread.sleep(this.retryInterval); |
99 | ||
100 | 0 | if (log.isDebugEnabled()) |
101 | { |
|
102 | 0 | log.debug("Attempt invocation [" + retryCounter |
103 | + "] for method [" |
|
104 | + invocation.getMethod().toString() + "]."); |
|
105 | } |
|
106 | // returning from a finally block will discard the |
|
107 | // exception |
|
108 | 0 | return invocation.proceed(); |
109 | 0 | } catch (Exception exp2) |
110 | { |
|
111 | // determine whether to retry or just throw the exception |
|
112 | // back up |
|
113 | 0 | if (!this.isReplayable(invocation, exp)) { throw exp; } |
114 | ||
115 | 0 | if (log.isDebugEnabled()) |
116 | { |
|
117 | 0 | log.debug("Attempt [" + retryCounter |
118 | + "] to replay invocation for method [" |
|
119 | + invocation.getMethod().toString() |
|
120 | + "] failed. [" + (retryCount - retryCounter) |
|
121 | + "] attempts left."); |
|
122 | } |
|
123 | ||
124 | 0 | lastExp = exp2; |
125 | 0 | retryCounter++; |
126 | 0 | } |
127 | } |
|
128 | 0 | if (log.isDebugEnabled()) |
129 | { |
|
130 | 0 | log.debug("[" + retryCounter |
131 | + "] attempts to replay invocation for method [" |
|
132 | + invocation.getMethod().toString() |
|
133 | + "] failed. Throwing exception [" |
|
134 | + lastExp.getClass().getName() + "]"); |
|
135 | } |
|
136 | 0 | throw lastExp; |
137 | } |
|
138 | ||
139 | } |
|
140 | ||
141 | public int getRetryCount() |
|
142 | { |
|
143 | 0 | return retryCount; |
144 | } |
|
145 | ||
146 | public void setRetryCount(int retryCount) |
|
147 | { |
|
148 | 0 | this.retryCount = retryCount; |
149 | 0 | } |
150 | ||
151 | public int getRetryInterval() |
|
152 | { |
|
153 | 0 | return retryInterval; |
154 | } |
|
155 | ||
156 | public void setRetryInterval(int retryInterval) |
|
157 | { |
|
158 | 0 | this.retryInterval = retryInterval; |
159 | 0 | } |
160 | ||
161 | /** |
|
162 | * Determine if we should attempt to replay the method given that the |
|
163 | * previous invocation returned the passed exception. |
|
164 | * |
|
165 | * @param exp |
|
166 | * @return True if we should replay the method. |
|
167 | */ |
|
168 | private boolean isReplayable(MethodInvocation invocation, Exception exp) |
|
169 | { |
|
170 | 0 | return replayDecisionMaker.shouldReplay(invocation, exp); |
171 | } |
|
172 | ||
173 | public void setReplayDecisionMaker( |
|
174 | TransactionalMethodReplayDecisionMaker replayDecisionMaker) |
|
175 | { |
|
176 | 0 | this.replayDecisionMaker = replayDecisionMaker; |
177 | 0 | } |
178 | ||
179 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |