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.