1
13
14 package org.springframework.retry.interceptor;
15
16 import java.util.Arrays;
17
18 import org.aopalliance.intercept.MethodInterceptor;
19 import org.aopalliance.intercept.MethodInvocation;
20
21 import org.springframework.aop.ProxyMethodInvocation;
22 import org.springframework.retry.RecoveryCallback;
23 import org.springframework.retry.RetryCallback;
24 import org.springframework.retry.RetryContext;
25 import org.springframework.retry.RetryOperations;
26 import org.springframework.retry.support.RetryTemplate;
27 import org.springframework.util.Assert;
28 import org.springframework.util.StringUtils;
29
30
46 public class RetryOperationsInterceptor implements MethodInterceptor {
47
48 private RetryOperations retryOperations = new RetryTemplate();
49
50 private MethodInvocationRecoverer<?> recoverer;
51
52 private String label;
53
54 public void setLabel(String label) {
55 this.label = label;
56 }
57
58 public void setRetryOperations(RetryOperations retryTemplate) {
59 Assert.notNull(retryTemplate, "'retryOperations' cannot be null.");
60 this.retryOperations = retryTemplate;
61 }
62
63 public void setRecoverer(MethodInvocationRecoverer<?> recoverer) {
64 this.recoverer = recoverer;
65 }
66
67 public Object invoke(final MethodInvocation invocation) throws Throwable {
68
69 String name;
70 if (StringUtils.hasText(label)) {
71 name = label;
72 } else {
73 name = invocation.getMethod().toGenericString();
74 }
75 final String label = name;
76
77 RetryCallback<Object, Throwable> retryCallback = new RetryCallback<Object, Throwable>() {
78
79 public Object doWithRetry(RetryContext context) throws Exception {
80
81 context.setAttribute(RetryContext.NAME, label);
82
83
89 if (invocation instanceof ProxyMethodInvocation) {
90 try {
91 return ((ProxyMethodInvocation) invocation).invocableClone().proceed();
92 }
93 catch (Exception e) {
94 throw e;
95 }
96 catch (Error e) {
97 throw e;
98 }
99 catch (Throwable e) {
100 throw new IllegalStateException(e);
101 }
102 }
103 else {
104 throw new IllegalStateException(
105 "MethodInvocation of the wrong type detected - this should not happen with Spring AOP, " +
106 "so please raise an issue if you see this exception");
107 }
108 }
109
110 };
111
112 if (recoverer != null) {
113 ItemRecovererCallback recoveryCallback = new ItemRecovererCallback(
114 invocation.getArguments(), recoverer);
115 return this.retryOperations.execute(retryCallback, recoveryCallback);
116 }
117
118 return this.retryOperations.execute(retryCallback);
119
120 }
121
122
126 private static final class ItemRecovererCallback implements RecoveryCallback<Object> {
127
128 private final Object[] args;
129
130 private final MethodInvocationRecoverer<?> recoverer;
131
132
135 private ItemRecovererCallback(Object[] args, MethodInvocationRecoverer<?> recoverer) {
136 this.args = Arrays.asList(args).toArray();
137 this.recoverer = recoverer;
138 }
139
140 public Object recover(RetryContext context) {
141 return recoverer.recover(args, context.getLastThrowable());
142 }
143
144 }
145
146 }
147