Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to chain Guava futures?

Tags:

java

future

guava

I'm trying to create a small service to accept file upload, unzip it and then delete the uploaded file. Those three steps should be chained as futures. I'm using Google Guava library.

Workflow is:

A future to download the file, if the operation completed, then a future to unzip the file. If unzipping is done, a future to delete the original uploaded file.

But honestly, it isn't clear to me how I would chain the futures, and even how to create them in Guava's way. Documentation is simply terse and unclear. Ok, there is transform method but no concrete example at all. chain method is deprecated.

I miss RxJava library.

like image 503
Chiron Avatar asked Jan 13 '15 11:01

Chiron


1 Answers

Futures.transform is not fluently chainable like RxJava, but you can still use it to set up Futures that depend on one another. Here is a concrete example:

final ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());

final ListenableFuture<FileClass> fileFuture = service.submit(() -> fileDownloader.download())
final ListenableFuture<UnzippedFileClass> unzippedFileFuture = Futures.transform(fileFuture, 
      //need to cast this lambda
      (Function<FileClass, UnzippedFileClass>) file -> fileUnzipper.unzip(file));
final ListenableFuture<Void> deletedFileFuture = Futures.transform(unzippedFileFuture, 
      (Function<UnzippedFileClass, Void>) unzippedFile -> fileDeleter.delete(unzippedFile));
deletedFileFuture.get(); //or however you want to wait for the result

This example assumes fileDownloader.download() returns an instance of FileClass, fileUpzipper.unzip() returns an UnzippedFileClass etc. If FileDownloader.download() instead returns a ListenableFuture<FileClass>, use AsyncFunction instead of Function.

This example also uses Java 8 lambdas for brevity. If you are not using Java 8, pass in anonymous implementations of Function or AsyncFunction instead:

Futures.transform(fileFuture, new AsyncFunction<FileClass, UpzippedFileClass>() {
        @Override
        public ListenableFuture<UnzippedFileClass> apply(final FileClass input) throws Exception {
            return fileUnzipper.unzip();
        }
    });

More info on transform here: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/util/concurrent/Futures.html#transform (scroll or search for "transform" -- deep linking appears to be broken currently)

like image 168
martiansnoop Avatar answered Sep 28 '22 08:09

martiansnoop