Using CompletableFuture to build an object with multiple methods

I’m trying to understand CompletableFuture and how I can utilise it to build an object with information obtained from several endpoints. I’ve come across a few examples but none are quite tailored to my problem. For example, this one is running the same method in parallel to get a list of strings where I want to run multiple methods in parallel to build and return an object.

I’ve created a simple DTO for an employee:

@Builder
@Data
@AllArgsConstructor
public class EmployeeDTO {

    private String name;
    private String accountNumber;
    private int salary;

}

I’ve created a service to mimic calls to three separate APIs to set the values of the DTO with a considerable wait time:

public class EmployeeService {

    public EmployeeDTO setName() {
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return EmployeeDTO.builder().name("John Doe").build();
    }

    public EmployeeDTO setAccountNumber() {
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return EmployeeDTO.builder().accountNumber("1235").build();
    }

    public EmployeeDTO setSalary() {
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return EmployeeDTO.builder().salary(100000).build();
    }
}

I can supplyAsync all three of the methods and then run allOf but it doesn’t do anything:

    private void run() {
        EmployeeService employeeService = new EmployeeService();

        CompletableFuture<EmployeeDTO> employeeCfWithName = CompletableFuture
                .supplyAsync(employeeService::setName);
        CompletableFuture<EmployeeDTO> employeeCfWithAccountNumber = CompletableFuture
                .supplyAsync(employeeService::setAccountNumber);
        CompletableFuture<EmployeeDTO> employeeCfWithSalary = CompletableFuture
                .supplyAsync(employeeService::setSalary);

        CompletableFuture allCompletableFutures = CompletableFuture.allOf(employeeCfWithName, employeeCfWithAccountNumber, employeeCfWithSalary);
    }

How can I combine the results into one EmployeeDTO?

2
Leave a Reply

avatar
2 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Jason Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Jason
Guest

You will have to combine the results of the three CompletableFutures into a single EmployeeDTO. This is not magically done by allOf.

Try something like this (untested):

CompletableFuture allCompletableFutures = CompletableFuture.allOf(
  employeeCfWithName, employeeCfWithAccountNumber, employeeCfWithSalary);

// Wait for all three to complete.
allCompletableFutures.get();

// Now join all three and combine the results.
EmployeeDTO finalResult = EmployeeDTO.builder()
  .name(new employeeCfWithName.join())
  .accountNumber(new employeeCfWithAccountNumber.join())
  .salary(new employeeCfWithSalary.join())
  .build();

This looks a little bit silly. We use a builder in every method just to combine their results using a fourth builder.

Jason
Guest

Make you employee service functions take EmployeeDTO.builder() as input and then in run() function create one builder and pass that builder in the all supplyAsync calls to service. Also make sure that you build() after allOf() call which guarantees that every service call is done with its part. Also do not build in individual service function – public class EmployeeService { public EmployeeDTO setName(EmployeeDTO.EmployeeDTOBuilder builder) { try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } return builder.name("John Doe"); } public EmployeeDTO setAccountNumber(EmployeeDTO.EmployeeDTOBuilder builder) { try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } return… Read more »