CodexBloom - Programming Q&A Platform

Java 11: How to Properly Implement Retry Logic with CompletableFuture and Handle Exceptions?

👀 Views: 1306 đŸ’Ŧ Answers: 1 📅 Created: 2025-06-12
java completablefuture exception-handling retry Java

I'm sure I'm missing something obvious here, but I'm trying to implement a retry mechanism using `CompletableFuture` in Java 11 for a network call that may unexpected result intermittently. The goal is to retry the operation a few times before giving up and returning an behavior. However, I'm working with issues where the exceptions thrown by the failed attempts are not being properly handled and propagated, leading to an unhelpful `CompletionException`. I've implemented the following code snippet: ```java import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.function.Supplier; public class RetryExample { public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture<String> futureResult = retry(() -> networkCall(), 3); futureResult.thenAccept(System.out::println) .exceptionally(ex -> { System.err.println("Failed after retries: " + ex.getMessage()); return null; }); } private static CompletableFuture<String> retry(Supplier<String> supplier, int attempts) { return CompletableFuture.supplyAsync(() -> { while (attempts-- > 0) { try { return supplier.get(); } catch (Exception e) { if (attempts == 0) { throw new CompletionException(e); } System.out.println("Retrying..."); } } throw new CompletionException("Exceeded maximum retry attempts"); }); } private static String networkCall() { // Simulating network call which may unexpected result if (Math.random() < 0.7) { throw new RuntimeException("Network behavior"); } return "Success"; } } ``` I expected to see either the successful result or a clear behavior message after the retries, but instead, I'm only getting a `CompletionException` with the original behavior wrapped in it. I tried catching the specific exception thrown during the retries but that didn't seem to work. Is there a better approach to implement the retry logic here? Additionally, how can I ensure that the specific exception is logged or handled properly after all attempts have failed? Any guidance on best practices for this type of scenario would be appreciated. For context: I'm using Java on Linux. How would you solve this? For reference, this is a production service. Thanks for taking the time to read this!