I'm trying to implement a retry mechanism using spring retry. However, retries are not working. I have added @EnableRetry annotation in the main class
Below is the code of the service class. I want to retry the getProductMetadata method 3 times on exception. The exception is 502 Error.
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestTemplate;
@Service
@Slf4j
public class ProductService {
private String productInfoBaseUrl = "http://localhost";
@Value("${service.product.metadata}")
private String productInfoPathProductMetadata;
private static final Logger logger = LoggerFactory.getLogger(ProductService.class);
@Autowired
RestTemplate restTemplate;
int count = 0;
@Retryable(retryFor = Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 100))
public ProductResponse getProductMetadata(String sku, HandlerResult handlerResult) {
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
String errorMsg;
String endpoint = getProductFetchMetadataEndpoint();
ResponseEntity<String> response;
try {
response = restTemplate.getForEntity(endpoint, String.class);
} catch (Exception ex) {
errorMsg = "getProductMetadata for sku: " + sku + " threw exception: " + ex.getMessage();
//log.info(errorMsg);
HandlerResult.updateStatus(handlerResult, errorMsg, false);
logger.info(++count + " Call attempts were made");
return null;
}
ProductResponse metadataResponse;
Gson gson = new Gson();
try {
metadataResponse = gson.fromJson(response.getBody(), ProductResponse.class);
} catch (Exception e) {
errorMsg = String.format("Exception ProductResponse converting %s to map", response.getBody());
log.info(errorMsg);
HandlerResult.updateStatus(handlerResult, errorMsg, false);
return null;
}
return metadataResponse;
}
private String getProductFetchMetadataEndpoint() {
return productInfoBaseUrl + "/" + productInfoPathProductMetadata + "/";
}
}
Can someone please guide me on what I'm missing?
Spring retry uses a proxy to detect if a retryable exception is thrown, the proxy wraps around the class, looking for method invocations that throw exceptions.
If you catch all the exceptions inside the method then the proxy won't see any exceptions and won't know it needs to retry anything.
You can still catch exceptions for purposes like logging, just make sure to rethrow anything you want retried.
Here is another answer I posted with a working example using spring retry. Exceptions get thrown from the retryable method and trigger the retry behavior.