Spring-Retry cannot locate recovery method when implement an interface

Viewed 6517

I found a problem when doing spring-retry with spring boot. When a class implements an interface, it cannot enter the @recover method after exceeding the maximum number of retries. But when I inject a normal class, I can enter this method.Your prompt help and kind advices would be much appreciated,thanks!

When I do this,I can enter the @Recover method

@Service
public class TestService {

    @Retryable(Exception.class)
    public String retry(String c) throws Exception{
        throw new Exception();
    }

    @Recover
    public String recover(Exception e,String c) throws Exception{
        System.out.println("got error");
        return null;
    }
}

But once the class implement another interface, it's not works

@Service
public class TestService implements TestServiceI{

    @Override
    @Retryable(Exception.class)
    public String retry(String c) throws Exception{
        throw new Exception();
    }

    @Recover
    public String recover(Exception e,String c) throws Exception{
        System.out.println("got error");
        return null;
    }
}
2 Answers

Spring-Retry uses AOP to implement the @Retry. When using AOP the default is to use JDK Dynamic Proxies. JDK Dynamic Proxies are interface based.

This means you get a dynamically created class that pretents to be a TestServiceI however it isn't a TestService. The proxy doesn't include the recover method (as it isn't on the interface) and as such Spring Retry cannot detect it.

To fix you need to enable class based proxies for Spring Retry by setting the proxyTargetClass attribute on @EnableRetry to true (see the javadoc).

@EnableRetry(proxyTargetClass=true) 
  1. mark proxyTargetClass=true: @EnableRetry(proxyTargetClass = true)
  2. The @Recover method must return the same type as the original method;
Related