Add clone for method invocation to preserve interceptor chain.
This commit is contained in:
@@ -18,6 +18,7 @@ package org.springframework.batch.repeat.aop;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.framework.ReflectiveMethodInvocation;
|
||||
import org.springframework.batch.repeat.RepeatCallback;
|
||||
import org.springframework.batch.repeat.RepeatContext;
|
||||
import org.springframework.batch.repeat.RepeatOperations;
|
||||
@@ -50,14 +51,21 @@ public class RepeatOperationsInterceptor implements MethodInterceptor {
|
||||
*
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
||||
*/
|
||||
public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
|
||||
public Object invoke(final MethodInvocation invocation) throws Throwable {
|
||||
|
||||
batchTempate.iterate(new RepeatCallback() {
|
||||
|
||||
public ExitStatus doInIteration(RepeatContext context) throws Exception {
|
||||
try {
|
||||
|
||||
MethodInvocation clone = invocation;
|
||||
if (invocation instanceof ReflectiveMethodInvocation) {
|
||||
clone = ((ReflectiveMethodInvocation) invocation)
|
||||
.invocableClone();
|
||||
}
|
||||
|
||||
// N.B. discards return value if there is one
|
||||
return new ExitStatus(methodInvocation.proceed() != null);
|
||||
return new ExitStatus(clone.proceed() != null);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
if (e instanceof Exception) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.batch.retry.aop;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.framework.ReflectiveMethodInvocation;
|
||||
import org.springframework.batch.retry.RetryCallback;
|
||||
import org.springframework.batch.retry.RetryContext;
|
||||
import org.springframework.batch.retry.RetryOperations;
|
||||
@@ -38,12 +39,26 @@ public class RetryOperationsInterceptor implements MethodInterceptor {
|
||||
this.retryTemplate = retryTemplate;
|
||||
}
|
||||
|
||||
public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
|
||||
public Object invoke(final MethodInvocation invocation) throws Throwable {
|
||||
// TODO: use the method name to initialise a statistics context
|
||||
return this.retryTemplate.execute(new RetryCallback() {
|
||||
|
||||
public Object doWithRetry(RetryContext context) throws Throwable {
|
||||
return methodInvocation.proceed();
|
||||
|
||||
/*
|
||||
* If we don't copy the invocation carefully it won't keep a
|
||||
* reference to the other interceptors in the chain. We don't
|
||||
* have a choice here but to specialise to
|
||||
* ReflectiveMethodInvocation (but how often would another
|
||||
* implementation come along?).
|
||||
*/
|
||||
MethodInvocation clone = invocation;
|
||||
if (invocation instanceof ReflectiveMethodInvocation) {
|
||||
clone = ((ReflectiveMethodInvocation) invocation)
|
||||
.invocableClone();
|
||||
}
|
||||
|
||||
return clone.proceed();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -21,12 +21,16 @@ import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.batch.repeat.RepeatCallback;
|
||||
import org.springframework.batch.repeat.RepeatOperations;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.batch.repeat.exception.RepeatException;
|
||||
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
|
||||
import org.springframework.batch.retry.support.RetryTemplate;
|
||||
|
||||
public class RepeatOperationsInterceptorTests extends TestCase {
|
||||
|
||||
@@ -88,6 +92,22 @@ public class RepeatOperationsInterceptorTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testInterceptorChainWithRetry() throws Exception {
|
||||
((Advised) service).addAdvice(interceptor);
|
||||
final List list = new ArrayList();
|
||||
((Advised) service).addAdvice(new MethodInterceptor() {
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
list.add("chain");
|
||||
return invocation.proceed();
|
||||
}
|
||||
});
|
||||
RetryTemplate template = new RetryTemplate();
|
||||
template.setRetryPolicy(new SimpleRetryPolicy(2));
|
||||
service.service();
|
||||
assertEquals(3, target.count);
|
||||
assertEquals(3, list.size());
|
||||
}
|
||||
|
||||
private interface Service {
|
||||
Object service() throws Exception;
|
||||
|
||||
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package org.springframework.batch.retry.aop;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.target.SingletonTargetSource;
|
||||
import org.springframework.batch.retry.policy.NeverRetryPolicy;
|
||||
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
|
||||
import org.springframework.batch.retry.support.RetryTemplate;
|
||||
|
||||
public class RetryOperationsInterceptorTests extends TestCase {
|
||||
@@ -45,6 +51,23 @@ public class RetryOperationsInterceptorTests extends TestCase {
|
||||
assertEquals(2, target.count);
|
||||
}
|
||||
|
||||
public void testInterceptorChainWithRetry() throws Exception {
|
||||
((Advised) service).addAdvice(interceptor);
|
||||
final List list = new ArrayList();
|
||||
((Advised) service).addAdvice(new MethodInterceptor() {
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
list.add("chain");
|
||||
return invocation.proceed();
|
||||
}
|
||||
});
|
||||
RetryTemplate template = new RetryTemplate();
|
||||
template.setRetryPolicy(new SimpleRetryPolicy(2));
|
||||
interceptor.setRetryTemplate(template);
|
||||
service.service();
|
||||
assertEquals(2, target.count);
|
||||
assertEquals(2, list.size());
|
||||
}
|
||||
|
||||
public void testRetryExceptionAfterTooManyAttempts() throws Exception {
|
||||
((Advised) service).addAdvice(interceptor);
|
||||
RetryTemplate template = new RetryTemplate();
|
||||
|
||||
Reference in New Issue
Block a user