001
014
015 package com.liferay.portal.spring.aop;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.spring.aop.Property;
020 import com.liferay.portal.kernel.spring.aop.Retry;
021 import com.liferay.portal.service.RetryAcceptor;
022 import com.liferay.portal.util.PropsValues;
023
024 import java.lang.annotation.Annotation;
025
026 import java.util.HashMap;
027 import java.util.Map;
028
029 import org.aopalliance.intercept.MethodInvocation;
030
031
034 public class RetryAdvice extends AnnotationChainableMethodAdvice<Retry> {
035
036 @Override
037 public Retry getNullAnnotation() {
038 return _nullRetry;
039 }
040
041 @Override
042 public Object invoke(MethodInvocation methodInvocation) throws Throwable {
043 Retry retry = findAnnotation(methodInvocation);
044
045 if (retry == _nullRetry) {
046 return methodInvocation.proceed();
047 }
048
049 int retries = retry.retries();
050
051 if (retries < 0) {
052 retries = PropsValues.RETRY_ADVICE_MAX_RETRIES;
053 }
054
055 int totalRetries = retries;
056
057 if (retries >= 0) {
058 retries++;
059 }
060
061 Map<String, String> properties = new HashMap<>();
062
063 for (Property property : retry.properties()) {
064 properties.put(property.name(), property.value());
065 }
066
067 Class<? extends RetryAcceptor> clazz = retry.acceptor();
068
069 RetryAcceptor retryAcceptor = clazz.newInstance();
070
071 ServiceBeanMethodInvocation serviceBeanMethodInvocation =
072 (ServiceBeanMethodInvocation)methodInvocation;
073
074 serviceBeanMethodInvocation.mark();
075
076 Object returnValue = null;
077 Throwable throwable = null;
078
079 while ((retries < 0) || (retries-- > 0)) {
080 try {
081 returnValue = serviceBeanMethodInvocation.proceed();
082
083 if (!retryAcceptor.acceptResult(returnValue, properties)) {
084 return returnValue;
085 }
086
087 if (_log.isWarnEnabled() && (retries != 0)) {
088 String number = String.valueOf(retries);
089
090 if (retries < 0) {
091 number = "unlimited";
092 }
093
094 _log.warn(
095 "Retry on " + methodInvocation + " for " + number +
096 " more times due to result " + returnValue);
097 }
098 }
099 catch (Throwable t) {
100 throwable = t;
101
102 if (!retryAcceptor.acceptException(t, properties)) {
103 throw t;
104 }
105
106 if (_log.isWarnEnabled() && (retries != 0)) {
107 String number = String.valueOf(retries);
108
109 if (retries < 0) {
110 number = "unlimited";
111 }
112
113 _log.warn(
114 "Retry on " + methodInvocation + " for " + number +
115 " more times due to exception " + throwable,
116 throwable);
117 }
118 }
119
120 serviceBeanMethodInvocation.reset();
121 }
122
123 if (throwable != null) {
124 if (_log.isWarnEnabled()) {
125 _log.warn(
126 "Give up retrying on " + methodInvocation + " after " +
127 totalRetries + " retries and rethrow last retry's " +
128 "exception " + throwable,
129 throwable);
130 }
131
132 throw throwable;
133 }
134
135 if (_log.isWarnEnabled()) {
136 _log.warn(
137 "Give up retrying on " + methodInvocation + " after " +
138 totalRetries + " retries and returning the last retry's " +
139 "result " + returnValue);
140 }
141
142 return returnValue;
143 }
144
145 private static final Log _log = LogFactoryUtil.getLog(RetryAdvice.class);
146
147 private static final Retry _nullRetry = new Retry() {
148
149 @Override
150 public Class<? extends RetryAcceptor> acceptor() {
151 return null;
152 }
153
154 @Override
155 public Class<? extends Annotation> annotationType() {
156 return Retry.class;
157 }
158
159 @Override
160 public Property[] properties() {
161 return null;
162 }
163
164 @Override
165 public int retries() {
166 return 0;
167 }
168
169 };
170
171 }