karthik karthik - 1 month ago 32
Java Question

Spring Retry Framework with Annotation not Working

I tried spring retry framework with Simple java classes using SimpleRetryPolicy/RetryTemplate. It worked fine. So I thought of doing the same with Annotations. Annotations never worked for me. Didn't find much help online as well. The following code just worked like normal Java program throwing the exception at first attempt which is not the expected behavior. It should have tried atleast 5 times before throwing exception or recovering from it. Not sure where I went wrong. Do I need to do any XML/spring AOP configuration for this to work ? How would that be

import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;

@EnableRetry
@Configuration
public class App {
public static void main(String[] args) throws Exception {
Parentservice p = new SpringRetryWithHystrixService();
String status = p.getStatus();
System.out.println(status);
}
}

import org.springframework.retry.annotation.Retryable;
public interface Parentservice {
@Retryable(maxAttempts=5)
String getStatus() throws Exception;
}


import org.springframework.retry.annotation.Recover;
public class SpringRetryWithHystrixService implements Parentservice{

public static int i=0;

public String getStatus() throws Exception{
System.out.println("Attempt:"+i++);
throw new NullPointerException();
}

@Recover
public static String getRecoveryStatus(){
return "Recovered from NullPointer Exception";
}
}


I tried @Retryable(maxAttempts=5) on the top of interface and implementation which didn't make any difference.

Answer

Your application has to be managed by Spring, you can't just use new ...

Parentservice p = new  SpringRetryWithHystrixService();

Here's a Spring Boot app...

@SpringBootApplication
@EnableRetry
public class So40308025Application {

    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = SpringApplication.run(So40308025Application.class, args);
        System.out.println(context.getBean(SpringRetryWithHystrixService.class).getStatus());
        context.close();
    }

}


@Component
public class SpringRetryWithHystrixService {

    public static int i = 0;

    @Retryable(maxAttempts = 5)
    public String getStatus() throws Exception {
        System.out.println("Attempt:" + i++);
        throw new NullPointerException();
    }

    @Recover
    public static String getRecoveryStatus() {
        return "Recovered from NullPointer Exception";
    }

}

result:

Attempt:0
Attempt:1
Attempt:2
Attempt:3
Attempt:4
Recovered from NullPointer Exception

If you don't want to use Spring Boot for some reason, use

@Configuration
@EnableRetry
public class So40308025Application {

    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(So40308025Application.class);
        System.out.println(context.getBean(SpringRetryWithHystrixService.class).getStatus());
        context.close();
    }

    @Bean
    public SpringRetryWithHystrixService service() {
        return new SpringRetryWithHystrixService();
    }

}