Skip to content

Commit f68f983

Browse files
committed
feat(completablefuture): add demo for async tasks with timeout and exception handling
What - Introduced `CompletableFutureDemo` to demonstrate advanced usage of Java’s `CompletableFuture`. - Implemented: - Parallel execution of two async tasks: - `fetchUserDetails()` → simulates network call for user profile. - `fetchOrderHistory()` → simulates network call for user orders (with random failure). - Combination of results using `thenCombine()` to merge outputs when both tasks finish. - Timeout handling with `applyToEither()` and a helper `timeoutAfter()` future. - Exception handling with `exceptionally()` to provide a safe fallback message. - Final result is printed to console with either combined data, timeout message, or error details. Why - Showcases **asynchronous programming** in Java without blocking threads. - Demonstrates: - Running multiple tasks concurrently (`supplyAsync`). - Combining dependent async results (`thenCombine`). - Handling unpredictable delays (`timeoutAfter`). - Managing failures gracefully (`exceptionally`). - Provides a practical pattern for resilient, fault-tolerant microservice or API calls. Logic 1. **Task Creation** - `CompletableFuture.supplyAsync()` runs tasks in ForkJoinPool common pool threads. - Two tasks: - `fetchUserDetails()` → sleeps 1s, returns user string. - `fetchOrderHistory()` → sleeps 1.5s, randomly fails 30% of the time. 2. **Result Combination** - `thenCombine(userFuture, orderFuture, ...)` merges results once both complete. - Produces a formatted output containing both user and order data. 3. **Timeout Handling** - `timeoutAfter(2)` starts another async future that waits 2s before returning `"Request timed out!"`. - `applyToEither(combinedFuture, timeoutFuture)` ensures whichever completes first is used. - Prevents hanging if services are too slow. 4. **Exception Handling** - `exceptionally(ex -> "Error fetching data: ...")` ensures program never crashes. - Converts runtime exceptions (like service failure) into safe user-facing messages. 5. **Final Execution** - `join()` waits for result, returning either: - Successful combined data, - Timeout message, - Or error fallback. Real-life applications - Microservices orchestration: Fetching data from multiple APIs in parallel with timeouts. - E-commerce systems: Get user profile + order/cart details concurrently. - Mobile/Frontend backends: Aggregate slow services without blocking UI. - Fault-tolerant distributed systems: Ensure safe defaults when some services fail. Notes - Default async execution uses ForkJoinPool’s common pool; can supply custom executors for better scaling. - `applyToEither()` races futures → useful for fallback/timeout patterns. - Always handle exceptions (`exceptionally` or `handle`) in production-grade async flows. - Random failure in `fetchOrderHistory()` mimics real-world flaky services. Signed-off-by: https://github.com/Someshdiwan <[email protected]>
1 parent 7c82386 commit f68f983

File tree

1 file changed

+36
-35
lines changed

1 file changed

+36
-35
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import java.util.concurrent.*;
22

3-
public class CompletableFutureAdvancedExample {
3+
public class CompletableFutureDemo {
44
public static void main(String[] args) {
55
// Start both tasks in parallel
66
CompletableFuture<String> userFuture = CompletableFuture.supplyAsync(() -> fetchUserDetails());
@@ -23,7 +23,7 @@ public static void main(String[] args) {
2323
System.out.println(result);
2424
}
2525

26-
// Simulates fetching user details (may be slow)
26+
// Simulates fetching user details (maybe slow)
2727
private static String fetchUserDetails() {
2828
sleep(1000); // Simulate network delay
2929
return "John Doe, Age 30";
@@ -50,37 +50,38 @@ private static CompletableFuture<String> timeoutAfter(int seconds) {
5050
}
5151
}
5252

53+
/*
54+
Complex Example: Making Parallel API Calls with Timeout & Error Handling
5355
54-
//### **🔥 Complex Example: Making Parallel API Calls with Timeout & Error Handling**
55-
//#### **Scenario:**
56-
//We need to fetch user details and their order history **simultaneously** from two different services.
57-
//- **User Service** → Returns user details
58-
//- **Order Service** → Returns the user's past orders
59-
//- Both should run **in parallel**.
60-
//- If either fails, we should **handle errors gracefully**.
61-
//- If the response takes too long, we should **timeout** the request.
62-
//
63-
//### **🔍 Step-by-Step Explanation**
64-
//1. **Parallel Execution**:
65-
// - `CompletableFuture.supplyAsync(fetchUserDetails())` runs **user service** in a separate thread.
66-
// - `CompletableFuture.supplyAsync(fetchOrderHistory())` runs **order service** in parallel.
67-
//
68-
//2. **Combining Results (`thenCombine()`)**
69-
// - When both futures are done, we combine the responses:
70-
// - `"User: John Doe\nOrders: Laptop, Phone"`
71-
//
72-
//3. **Timeout Handling (`applyToEither()`)**
73-
// - If the API call takes longer than **2 seconds**, it returns `"Request timed out!"`.
74-
//
75-
//4. **Error Handling (`exceptionally()`)**
76-
// - If any API fails, it catches the exception and returns `"Error fetching data"`.
77-
//
78-
//### **📌 Why is this "Hard"?**
79-
//- **Runs tasks in parallel** to improve performance.
80-
//- **Handles failures** without crashing the app.
81-
//- **Implements a timeout** mechanism using `applyToEither()`.
82-
//- **Combines API results dynamically**.
83-
//
84-
//This is a real-world pattern used in **microservices, web applications, and high-performance systems**. 🚀
85-
//
86-
//Would you like a breakdown of any part? 😊
56+
Scenario:
57+
We need to fetch user details and their order history simultaneously from two different services.
58+
- User Service → returns user details.
59+
- Order Service → returns the user's past orders.
60+
- Both should run in parallel.
61+
- If either fails, we should handle errors gracefully.
62+
- If the response takes too long, we should timeout the request.
63+
64+
Step-by-Step Explanation:
65+
66+
1. Parallel Execution:
67+
- CompletableFuture.supplyAsync(fetchUserDetails()) runs the user service in a separate thread.
68+
- CompletableFuture.supplyAsync(fetchOrderHistory()) runs the order service in parallel.
69+
70+
2. Combining Results (thenCombine):
71+
- When both futures are completed, we combine the responses into a single result,
72+
for example: "User: John Doe\nOrders: Laptop, Phone".
73+
74+
3. Timeout Handling (applyToEither):
75+
- If an API call takes longer than 2 seconds, it returns a default response such as "Request timed out!".
76+
77+
4. Error Handling (exceptionally):
78+
- If any API fails, the exception is caught, and a safe fallback like "Error fetching data" is returned.
79+
80+
Why is this considered a "hard" example?
81+
- Tasks run in parallel, improving performance.
82+
- Failures are handled without crashing the application.
83+
- A timeout mechanism is implemented with applyToEither().
84+
- Results from multiple APIs are combined dynamically.
85+
86+
This pattern is commonly used in microservices, web applications, and high-performance systems.
87+
*/

0 commit comments

Comments
 (0)