Reputation: 2369
I have some workflow abstraction that relies on an interface WorkflowStep
:
public interface WorkflowStep {
public void executeStep();
}
Now I have got three different classes that implement this interface:
GetCoordinatesForWaypoints, DisplayDetails, PlaySounds
My aim is to chain them with CompletableFuture
, currently each overriden executeStep()
method runs in a runnable, like shown here for example:
public class GetCoordinatesForEndpoints implements WorkflowStep {
@Override
public void executeStep() {
new Thread(new Runnable() {
@Override
public void run() {
//download coordinates from open street map
}).start();
}
}
The other classes methods look similiar. Now I have a central class where the workflow is started. Currently it looks like this:
public class DetailsDispatchWorkflow implements DispatchWorkflow {
private List<WorkflowStep> workflowSteps;
public DetailsDispatchWorkflow() {
workflowSteps = new LinkedList<>();
}
@Override
public void start() {
workflowSteps.add(new GetCoordinatesForEndpoints());
workflowSteps.add(new DisplayDetails());
workflowSteps.add(new PlaySounds());
workflowSteps.forEach(WorkflowStep::executeStep);
}
}
Now I want to replace this with CompletableFuture
s. The first thing I tried was to do something like this:
ExecutorService executorService = Executors.newFixedThreadPool(5);
CompletableFuture<WorkflowStep> workflowStepCompletableFuture =
CompletableFuture.supplyAsync(() -> new
GetCoordinatesForEndpoints().executeStep(), executorService);
which gives me an error (I think because the called method returns void). Calling only the constructor works. My next step is to chain those calls with thenAccept
(because the called actions do not return a value), but that does not work either, when I append
.thenAccept(() -> new DisplayDetails().executeStep(), executorService);
I get an error that the compiler cannot infer the functional interface type. My quesiton is: How can I achieve the following call chain:
CompletableFuture<WorkflowStep> workflowStepCompletableFuture =
CompletableFuture
.supplyAsync(() -> new GetCoordinatesForEndpoints().executeStep(), executorService)
.thenAccept(() -> new DisplayDetails().executeStep(), executorService)
.thenAcceptAsync(() -> new PlaySounds().executeStep(), executorService);
when all instantiated objects implement the same interface?
Upvotes: 1
Views: 383
Reputation: 20608
Your WorkflowStep
interface is basically equivalent to Runnable
: no input, no output. In the CompletableFuture
API, you should thus use the corresponding runAsync()
and thenRunAsync()
methods:
CompletableFuture<Void> workflowStepCompletableFuture =
CompletableFuture
.runAsync(() -> new GetCoordinatesForEndpoints().executeStep(), executorService)
.thenRunAsync(() -> new DisplayDetails().executeStep(), executorService)
.thenRunAsync(() -> new PlaySounds().executeStep(), executorService);
This will make all of them run asynchronously, but in sequence (as it seems you are trying to do).
Of course you should also remove the Thread
creation from your implementation to make this useful.
Upvotes: 1