Spring -@Recover Cannot locate recovery method exception

42 Views Asked by At

I am getting Cannot locate recovery method exception while trying to call a method which is annotated as @Retryable, I have created a recover method also with annotation @Recover, But somehow it seems recover is not getting called in case I have failures in original method.

@Retryable(maxAttempts = 3, backoff = @Backoff(random = true, maxDelay = 4000, multiplier = 2.5),
      value = {MyClientException.class})
  public ResponseEntity<String> getResponseEntity(MyModel myModel, int retryCount, JsonNode rootNode,String uri) throws MyClientException {

    ResponseEntity<String> response = ResponseEntity.internalServerError().body("ghj"); //doing it purposely to call recover method
       
    if (!HttpStatus.OK.equals(response.getStatusCode())) {
            log.info("[METHOD] Error while publishing message: {} uri: {}, result: {}, attempt: {}", serviceStatus,
      throw new MyClientException();
    }
    return response;
  }

  @Recover
  @Counted(value = CustomMetrics.TOTAL_MSG_PROCESSED)
  public ResponseEntity<String> recover(Exception e, MyModel myModel) {
    try {
      log.warn("All retries to persist serviceStatus: {} failed. publishing event async as fallback.",
          myModel);
      asyncClient.publish(serviceStatus);
      return ResponseEntity.ok().body("Submitted to persist as async");
    } catch (Exception ex) {
      log.error("Unable to publish event: {} as fallback. Failed with error: {} ",
          serviceStatus, properties.getDeadBucket(), ExceptionUtils.getStackTrace(ex));
      return ResponseEntity.internalServerError().body("Unable to publish");
    }
  }

Here I am purposely doing this to throw Exception

ResponseEntity<String> response = ResponseEntity.internalServerError().body("ghj"); 

I am trying to test this from another application where @EnableRetry is already annotated.

I am to test it with Unit test.

@Test
  public void testRecoverCalledWhenRetryExhausted() throws Exception {
    RetryTemplate retryTemplate = new RetryTemplate();
    RetryPolicy retryPolicy = new SimpleRetryPolicy(3);
    retryTemplate.setRetryPolicy(retryPolicy);

    try {
      retryTemplate.execute(context -> {
        myClientTest.getResponseEntity(new MyModel(), context.getRetryCount(), mock(JsonNode.class), "testUri");
        return null;
      });
    } catch (ExhaustedRetryException e) {
      // Ensure that the recover method is called
      verify(MyClientException, times(1)).recover(any(Exception.class), any(myModel.class));
    }
  }

This is log sample:

10:43:29.586 [main] INFO com.----ient -- [[METHOD] Error while publishing message: {"--(hiding data--"} uri: testUri, result: <500 INTERNAL_SERVER_ERROR  Internal Server Error,ghj,[]>, attempt: 0
10:43:29.591 [main] INFO com.-... -- [[METHOD] Error while publishing message: {"--(hiding data--"} uri: testUri, result: <500 INTERNAL_SERVER_ERROR  Internal Server Error,ghj,[]>, attempt: 1
10:43:29.591 [main] INFO com.... -- [METHOD] Error while publishing message: {"--(hiding data--"} uri: testUri, result: <500 INTERNAL_SERVER_ERROR Internal Server Error,ghj,[]>, attempt: 2

MyException()
    at com.wayfair.sct.ocp.status.service.client.services.StatusServiceRestClient.getResponseEntity(StatusServiceRestClient.java:73)
    at com.......MyClientTest.lambda$testRecoverCalledWhenRetryExhausted$0(MyCliemtClientTest.java:131)

I am unable to figure out what am I missing. Any leads will be highly helpful.

0

There are 0 best solutions below