Home » Java » java – @Recover (fallback method) is not getting invoked when used with @CircuitBreaker, once all the retry gets exhaused-Exceptionshub

java – @Recover (fallback method) is not getting invoked when used with @CircuitBreaker, once all the retry gets exhaused-Exceptionshub

Posted by: admin February 25, 2020 Leave a comment

Questions:

Though with other return type Spring retry fallback mechanism seems to be working fine, but when it comes to calling an API with return type void. Recover method is not getting called at all, I have tried with all possible type of method parameters and changing the return type of the fallback method…. Is thr any way to do it? I don’t understand why the @CircuitBReaker annotation doesn’t have a parameter to take the fallback method name passed as a value to it?

    @CircuitBreaker(maxAttempts = 3, openTimeout = 8000, resetTimeout = 15000)
    public Void callingXYZ(final Abc abc, final Cdf cdf) {
        return retryTemplate.execute(context -> {
            log.info("Retry count={} when calling ******", context.getRetryCount());
            AbcServiceImpl.this.update*****Settings(OrgId.fromString(abc.getUUID(), cdf.getData());
            return null;
        });
    }

   //Recover method that should get invoked
    @Recover
    public Void fallbackUpdate*****(Throwable e, Abc abc) throws Throwable{
        log.info("Inside fallback");
        if (e instanceof ClientException) {
            log.warn("Fallback method is called when trying to call ******** from ****** because of {}", e.getCause());

   //Rollback in the db based on the method attributes
            throw SpecificException.forTask(HttpStatus.SERVICE_UNAVAILABLE.value(),
                    Enum.NAME.getErrorCode(),
                    Enum.NAME.getMEssage(), true);
        }
        throw e;
    } 

How to&Answers:

Try using @Retryable it works for me

 <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
        <version>1.1.5.RELEASE</version>
    </dependency>

@Retryable(value = { NullPointerException.class},maxAttempts = 2)
public void retry() throws NullPointerException{
    throw new NullPointerException("something went wrong");
}

@Recover
public void recover(NullPointerException ex)
{
    System.out.println("iniside recover");
}

For more details check this link https://www.baeldung.com/spring-retry

Answer:

I resolved the issue in my code, it had nothing to do with spring-retry project. I was unable to find the solution of my issue because of my lack of understanding in Spring implementation of AOP. As Spring’s aspect is applied to a proxy surrounding the bean not the actual class, calling a method with @circuitbreaker won’t work if it is called from a same class/Service.