resilience4j / resilience4j

Resilience4j is a fault tolerance library designed for Java8 and functional programming
Apache License 2.0
9.74k stars 1.33k forks source link

ignoreExceptions & recordExceptions are not working as expected #1176

Closed VravikumarV closed 4 years ago

VravikumarV commented 4 years ago

Resilience4j version:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-boot2</artifactId>
            <version>1.5.0</version>
        </dependency>

Java version: 11

Spring Rest Controller methods are configured as follows:

   @CircuitBreaker(name = "testService", fallbackMethod = "geMyExpectedResponseFallBack")
    public MyExpectedResponse geMyExpectedResponse(final String custId) {
        if (custId.equalsIgnoreCase("11130817")) throw new NumberFormatException("NFE");
        if (custId.equalsIgnoreCase("11130423")) throw new NullPointerException("NPE");
        // do what you suppose to do to return actual MyExpectedResponse 
    }

    public MyExpectedResponse geMyExpectedResponseFallBack(final String custId, Throwable rt) {
        //  do what you suppose to do to return Fallback MyExpectedResponse 
    }                     

application.yml

resilience4j:
  circuitbreaker:
    configs:
      default:
        registerHealthIndicator: true
        slidingWindowSize: 10
        minimumNumberOfCalls: 2
        permittedNumberOfCallsInHalfOpenState: 1
        automaticTransitionFromOpenToHalfOpenEnabled: true
        waitDurationInOpenState: 5s
        failureRateThreshold: 5
        eventConsumerBufferSize: 10
        recordExceptions:
          - org.springframework.web.client.HttpServerErrorException
          - java.util.concurrent.TimeoutException
          - java.io.IOException
  instances:
    testService:
      baseConfig: default
      ringBufferSizeInClosedState: 4
      registerHealthIndicator: true
      ignoreExceptions:
        - java.lang.NumberFormatException
      recordExceptions:
        - java.lang.NullPointerException

Based on the above code base, am expecting that CircuitBreaker fallback should be triggered and response should return from fallback method only for all exception mentioned as recordExceptions (in this case NullPointerException for custId = 11130423).

But in my case, fallBackmethod getting triggered for exceptions declared under ignoreExceptions as well (in this case NumberFormatException for a given input custId = 11130817)

Could you help on this to on how to consider only recordExceptions (in this case: NullPointerException) for fallBack behaviour but not ignoreExceptions (in this case : NumberFormatException) configuration ?

Thanks for raising a Resilience4j issue. Please replace this text with a brief description of your problem along with the versions you are using. If possible, please also consider putting together a complete JUnit test that reproduces the issue.

RobWin commented 4 years ago

The fallback is like a try/catch. It catches every exception which you have specified in your method signature. It does not ignore any exceptions right now. If you only want to have fallback methods for certain exceptions, define fallback methods with specific exceptions. Also better wrap exceptions in a custom ValidationException.

public MyExpectedResponse getMyExpectedResponseFallBack(final String custId, NumberFormatException ex) {

}                     

public MyExpectedResponse getMyExpectedResponseFallBack(final String custId, NullPointerException ex) {

}     

public MyExpectedResponse getMyExpectedResponseFallBack(final String custId, CallNotPermittedException ex) {

} 

better is:

public MyExpectedResponse getMyExpectedResponseFallBack(final String custId, ValidationException ex) {

} 

public MyExpectedResponse getMyExpectedResponseFallBack(final String custId, CallNotPermittedException ex ) {

}