0

I have created an adapterImpl class that will retry a method with an objA but if it throws an exception(hardcoded to throw) it will call recover method - which will again call the method with objB.

My problem is - The @Recover method is not called. I am not sure what I am doing wrong here.

Spring version - 4.3.5.RELEASE

Spring retry - 1.2.1.RELEASE

My Config class -

@Configuration
@EnableRetry
public class ConfigClass {

@Bean
public ClassTest beanA(){
    ClassTest obj = new ClassTest();
    obj.setProp(5);
    return obj;
}

@Bean
public ClassTest beanB(){
    ClassTest obj = new ClassTest();
    obj.setProp(10);
    return obj;
}

@Bean("adapterImpl")
public AdapterInterfaceImpl adapter(){
    AdapterInterfaceImpl obj = new AdapterInterfaceImpl();
    return obj;
}
}

My AdapterInterfaceImpl class -

public class AdapterInterfaceImpl implements AdapterInterface{

@Autowired
@Qualifier("beanA")
private ClassTest objA;

@Autowired
@Qualifier("beanB")
private ClassTest objB;


public ClassTest getObjA() {
    return objA;
}


public void setObjA(ClassTest objA) {
    this.objA = objA;
}


public ClassTest getObjB() {
    return objB;
}


public void setObjB(ClassTest objB) {
    this.objB = objB;
}


@Retryable(maxAttempts = 3, include = Exception.class, backoff = @Backoff(delay = 2000))
public int getValue(int val) throws Exception{
    System.out.println("obj A get Value");
    return getValue(objA,val);
}


public int getValue(ClassTest obj, int val) throws Exception{
    System.out.println("get Value");
    if(obj==objA){
        throw new Exception("This is msg");
    }
    return obj.methodA(val);
}

@Recover
public int getValue(Exception e, int val){
    System.out.println("Recover get Value");
    try{
        return getValue(objB,val);
    }catch(Exception e1){
        return 0;
    }           
}

My ClassTest class -

public class ClassTest {
private int prop;

public int getProp() {
    return prop;
}

public void setProp(int prop) {
    this.prop = prop;
}

public int methodA(int x){
    return x+prop;
}

}

My class with main method -

public class App 
{   
public static void main( String[] args )
{
    AbstractApplicationContext context = new 
    AnnotationConfigApplicationContext(ConfigClass.class);
    AdapterInterface adapter = (AdapterInterface) 
    context.getBean("adapterImpl");
    try {
        System.out.println(adapter.getValue(3));
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

My output is not showing any retry nor recovery -

 A get Value
 get Value
 obj A get Value
 get Value
 obj A get Value
 get Value
 org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is java.lang.Exception: This is msg
user93726
  • 683
  • 1
  • 9
  • 22

2 Answers2

1

Spring Retry uses AOP, internal calls (from getValue(int) to getValue(ClassTest, int)) won't go through the proxy.

You have to put the @Retryable on the method that is called externally so that the proxy can intercept the call and apply the retry logic.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Hi thank you, my retry is working. But I am getting `Cannot locate recovery method;` as an exception. I tried changing the name of my recovery Mehod to **getValue(exception,int)**. By removing the ClassTest argument so that it can match **getValue(int)** retryable method. Still not working. – user93726 May 02 '18 at 04:11
0

There is a similar issue reported in https://github.com/spring-projects/spring-retry/issues/75

So @EnableRetry(proxyTargetClass=true) works as it is now able to find the recovery method in the implementation class.

user93726
  • 683
  • 1
  • 9
  • 22