Search code examples
javamultithreadingspring-bootconcurrencyhttprequest

Java Run Multiple APIs same time, collect Request List which failed


I am running same API multiple times for a List in parallel to save time. I have input List of ProductIds and API returns an Output ProductResponse with successFlag and TransactionId.

1 I am trying to run them all, the other API calls should continue even if one fails.

2 And then collect all ProductId Number Requests which fail. How would I collect the original request list that failed? Trying to modify code below.

public runAllAPIs() {

    List<Integer> productIds = Arrays.asList(2,5,7);

    List<CompletableFuture<ProductResponse>> productFutures =
                    productIds.stream()
                            .map(productIdItems -> createProduct(productId)
                            .collect(Collectors.toList());

    List<ProductResponse> productResponses =
                    productFutures.stream()
                            .map(CompletableFuture::join)
                            .collect(Collectors.toList());

    // how to print which productIds requests failed here
}

private CompletableFuture<ProductResponse> createProduct(int productId){
    return CompletableFuture.supplyAsync(() -> productAPI.createProduct(productId);
}

@Data
public class ProductResponse {
  private boolean isSuccessAPI;
  private int transactionId;
}

Note: the Response Object does not contain ProductId in request.


Solution

  • @Test
    public void test() {
        List<Integer> productIds = Arrays.asList(2, 5, 7);
    
        List<CompletableFuture<MyCustomProductResponse>> productFutures =
                productIds.stream()
                        .map(productId -> createProduct(productId))
                        .collect(Collectors.toList());
    
        List<MyCustomProductResponse> productResponses =
                productFutures.stream()
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList());
    
        // how to print which productIds requests failed here
        productResponses.forEach(pr -> {
            if (!pr.apiResponse.isSuccessAPI) {
                System.out.println(pr.productId);
            }
        });
    }
    
    private CompletableFuture<MyCustomProductResponse> createProduct(int productId) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
                // This is what you get from API
                ProductResponseFromAPI apiResponse = new ProductResponseFromAPI(new Random().nextBoolean(), new Random().nextInt());
                //You wrap that in your own object
                return new MyCustomProductResponse(productId, apiResponse);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }
    
    @Value
    static class ProductResponseFromAPI {
        private boolean isSuccessAPI;
        private int productTransactionId;
    }
    
    @Value
    static class MyCustomProductResponse {
        private int productId;
        private ProductResponseFromAPI apiResponse;
    }