I have a simple Service class that makes call to a third party API to create or update the record. I have 2 separate methods in my service class to make the POST and PUT call. The service class first makes a POST call , and if the API throws an exception stating that the property already exists then a PUT call is done. There is no other way to know before hand and hence have to rely on exception from the API. Below are the methods (the retries works fine, so not including the retry configurations)
@Retryable(retryFor = {TechnicalException.class}) public void createPropertyWithRetry(CustomData customData) throws TechnicalException { try { List<CustomDataDetail> response = clientApi.createCustomData(customData); } catch (ApiException e) { if (isTechnicalError(e)) { throw new TechnicalException("Technical error"); } } } @Retryable(retryFor = {TechnicalException.class}) public void updatePropertyWithRetry(CustomData customData) throws TechnicalException { try { List<CustomDataDetail> response = clientApi.updateCustomData(customData); } catch (ApiException e) { if (isTechnicalError(e)) { throw new TechnicalException("Technical error"); } } } Below is my recover method
@Recover public void recoverFromTechnicalFailure( TechnicalException ex, CustomDataApi customDataApi, CustomDataDetail customDataDetail, String propertyCode) { logErrorMessage( log, "Operation failed after {} retries for property {}", maxRetryAttempts, propertyCode, ex); metricsService.incrementRetriesExhausted(); throw new TechnicalException( "Failed to process property " + propertyCode + " after all retries", ex); } The retries should only be for TechnicalException.
Orchestrator method part that calls the above methods
void makeApiCall(){ try { apiService.createPropertyWithRetry(customDataApi); } catch (ApiException apiException) { if (doesPropertyExist(apiException)) { // checks and apiService.updatePropertyWithRetry(customDataApi); } else { // handling / re-throwing other exceptions } } } The issue is following: What would be the right way to throw ApiException from my retryable method? Because it retries only for TechnicalException if I throw ApiException from those methods, the app throws below exception:
org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method
As a work around, I can wrap the exception in another class and with a boolean variable and then return that and do orchestration. But, I wanted to know if there is a cleaner way to do it.