Return method results and supply them as parameters to methods that execute in a chain

Viewed 58

The following code executes 3 methods sequentially using CompletableFuture.

ExecutorService executor = Executors.newSingleThreadExecutor();

// Various handlers
ModelHandler modelHandler = new ModelHandler();
PermissionHandler permissionHandler = new PermissionHandler();
RemoteClient remoteClient = new RemoteClient();


Runnable getFacadeMetadata = () -> modelHandler.getMetadata("myMethod");
Runnable isUserAuthorized = () -> permissionHandler.isUserAuthorized("user");
Runnable invoke = () -> remoteClient.invoke();

CompletableFuture.runAsync(getMetadata, executor)
    .thenRunAsync(isUserAuthorized, executor)
    .thenRunAsync(invoke, executor);

Currently they don't return values and supply them as parameters to the next calls.

How should the CompletableFuture chain be written so that the first two methods can return data to be consumed by later methods?

Example:

String metadata = modelHandler.getMetadata("myMethod");
boolean authorized = permissionHandler.isUserAuthorized("user", metadata); // metadata passed

remoteClient.invoke(metadata, authorized); // metadata and authorized passed
1 Answers

If you just had 2 methods then it would be very easy to pass the return value of the first to the second ofcourse

Supplier<String> getFacadeMetadata = () -> modelHandler.getMetadata("myMethod");
Function<String, Object[]> isUserAuthorized = (metadata) -> permissionHandler.isUserAuthorized("user", metadata);
CompletableFuture.supplyAsync(getFacadeMetadata, executor).thenApplyAsync(isUserAuthorized, executor);

But you wish to pass the return value of the first method (metadata) to the third function and I don't think that can be done directly. You may call getMetadata again or change return of isAuthorized to array, returning both metadata and boolean, neither a clean approach I'm afraid. So below is what I would propose

Supplier<String> getFacadeMetadata = () -> modelHandler.getMetadata("myMethod");
Consumer<String> invoke = (metadata) -> {
    boolean isAuth = permissionHandler.isUserAuthorized("user", metadata);
    remoteClient.invoke(metadata, isAuth);
};

CompletableFuture.supplyAsync(getFacadeMetadata, executor)
        .thenAcceptAsync(invoke, executor);
Related