Search code examples
javacompletable-futurefuturetask

Return a value inside a CompletableFuture in another CompletableFuture and return that future


I want to get a value inside a CompletableFuture (in this case clonedWorld) in another CompletableFuture and return that future. This is my code, and I'm stuck here:

@Override
public CompletableFuture<SlimeWorld> asyncCloneWorld(String worldName, String newWorld) {
    loadWorldAsync(worldName).whenComplete((slimeWorld, throwable) -> {
        if (throwable != null || slimeWorld.isEmpty()) {
            plugin.getLogger().log(Level.SEVERE, "Impossibile caricare il mondo template!", throwable);
            return;
        }
        try {
            SlimeWorld clonedWorld = slimeWorld.get().clone(newWorld, loader, true);
        } catch (IOException | WorldAlreadyExistsException e) {
            plugin.getLogger().log(Level.SEVERE, "Non è stato possibile clonare il mondo: " + worldName, e);
        }
    });
  return ?;
}

Solution

  • Your problem is that whenComplete() only takes a BiConsumer as parameter, which cannot handle the result of the returned CompletableFuture – except if an exception is thrown.

    The appropriate method to use if you want to change the result (here from something like Optional<SlimeWorld> or an exception to just SlimeWorld or null) is handle(). The lambda passed to handle() should thus return the final result (the cloned world or null).

    And as CompletableFuture is a fluent API, you can just return the result of the handle() call from asyncCloneWorld():

    public CompletableFuture<SlimeWorld> asyncCloneWorld(String worldName, String newWorld) {
        return loadWorldAsync(worldName).handle((slimeWorld, throwable) -> {
            if (throwable != null || slimeWorld.isEmpty()) {
                plugin.getLogger().log(Level.SEVERE, "Impossibile caricare il mondo template!", throwable);
                return null;
            }
            try {
                return slimeWorld.get().clone(newWorld, loader, true);
            } catch (IOException e) {
                plugin.getLogger().log(Level.SEVERE, "Non è stato possibile clonare il mondo: " + worldName, e);
                return null;
            }
        });
    }