Useful utils built on top of Guava's ListenableFuture
- Maven Dependencies
- The problem 'wills' solve
- Creation
- Callbacks
- Fallback (Replacing Future in case of failure)
Last stable version:
<dependency>
<groupId>com.github.avarabyeu</groupId>
<artifactId>wills</artifactId>
<version>0.0.2</version>
</dependency>Google did perfect job releasing Guava - set of very useful utilities for collections, I/O, concurrency and others java APIs. Guava's concurrency utilities helps to implement common asynchronous use cases such as adding callbacks, transforming/filtering futures. But, sometimes it looks a bit ridiculous. Just take a look:
ListeningExecutorService executorService = MoreExecutors
.listeningDecorator(Executors.newFixedThreadPool(1));
ListenableFuture<String> future = executorService
.submit(new SomeCallable<String>());
Futures.addCallback(future, new FutureCallback<String>() {
@Override
public void onSuccess(@Nullable String result) {
System.out.println("I'm successful!");
}
@Override
public void onFailure(Throwable t) {
System.out.println("I'm not!");
}
});Too much lines of code, right? Adding callbacks via Futures make sense if you want to add several ones. But what if you need to add just one? This is what 'wills' do for you:
WillExecutorService executorService = WillExecutors
.willDecorator(Executors.newFixedThreadPool(1));
Will<String> future = executorService
.submit(new SomeCallable<String>())
.whenSuccessful(new Action<String>() {
@Override
public void apply(String s) {
System.out.println("I'm OK!");
}
}).whenFailed(new Action<Throwable>() {
@Override
public void apply(Throwable throwable) {
System.out.println("I'm not!");
}
});or even more simple in JDK8 style:
executorService.submit(new SomeCallable<String>())
.whenSuccessful(result -> System.out.println("I'm OK!"))
.whenFailed(throwable -> System.out.println("I'm not!"));Another words, using 'wills' you are able to build chained method calls which makes code cleaner and faster to implement. Actually, com.github.avarabyeu.wills.Will interface extends Guava's ListanableFuture with some useful convenience methods. Go through documentation to find out them explanation.
Future<String> future = ...;
Will<String> will = Wills.forFuture(future);ListenableFuture<String> future = ...;
Will<String> will = Wills.forListenableFuture(future);This is most simple way to work with 'wills':
WillExecutorService executorService = WillExecutors.willDecorator(Executors.newFixedThreadPool(10));
Will<String> will = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "Hello world!";
}
});Executes some action once Future is done.
Example:
Will<String> will = Wills.of("SOME RESULT")
.whenSuccessful(new Action<String>() {
@Override
public void apply(String o) {
doSomething():
}
});Example (JDK8):
Wills.of("SOME RESULT").whenSuccessful(result -> doSomething());Guava's analogue:
ListenableFuture<?> future = Futures.immediateFuture("SOME RESULT")
A05D
;
Futures.addCallback(future, new FutureCallback<Object>() {
@Override
public void onSuccess(@Nullable Object result) {
doSomething();
}
@Override
public void onFailure(Throwable t) {
//do nothing
}
});Executes some action in case Future is failed
Example:
Will<String> will = Wills.of("SOME RESULT")
.whenFailed(new Action<String>() {
@Override
public void apply(String o) {
doSomething():
}
});Example (JDK8):
Wills.of("SOME RESULT").whenFailed(result -> doSomething());Guava's analogue:
ListenableFuture<?> future = Futures.immediateFuture("SOME RESULT");
Futures.addCallback(future, new FutureCallback<Object>() {
@Override
public void onSuccess(@Nullable Object result) {
//do nothing
}
@Override
public void onFailure(Throwable t) {
doSomething();
}
});Executes some action once Future is completed. Doesn't matter successful or not. Here action is boolean-type, because there will be passed execution result (TRUE in case if future execution is successful)
Example:
Will<String> will = Wills.of("SOME RESULT")
.whenDone(new Action<Boolean>() {
@Override
public void apply(Boolean successful) {
doSomething():
}
});Example (JDK8):
Wills.of("SOME RESULT").whenDone(successful -> doSomething());Guava's analogue: There is no direct analogue. You can only can add the following callback:
new FutureCallback<A>() {
@Override
public void onSuccess(@Nullable A result) {
action.apply(true);
}
@Override
public void onFailure(Throwable t) {
action.apply(false);
}
});Sometimes you need something like default value for you Future. Guava's fallbacks mechanism is a good solution for such cases:
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "Hello world!";
}
});
future = Futures.withFallback(future, new FutureFallback<String>() {
@Override
public ListenableFuture<String> create(Throwable t) throws Exception {
return Futures.immediateFuture("NO RESULTS!");
}
});Here is more simple version in Wills style:
WillExecutorService executorService = WillExecutors.willDecorator(Executors.newFixedThreadPool(10));
Will<String> will = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "Hello world!";
}
}).replaceFailed(Wills.of("NO RESULTS!")); if you wanna get access to future's exception, you still may use Guava's FutureFallback:
will = will.replaceFailed(new FutureFallback<String>() {
@Override
public ListenableFuture<String> create(Throwable t) throws Exception {
return Wills.of("NO RESULTS!");
}
});