I have used Spring's retry in my project to achieve retry functionality for specific exceptions.
SomeService.java
@Service
@Slf4j
public class SomeService implements AuthenticationService {
private static final String LOGIN_END_POINT = "/api/auth/v1/login";
private static final String VALIDATE_TOKEN_END_POINT = "/api/auth/v1/validate";
private RestTemplate restTemplate;
private CdsConfig cdsConfig;
@Autowired
public SomeService(CdsConfig cdsConfig, RestTemplate restTemplate) {
this.cdsConfig = cdsConfig;
this.restTemplate = restTemplate;
}
@Retryable(
value = {IOException.class, ResourceAccessException.class},
maxAttemptsExpression = "${cds.retryMaxAttempts}",
backoff = @Backoff(delayExpression = "${cds.retryMaxDelay}"))
public boolean isValidToken(String jwtToken) {
log.info("TRYING.......isValidToken");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setBearerAuth(jwtToken);
HttpEntity<Void> httpEntity = new HttpEntity<>(httpHeaders);
ResponseEntity<Void> responseEntity =
this.restTemplate.exchange(
cdsConfig.getHostUrl() + VALIDATE_TOKEN_END_POINT,
HttpMethod.GET,
httpEntity,
Void.class);
return responseEntity.getStatusCode().equals(HttpStatus.OK);
}
This code is working fine ie when another service is down then it is retrying for 3 times as expected. But while testing this method for retry counts, it is getting invoked only for 1 time.(expecting it to be 3 times.)
I wrote Junit for above method as following.
@ExtendWith(MockitoExtension.class)
@SpringBootTest
@EnableRetry
class AuthenticationServiceTest {
AuthenticationService authenticationService;
@Mock
RestTemplateConfig restTemplateConfig;
@Mock
RestTemplateBuilder restTemplateBuilder;
@Value("${cds.retryMaxAttempts}")
int retryCount;
////////////////////////// various mocks for application context///////
@Mock
private RestTemplate restTemplate;
@Mock
private CdsConfig cdsConfig;
@BeforeEach
void setUp() {
this.authenticationService = new SomeService(cdsConfig, restTemplate, callerService);
when(this.cdsConfig.getHostUrl()).thenReturn(URI.create("https://someUrl.com"));
System.out.println("Retry count=" + retryCount);
}
@Test
void test_isValidToken_whenAuthServiceDown_thenRetry() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setBearerAuth("ValidJwtToken");
HttpEntity<Void> httpEntity = new HttpEntity<>(httpHeaders);
when(this.restTemplate.exchange(
"--CorrectUrl--/api/auth/v1/validate",
HttpMethod.GET,
httpEntity,
Void.class
)).thenThrow(new ResourceAccessException("authentication service is down"));
assertThrows(ResourceAccessException.class, () -> this.authenticationService.isValidToken("ValidJwtToken"));
//verify(authenticationService, times(3)).isValidToken(anyString());
verify(this.restTemplate, times(3))
.exchange("https://dev.csm.osttra.com/api/auth/v1/validate", HttpMethod.GET, httpEntity, Void.class);
}
}
This test is failing with below error.
Retry count=3 2023-05-09 19:30:38.968 INFO [abc-svc,,] 22624 --- [ main] c.o.cds.client.impl.PlatformAuthService : TRYING.......isValidToken
org.mockito.exceptions.verification.TooFewActualInvocations: restTemplate.exchange( "--correctBaseUrl--/api/auth/v1/validate", GET, <[Authorization:"Bearer ValidJwtToken"]>, class java.lang.Void ); Wanted 3 times: -> at com.osttra.cds.client.AuthenticationServiceTest.test_isValidToken_whenAuthServiceDown_thenRetry(AuthenticationServiceTest.java:213) But was 1 time: -> at com.osttra.cds.client.impl.SomeService.isValidToken(SomeService.java:74)