Retry for multiple parallel Api calls

I am doing multiple api calls parallely using completableFuture. I am Using RetryTemplate to invoke the Api when the api calls fail with 500 then it should retry. if multiple api calls fail I want the retry to happen for all the calls which got failed. I can see only one api call is retrying where as others calls are not getting retried

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.CompletableFuture;

@Service
public class ApiCaller {

@Autowired
private RetryTemplate retryTemplate;

// Method to call your API using RetryTemplate
public String callApiWithRetry(String apiUrl) {
    return retryTemplate.execute(context -> {
        System.out.println("Attempt: " + (context.getRetryCount() + 1));
        return makeApiCall(apiUrl);
    });
}

// Simulated API call method
private String makeApiCall(String apiUrl) {
    // Simulate an API call (replace with actual implementation)
    // For demonstration purposes, throw an exception to simulate a failure
    throw new RuntimeException("Simulated API failure for " + apiUrl);
}

// Method to execute API calls asynchronously
public void executeApiCalls() {
    CompletableFuture<String> call1 = CompletableFuture.supplyAsync(() -> callApiWithRetry("http://api.example.com/endpoint1"));
    CompletableFuture<String> call2 = CompletableFuture.supplyAsync(() -> callApiWithRetry("http://api.example.com/endpoint2"));

    // Combine results
    CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(call1, call2);

    // Handle results after both calls complete
    combinedFuture.thenRun(() -> {
        try {
            String result1 = call1.get();
            String result2 = call2.get();
            System.out.println("Result from call 1: " + result1);
            System.out.println("Result from call 2: " + result2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    });

    // Wait for completion
    combinedFuture.join();
}
}

In the above snippet, both call1 and call2 are failing, but I can see only one of the api call is retrying. I am expecting both calls to be retried.

Retry Template config:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import 
org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.web.client.HttpServerErrorException;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class RetryConfig {

@Bean
public RetryTemplate retryTemplate() {
    RetryTemplate retryTemplate = new RetryTemplate();

    // Retry only for 500 errors (HttpServerErrorException)
    Map<Class<? extends Throwable>, Boolean> retryableExceptions = new HashMap<>();
    retryableExceptions.put(HttpServerErrorException.class, true); // Retry on 500 errors

    SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3, retryableExceptions); // 3 retries for 500 error
    retryTemplate.setRetryPolicy(retryPolicy);

    // Exponential backoff policy (Optional)
    ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
    backOffPolicy.setInitialInterval(1000);  // Initial interval in milliseconds
    backOffPolicy.setMultiplier(2.0);        // Backoff multiplier
    backOffPolicy.setMaxInterval(10000);     // Maximum backoff interval
    retryTemplate.setBackOffPolicy(backOffPolicy);

    return retryTemplate;
}
}

2

Your RetryTemplate is specifically configured to retry on HttpServerErrorException (which typically corresponds to HTTP 500 errors), you need to throw HttpServerErrorException when simulating API failures and not RuntimeException which is not part of the retryable exceptions as defined in your RetryTemplate configuration.

Updated code:

private String makeApiCall(String apiUrl) {
    // Simulate an API call failure with 500 status code
    throw new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "Simulated API failure for " + apiUrl);
}

2

The problem here is that CompletableFuture does not handle exceptions properly for parallel tasks. When one API call fails, it affects the overall execution, and retries aren’t properly triggered for both calls.

You need to add exception handling for each CompletableFuture using .exceptionally() to make sure retries are handled independently.

Here is an example of how you might change your calls:

CompletableFuture<String> call1 = CompletableFuture.supplyAsync(() -> {
    try {
        return callApiWithRetry("http://api.example.com/endpoint1");
    } catch (Exception e) {
        throw new RuntimeException("Call 1 failed after retries", e);
    }
}).exceptionally(e -> {
    System.err.println("Error in call 1: " + e.getMessage());
    return "Failed call 1"; // Fallback or handle failure
});

Apply similar exception handling to your other CompletableFuture calls, in this example call2, to guarantee independent retries and proper failure handling.
The rest of your code looks fine.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật