Quick-n-Dirty
Is it possible to refactor a traditional event listener into a Java 8 Stream, such that listener events become the stream source?
Long Story
A client submits an arbitrary job, then listens for results:
Client client = new JobClient()
client.addTaskListener(this)
client.submitJobAsync( new MultiTaskJob()) //returns void, important (see below)
public void onTaskResult(TaskResult result){
if(result.isLastResult())
aggregateJobResults(result)
else
processResult(result)
}
Problem
For any job submitted, the client receives n results, but it doesn't know how many results it will receive (it uses isLastResult()
to determine when to stop and aggregate).
Goal
I want to refactor the listener into a "supplier", or something similiar, such that onTaskResult()
is the stream source:
Supplier<TaskResult> taskResultSupplier =
() -> Stream.of( .. ) //onTaskResult() feeds this
.map(result -> {
if(result.isLastResult())
//logic here
});
Something like that; if I can do it without the client knowing how many results to expect, I'm golden; right now, submitJobAsync()
returns void, I'd like to keep it that way, but I'm open to options as well...
Alternatives
After reading up on CompletableFutures by Tomasz Nurkiewicz for a similar scenario, an alternate option exists, assuming a minor change to the client:
List<CompletableFuture<TaskResult>> taskFutures =
client.submitJobAsync( new MultiTaskJob())
Here, the client gets a list of CompletableFutures<TaskResult>
, so we need to collect the results of the futures when they complete:
//processes all task result futures
List<TaskResult> = taskFutures.stream()
.map(taskResult ->
taskResult.thenApply(this::processResult))
.collect(Collectors.<TaskResult>toList());
The article also illustrates using CompletableFuture.allOf(..)
to perform final processing but only after all futures complete (it's pretty slick); that's where aggregation would occur in my case. No code to show for that here, though the article does a great job explaining it (I'm a total n00b with streams, though if I get it working I'll post the code:-D )