2018-10-29 17:19:37 +08:00
|
|
|
/*
|
2019-01-02 18:55:26 +08:00
|
|
|
* Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
|
2011-12-19 11:07:59 +01:00
|
|
|
*/
|
2018-03-13 23:45:55 +09:00
|
|
|
|
2017-03-16 09:30:00 +01:00
|
|
|
package jdocs.future;
|
2011-12-15 22:31:12 +01:00
|
|
|
|
|
|
|
|
//#imports1
|
2012-01-26 14:15:25 +01:00
|
|
|
import akka.dispatch.*;
|
2017-03-16 09:30:00 +01:00
|
|
|
import jdocs.AbstractJavaTest;
|
2012-07-06 17:04:04 +02:00
|
|
|
import scala.concurrent.ExecutionContext;
|
|
|
|
|
import scala.concurrent.Future;
|
2012-06-29 16:40:36 +02:00
|
|
|
import scala.concurrent.Await;
|
2013-05-09 21:48:08 +02:00
|
|
|
import scala.concurrent.Promise;
|
2011-12-15 22:31:12 +01:00
|
|
|
import akka.util.Timeout;
|
2017-07-26 04:09:45 +09:00
|
|
|
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
//#imports1
|
|
|
|
|
|
|
|
|
|
//#imports2
|
2018-08-23 22:43:17 +09:00
|
|
|
import java.time.Duration;
|
2018-03-26 14:56:20 +03:00
|
|
|
import java.util.concurrent.*;
|
|
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
import scala.util.Try;
|
|
|
|
|
|
|
|
|
|
import akka.japi.Function;
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
import static akka.dispatch.Futures.future;
|
|
|
|
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
2017-07-26 04:09:45 +09:00
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
//#imports2
|
|
|
|
|
|
|
|
|
|
//#imports3
|
|
|
|
|
import static akka.dispatch.Futures.sequence;
|
2017-07-26 04:09:45 +09:00
|
|
|
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
//#imports3
|
|
|
|
|
|
|
|
|
|
//#imports4
|
|
|
|
|
import static akka.dispatch.Futures.traverse;
|
2017-07-26 04:09:45 +09:00
|
|
|
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
//#imports4
|
|
|
|
|
|
|
|
|
|
//#imports5
|
|
|
|
|
import akka.japi.Function2;
|
|
|
|
|
import static akka.dispatch.Futures.fold;
|
2017-07-26 04:09:45 +09:00
|
|
|
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
//#imports5
|
|
|
|
|
|
|
|
|
|
//#imports6
|
|
|
|
|
import static akka.dispatch.Futures.reduce;
|
2017-07-26 04:09:45 +09:00
|
|
|
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
//#imports6
|
|
|
|
|
|
2012-02-20 15:43:17 +01:00
|
|
|
//#imports7
|
2012-08-20 19:49:01 +02:00
|
|
|
import static akka.pattern.Patterns.after;
|
2017-07-26 04:09:45 +09:00
|
|
|
|
|
|
|
|
|
2012-11-21 20:33:54 +01:00
|
|
|
import java.util.Arrays;
|
2017-04-24 15:52:14 +02:00
|
|
|
//#imports7
|
2012-08-20 19:49:01 +02:00
|
|
|
|
2018-03-26 14:56:20 +03:00
|
|
|
|
|
|
|
|
//#imports8
|
|
|
|
|
|
2018-12-06 22:40:43 +08:00
|
|
|
import static akka.pattern.Patterns.retry;
|
2018-03-26 14:56:20 +03:00
|
|
|
|
|
|
|
|
//#imports8
|
|
|
|
|
|
2018-07-28 23:52:51 +09:00
|
|
|
//#imports-ask
|
2018-12-06 22:40:43 +08:00
|
|
|
import static akka.pattern.Patterns.ask;
|
2018-07-28 23:52:51 +09:00
|
|
|
//#imports-ask
|
|
|
|
|
//#imports-pipe
|
2018-12-06 22:40:43 +08:00
|
|
|
import static akka.pattern.Patterns.pipe;
|
2018-07-28 23:52:51 +09:00
|
|
|
//#imports-pipe
|
|
|
|
|
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
2016-12-12 21:46:37 +01:00
|
|
|
|
|
|
|
|
import scala.compat.java8.FutureConverters;
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2013-05-02 17:12:36 +02:00
|
|
|
import akka.testkit.AkkaJUnitActorSystemResource;
|
|
|
|
|
import org.junit.ClassRule;
|
2011-12-15 22:31:12 +01:00
|
|
|
import org.junit.Test;
|
|
|
|
|
|
|
|
|
|
import akka.testkit.AkkaSpec;
|
|
|
|
|
import akka.actor.Status.Failure;
|
|
|
|
|
import akka.actor.ActorSystem;
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
import akka.actor.AbstractActor;
|
2011-12-15 22:31:12 +01:00
|
|
|
import akka.actor.ActorRef;
|
|
|
|
|
import akka.actor.Props;
|
2012-01-18 10:18:51 +01:00
|
|
|
import akka.pattern.Patterns;
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2016-12-12 21:46:37 +01:00
|
|
|
import static org.hamcrest.CoreMatchers.is;
|
|
|
|
|
import static org.hamcrest.core.StringContains.containsString;
|
2011-12-15 22:31:12 +01:00
|
|
|
import static org.junit.Assert.*;
|
|
|
|
|
|
2016-02-11 16:39:25 +01:00
|
|
|
public class FutureDocTest extends AbstractJavaTest {
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2013-05-02 17:12:36 +02:00
|
|
|
@ClassRule
|
|
|
|
|
public static AkkaJUnitActorSystemResource actorSystemResource =
|
|
|
|
|
new AkkaJUnitActorSystemResource("FutureDocTest", AkkaSpec.testConf());
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2013-05-02 17:12:36 +02:00
|
|
|
private final ActorSystem system = actorSystemResource.getSystem();
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2012-10-23 15:06:54 +02:00
|
|
|
public final static class PrintResult<T> extends OnSuccess<T> {
|
2013-05-02 17:12:36 +02:00
|
|
|
@Override public final void onSuccess(T t) {
|
|
|
|
|
// print t
|
2012-10-23 15:06:54 +02:00
|
|
|
}
|
2013-05-02 17:12:36 +02:00
|
|
|
}
|
2012-10-23 15:06:54 +02:00
|
|
|
|
|
|
|
|
public final static class Demo {
|
2013-05-02 17:12:36 +02:00
|
|
|
//#print-result
|
|
|
|
|
public final static class PrintResult<T> extends OnSuccess<T> {
|
|
|
|
|
@Override public final void onSuccess(T t) {
|
|
|
|
|
System.out.println(t);
|
2012-10-23 15:06:54 +02:00
|
|
|
}
|
2013-05-02 17:12:36 +02:00
|
|
|
}
|
|
|
|
|
//#print-result
|
2012-10-23 15:06:54 +02:00
|
|
|
}
|
2018-07-28 23:52:51 +09:00
|
|
|
|
|
|
|
|
//#pipe-to-usage
|
|
|
|
|
public class ActorUsingPipeTo extends AbstractActor {
|
|
|
|
|
ActorRef target;
|
2018-12-06 22:40:43 +08:00
|
|
|
Duration timeout;
|
2018-07-28 23:52:51 +09:00
|
|
|
|
|
|
|
|
ActorUsingPipeTo(ActorRef target) {
|
|
|
|
|
this.target = target;
|
2018-12-06 22:40:43 +08:00
|
|
|
this.timeout = Duration.ofSeconds(5);
|
2018-07-28 23:52:51 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Receive createReceive() {
|
|
|
|
|
return receiveBuilder()
|
|
|
|
|
.match(String.class, msg -> {
|
|
|
|
|
CompletableFuture<Object> fut =
|
|
|
|
|
ask(target, "some message", timeout).toCompletableFuture();
|
|
|
|
|
|
|
|
|
|
// the pipe pattern
|
2018-08-23 22:43:17 +09:00
|
|
|
pipe(fut, getContext().dispatcher()).to(getSender());
|
2018-07-28 23:52:51 +09:00
|
|
|
})
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#pipe-to-usage
|
|
|
|
|
|
|
|
|
|
//#pipe-to-returned-data
|
2018-08-23 22:43:17 +09:00
|
|
|
public class UserData {
|
|
|
|
|
final String data;
|
|
|
|
|
|
|
|
|
|
UserData(String data){
|
|
|
|
|
this.data = data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class UserActivity {
|
|
|
|
|
final String activity;
|
|
|
|
|
UserActivity(String activity){
|
|
|
|
|
this.activity = activity;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-28 23:52:51 +09:00
|
|
|
//#pipe-to-returned-data
|
|
|
|
|
|
|
|
|
|
//#pipe-to-user-data-actor
|
|
|
|
|
public class UserDataActor extends AbstractActor {
|
|
|
|
|
UserData internalData;
|
|
|
|
|
|
|
|
|
|
UserDataActor(){
|
|
|
|
|
this.internalData = new UserData("initial data");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Receive createReceive() {
|
|
|
|
|
return receiveBuilder()
|
|
|
|
|
.match(GetFromUserDataActor.class, msg -> sender().tell(internalData, self()))
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class GetFromUserDataActor {}
|
|
|
|
|
//#pipe-to-user-data-actor
|
|
|
|
|
|
|
|
|
|
//#pipe-to-user-activity-actor
|
|
|
|
|
interface UserActivityRepository {
|
|
|
|
|
CompletableFuture<ArrayList<UserActivity>> queryHistoricalActivities(String userId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class UserActivityActor extends AbstractActor {
|
|
|
|
|
String userId;
|
|
|
|
|
UserActivityRepository repository;
|
|
|
|
|
|
|
|
|
|
UserActivityActor(String userId, UserActivityRepository repository) {
|
|
|
|
|
this.userId = userId;
|
|
|
|
|
this.repository = repository;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Receive createReceive() {
|
|
|
|
|
return receiveBuilder()
|
|
|
|
|
.match(GetFromUserActivityActor.class, msg -> {
|
|
|
|
|
CompletableFuture<ArrayList<UserActivity>> fut =
|
|
|
|
|
repository.queryHistoricalActivities(userId);
|
|
|
|
|
|
|
|
|
|
pipe(fut, getContext().dispatcher()).to(sender());
|
|
|
|
|
})
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class GetFromUserActivityActor {}
|
|
|
|
|
//#pipe-to-user-activity-actor
|
|
|
|
|
|
|
|
|
|
//#pipe-to-proxy-actor
|
|
|
|
|
public class UserProxyActor extends AbstractActor {
|
|
|
|
|
ActorRef userActor;
|
|
|
|
|
ActorRef userActivityActor;
|
2018-12-06 22:40:43 +08:00
|
|
|
Duration timeout = Duration.ofSeconds(5);
|
2018-07-28 23:52:51 +09:00
|
|
|
|
|
|
|
|
UserProxyActor(ActorRef userActor, ActorRef userActivityActor) {
|
|
|
|
|
this.userActor = userActor;
|
|
|
|
|
this.userActivityActor = userActivityActor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Receive createReceive() {
|
|
|
|
|
return receiveBuilder()
|
|
|
|
|
.match(GetUserData.class, msg -> {
|
|
|
|
|
CompletableFuture<Object> fut =
|
|
|
|
|
ask(userActor, new GetUserData(), timeout).toCompletableFuture();
|
|
|
|
|
|
|
|
|
|
pipe(fut, getContext().dispatcher());
|
|
|
|
|
})
|
|
|
|
|
.match(GetUserActivities.class, msg -> {
|
|
|
|
|
CompletableFuture<Object> fut =
|
|
|
|
|
ask(userActivityActor, new GetFromUserActivityActor(), timeout).toCompletableFuture();
|
|
|
|
|
|
|
|
|
|
pipe(fut, getContext().dispatcher()).to(sender());
|
|
|
|
|
})
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#pipe-to-proxy-actor
|
|
|
|
|
|
|
|
|
|
//#pipe-to-proxy-messages
|
|
|
|
|
public class GetUserData {}
|
|
|
|
|
public class GetUserActivities {}
|
|
|
|
|
//#pipe-to-proxy-messages
|
|
|
|
|
|
2012-06-29 16:40:36 +02:00
|
|
|
@SuppressWarnings("unchecked") @Test public void useCustomExecutionContext() throws Exception {
|
2013-05-02 17:12:36 +02:00
|
|
|
ExecutorService yourExecutorServiceGoesHere = Executors.newSingleThreadExecutor();
|
|
|
|
|
//#diy-execution-context
|
|
|
|
|
ExecutionContext ec =
|
|
|
|
|
ExecutionContexts.fromExecutorService(yourExecutorServiceGoesHere);
|
2012-02-20 15:43:17 +01:00
|
|
|
|
2013-05-02 17:12:36 +02:00
|
|
|
//Use ec with your Futures
|
|
|
|
|
Future<String> f1 = Futures.successful("foo");
|
2012-02-20 15:43:17 +01:00
|
|
|
|
2013-05-02 17:12:36 +02:00
|
|
|
// Then you shut down the ExecutorService at the end of your application.
|
|
|
|
|
yourExecutorServiceGoesHere.shutdown();
|
|
|
|
|
//#diy-execution-context
|
2012-02-20 15:43:17 +01:00
|
|
|
}
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useBlockingFromActor() throws Exception {
|
2013-04-14 22:56:41 +02:00
|
|
|
ActorRef actor = system.actorOf(Props.create(MyActor.class));
|
2011-12-15 22:31:12 +01:00
|
|
|
String msg = "hello";
|
|
|
|
|
//#ask-blocking
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
2011-12-31 17:42:13 -08:00
|
|
|
Future<Object> future = Patterns.ask(actor, msg, timeout);
|
2011-12-15 22:31:12 +01:00
|
|
|
String result = (String) Await.result(future, timeout.duration());
|
|
|
|
|
//#ask-blocking
|
2018-07-28 23:52:51 +09:00
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
assertEquals("HELLO", result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useFutureEval() throws Exception {
|
2011-12-15 22:31:12 +01:00
|
|
|
//#future-eval
|
|
|
|
|
Future<String> f = future(new Callable<String>() {
|
|
|
|
|
public String call() {
|
|
|
|
|
return "Hello" + "World";
|
|
|
|
|
}
|
|
|
|
|
}, system.dispatcher());
|
2012-10-23 15:06:54 +02:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
f.onComplete(new PrintResult<Try<String>>(), system.dispatcher());
|
2011-12-15 22:31:12 +01:00
|
|
|
//#future-eval
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
String result = (String) Await.result(f, timeout.duration());
|
2013-05-02 17:12:36 +02:00
|
|
|
assertEquals("HelloWorld", result);
|
2011-12-15 22:31:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useMap() throws Exception {
|
2011-12-15 22:31:12 +01:00
|
|
|
//#map
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
Future<String> f1 = future(new Callable<String>() {
|
|
|
|
|
public String call() {
|
|
|
|
|
return "Hello" + "World";
|
|
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2012-01-25 22:36:03 +01:00
|
|
|
Future<Integer> f2 = f1.map(new Mapper<String, Integer>() {
|
2011-12-15 22:31:12 +01:00
|
|
|
public Integer apply(String s) {
|
|
|
|
|
return s.length();
|
|
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
f2.onComplete(new PrintResult<Try<Integer>>(), system.dispatcher());
|
2012-10-23 15:06:54 +02:00
|
|
|
//#map
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
int result = Await.result(f2, timeout.duration());
|
2011-12-15 22:31:12 +01:00
|
|
|
assertEquals(10, result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useFlatMap() throws Exception {
|
2011-12-15 22:31:12 +01:00
|
|
|
//#flat-map
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
Future<String> f1 = future(new Callable<String>() {
|
|
|
|
|
public String call() {
|
|
|
|
|
return "Hello" + "World";
|
|
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2012-01-25 22:36:03 +01:00
|
|
|
Future<Integer> f2 = f1.flatMap(new Mapper<String, Future<Integer>>() {
|
2011-12-15 22:31:12 +01:00
|
|
|
public Future<Integer> apply(final String s) {
|
|
|
|
|
return future(new Callable<Integer>() {
|
|
|
|
|
public Integer call() {
|
|
|
|
|
return s.length();
|
|
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
f2.onComplete(new PrintResult<Try<Integer>>(), system.dispatcher());
|
2011-12-15 22:31:12 +01:00
|
|
|
//#flat-map
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
int result = Await.result(f2, timeout.duration());
|
2011-12-15 22:31:12 +01:00
|
|
|
assertEquals(10, result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useSequence() throws Exception {
|
2011-12-15 22:31:12 +01:00
|
|
|
List<Future<Integer>> source = new ArrayList<Future<Integer>>();
|
2012-07-22 21:40:09 +02:00
|
|
|
source.add(Futures.successful(1));
|
|
|
|
|
source.add(Futures.successful(2));
|
2011-12-15 22:31:12 +01:00
|
|
|
|
|
|
|
|
//#sequence
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
2011-12-15 22:31:12 +01:00
|
|
|
//Some source generating a sequence of Future<Integer>:s
|
|
|
|
|
Iterable<Future<Integer>> listOfFutureInts = source;
|
|
|
|
|
|
|
|
|
|
// now we have a Future[Iterable[Integer]]
|
2012-07-06 17:04:04 +02:00
|
|
|
Future<Iterable<Integer>> futureListOfInts = sequence(listOfFutureInts, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
|
|
|
|
|
// Find the sum of the odd numbers
|
2012-09-26 10:56:25 +02:00
|
|
|
Future<Long> futureSum = futureListOfInts.map(
|
|
|
|
|
new Mapper<Iterable<Integer>, Long>() {
|
|
|
|
|
public Long apply(Iterable<Integer> ints) {
|
|
|
|
|
long sum = 0;
|
|
|
|
|
for (Integer i : ints)
|
|
|
|
|
sum += i;
|
|
|
|
|
return sum;
|
|
|
|
|
}
|
|
|
|
|
}, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
futureSum.onComplete(new PrintResult<Try<Long>>(), system.dispatcher());
|
2011-12-15 22:31:12 +01:00
|
|
|
//#sequence
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
long result = Await.result(futureSum, timeout.duration());
|
2011-12-15 22:31:12 +01:00
|
|
|
assertEquals(3L, result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useTraverse() throws Exception {
|
2011-12-15 22:31:12 +01:00
|
|
|
//#traverse
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
2011-12-15 22:31:12 +01:00
|
|
|
//Just a sequence of Strings
|
|
|
|
|
Iterable<String> listStrings = Arrays.asList("a", "b", "c");
|
|
|
|
|
|
2012-09-26 10:56:25 +02:00
|
|
|
Future<Iterable<String>> futureResult = traverse(listStrings,
|
|
|
|
|
new Function<String, Future<String>>() {
|
|
|
|
|
public Future<String> apply(final String r) {
|
|
|
|
|
return future(new Callable<String>() {
|
|
|
|
|
public String call() {
|
|
|
|
|
return r.toUpperCase();
|
|
|
|
|
}
|
|
|
|
|
}, ec);
|
|
|
|
|
}
|
|
|
|
|
}, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
|
|
|
|
|
//Returns the sequence of strings as upper case
|
2018-11-22 16:18:10 +01:00
|
|
|
futureResult.onComplete(new PrintResult<Try<Iterable<String>>>(), system.dispatcher());
|
2012-10-23 15:06:54 +02:00
|
|
|
//#traverse
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
Iterable<String> result = Await.result(futureResult, timeout.duration());
|
2011-12-15 22:31:12 +01:00
|
|
|
assertEquals(Arrays.asList("A", "B", "C"), result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useFold() throws Exception {
|
2011-12-15 22:31:12 +01:00
|
|
|
List<Future<String>> source = new ArrayList<Future<String>>();
|
2012-07-22 21:40:09 +02:00
|
|
|
source.add(Futures.successful("a"));
|
|
|
|
|
source.add(Futures.successful("b"));
|
2011-12-15 22:31:12 +01:00
|
|
|
//#fold
|
|
|
|
|
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
|
2011-12-15 22:31:12 +01:00
|
|
|
//A sequence of Futures, in this case Strings
|
|
|
|
|
Iterable<Future<String>> futures = source;
|
|
|
|
|
|
|
|
|
|
//Start value is the empty string
|
2012-09-26 10:56:25 +02:00
|
|
|
Future<String> resultFuture = fold("", futures,
|
|
|
|
|
new Function2<String, String, String>() {
|
|
|
|
|
public String apply(String r, String t) {
|
|
|
|
|
return r + t; //Just concatenate
|
|
|
|
|
}
|
|
|
|
|
}, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
resultFuture.onComplete(new PrintResult<Try<String>>(), system.dispatcher());
|
2012-10-23 15:06:54 +02:00
|
|
|
//#fold
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
String result = Await.result(resultFuture, timeout.duration());
|
2011-12-15 22:31:12 +01:00
|
|
|
assertEquals("ab", result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useReduce() throws Exception {
|
2011-12-15 22:31:12 +01:00
|
|
|
List<Future<String>> source = new ArrayList<Future<String>>();
|
2012-07-22 21:40:09 +02:00
|
|
|
source.add(Futures.successful("a"));
|
|
|
|
|
source.add(Futures.successful("b"));
|
2011-12-15 22:31:12 +01:00
|
|
|
//#reduce
|
|
|
|
|
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
2011-12-15 22:31:12 +01:00
|
|
|
//A sequence of Futures, in this case Strings
|
|
|
|
|
Iterable<Future<String>> futures = source;
|
|
|
|
|
|
2012-09-26 10:56:25 +02:00
|
|
|
Future<Object> resultFuture = reduce(futures,
|
|
|
|
|
new Function2<Object, String, Object>() {
|
|
|
|
|
public Object apply(Object r, String t) {
|
|
|
|
|
return r + t; //Just concatenate
|
|
|
|
|
}
|
|
|
|
|
}, ec);
|
2011-12-15 22:31:12 +01:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
resultFuture.onComplete(new PrintResult<Try<Object>>(), system.dispatcher());
|
2011-12-15 22:31:12 +01:00
|
|
|
//#reduce
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
Object result = Await.result(resultFuture, timeout.duration());
|
2011-12-15 22:31:12 +01:00
|
|
|
|
|
|
|
|
assertEquals("ab", result);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 16:02:37 +01:00
|
|
|
@Test
|
2013-05-09 21:48:08 +02:00
|
|
|
public void useSuccessfulAndFailedAndPromise() throws Exception {
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
2012-01-24 16:31:20 +01:00
|
|
|
//#successful
|
2012-07-22 21:40:09 +02:00
|
|
|
Future<String> future = Futures.successful("Yay!");
|
2012-01-24 16:31:20 +01:00
|
|
|
//#successful
|
|
|
|
|
//#failed
|
2012-09-26 10:56:25 +02:00
|
|
|
Future<String> otherFuture = Futures.failed(
|
|
|
|
|
new IllegalArgumentException("Bang!"));
|
2012-01-24 16:31:20 +01:00
|
|
|
//#failed
|
2013-05-09 21:48:08 +02:00
|
|
|
//#promise
|
|
|
|
|
Promise<String> promise = Futures.promise();
|
|
|
|
|
Future<String> theFuture = promise.future();
|
|
|
|
|
promise.success("hello");
|
|
|
|
|
//#promise
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
Object result = Await.result(future, timeout.duration());
|
2012-02-10 16:02:37 +01:00
|
|
|
assertEquals("Yay!", result);
|
2012-09-26 10:56:25 +02:00
|
|
|
Throwable result2 = Await.result(otherFuture.failed(),
|
2018-08-23 22:43:17 +09:00
|
|
|
timeout.duration());
|
2012-02-10 16:02:37 +01:00
|
|
|
assertEquals("Bang!", result2.getMessage());
|
2018-08-23 22:43:17 +09:00
|
|
|
String out = Await.result(theFuture, timeout.duration());
|
2013-05-09 21:48:08 +02:00
|
|
|
assertEquals("hello", out);
|
2012-01-24 16:31:20 +01:00
|
|
|
}
|
|
|
|
|
|
2012-02-10 16:02:37 +01:00
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useFilter() throws Exception {
|
2012-02-10 16:02:37 +01:00
|
|
|
//#filter
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
2012-07-22 21:40:09 +02:00
|
|
|
Future<Integer> future1 = Futures.successful(4);
|
2012-09-26 10:56:25 +02:00
|
|
|
Future<Integer> successfulFilter = future1.filter(Filter.filterOf(
|
|
|
|
|
new Function<Integer, Boolean>() {
|
|
|
|
|
public Boolean apply(Integer i) {
|
|
|
|
|
return i % 2 == 0;
|
|
|
|
|
}
|
|
|
|
|
}), ec);
|
2012-01-24 16:31:20 +01:00
|
|
|
|
2012-09-26 10:56:25 +02:00
|
|
|
Future<Integer> failedFilter = future1.filter(Filter.filterOf(
|
|
|
|
|
new Function<Integer, Boolean>() {
|
|
|
|
|
public Boolean apply(Integer i) {
|
|
|
|
|
return i % 2 != 0;
|
|
|
|
|
}
|
|
|
|
|
}), ec);
|
2012-01-24 16:31:20 +01:00
|
|
|
//When filter fails, the returned Future will be failed with a scala.MatchError
|
|
|
|
|
//#filter
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-31 16:00:46 +01:00
|
|
|
public void sendToTheInternetz(String s) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void sendToIssueTracker(Throwable t) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 16:02:37 +01:00
|
|
|
@Test
|
|
|
|
|
public void useAndThen() {
|
2012-01-31 16:00:46 +01:00
|
|
|
//#and-then
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
2012-09-26 10:56:25 +02:00
|
|
|
Future<String> future1 = Futures.successful("value").andThen(
|
|
|
|
|
new OnComplete<String>() {
|
2012-02-20 15:43:17 +01:00
|
|
|
public void onComplete(Throwable failure, String result) {
|
2012-09-26 10:56:25 +02:00
|
|
|
if (failure != null)
|
|
|
|
|
sendToIssueTracker(failure);
|
2012-02-20 15:43:17 +01:00
|
|
|
}
|
2012-09-26 10:56:25 +02:00
|
|
|
}, ec).andThen(new OnComplete<String>() {
|
2012-02-10 16:02:37 +01:00
|
|
|
public void onComplete(Throwable failure, String result) {
|
|
|
|
|
if (result != null)
|
|
|
|
|
sendToTheInternetz(result);
|
|
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2012-01-31 16:00:46 +01:00
|
|
|
//#and-then
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 16:02:37 +01:00
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useRecover() throws Exception {
|
2012-01-31 16:00:46 +01:00
|
|
|
//#recover
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
|
2012-01-31 16:00:46 +01:00
|
|
|
Future<Integer> future = future(new Callable<Integer>() {
|
|
|
|
|
public Integer call() {
|
|
|
|
|
return 1 / 0;
|
|
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec).recover(new Recover<Integer>() {
|
2012-02-10 16:02:37 +01:00
|
|
|
public Integer recover(Throwable problem) throws Throwable {
|
|
|
|
|
if (problem instanceof ArithmeticException)
|
|
|
|
|
return 0;
|
|
|
|
|
else
|
|
|
|
|
throw problem;
|
|
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2012-10-23 15:06:54 +02:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
future.onComplete(new PrintResult<Try<Integer>>(), system.dispatcher());
|
2012-10-23 15:06:54 +02:00
|
|
|
//#recover
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
int result = Await.result(future, timeout.duration());
|
2012-01-31 16:00:46 +01:00
|
|
|
assertEquals(result, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 16:02:37 +01:00
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useTryRecover() throws Exception {
|
2012-01-31 16:00:46 +01:00
|
|
|
//#try-recover
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
|
2012-01-31 16:00:46 +01:00
|
|
|
Future<Integer> future = future(new Callable<Integer>() {
|
|
|
|
|
public Integer call() {
|
|
|
|
|
return 1 / 0;
|
|
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec).recoverWith(new Recover<Future<Integer>>() {
|
2012-02-10 16:02:37 +01:00
|
|
|
public Future<Integer> recover(Throwable problem) throws Throwable {
|
|
|
|
|
if (problem instanceof ArithmeticException) {
|
|
|
|
|
return future(new Callable<Integer>() {
|
|
|
|
|
public Integer call() {
|
|
|
|
|
return 0;
|
2012-01-31 16:00:46 +01:00
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2012-02-10 16:02:37 +01:00
|
|
|
} else
|
|
|
|
|
throw problem;
|
|
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2012-10-23 15:06:54 +02:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
future.onComplete(new PrintResult<Try<Integer>>(), system.dispatcher());
|
2012-10-23 15:06:54 +02:00
|
|
|
//#try-recover
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
int result = Await.result(future, timeout.duration());
|
2012-01-31 16:00:46 +01:00
|
|
|
assertEquals(result, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 16:02:37 +01:00
|
|
|
@Test
|
2018-11-22 16:18:10 +01:00
|
|
|
public void useOnOnComplete() throws Exception {
|
2012-02-10 16:02:37 +01:00
|
|
|
{
|
2012-07-22 21:40:09 +02:00
|
|
|
Future<String> future = Futures.successful("foo");
|
2012-02-10 08:20:36 +01:00
|
|
|
|
2012-02-10 16:02:37 +01:00
|
|
|
//#onComplete
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
|
2012-02-10 16:02:37 +01:00
|
|
|
future.onComplete(new OnComplete<String>() {
|
2013-05-02 17:12:36 +02:00
|
|
|
public void onComplete(Throwable failure, String result) {
|
|
|
|
|
if (failure != null) {
|
|
|
|
|
//We got a failure, handle it here
|
|
|
|
|
} else {
|
|
|
|
|
// We got a result, do something with it
|
2012-02-10 16:02:37 +01:00
|
|
|
}
|
2013-05-02 17:12:36 +02:00
|
|
|
}
|
2012-07-06 17:04:04 +02:00
|
|
|
}, ec);
|
2012-02-10 16:02:37 +01:00
|
|
|
//#onComplete
|
|
|
|
|
}
|
2012-01-24 16:31:20 +01:00
|
|
|
}
|
|
|
|
|
|
2012-02-10 16:02:37 +01:00
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void useOrAndZip() throws Exception {
|
2012-01-24 16:31:20 +01:00
|
|
|
{
|
2012-02-10 16:02:37 +01:00
|
|
|
//#zip
|
2012-07-06 17:04:04 +02:00
|
|
|
final ExecutionContext ec = system.dispatcher();
|
2012-07-22 21:40:09 +02:00
|
|
|
Future<String> future1 = Futures.successful("foo");
|
|
|
|
|
Future<String> future2 = Futures.successful("bar");
|
2012-09-26 10:56:25 +02:00
|
|
|
Future<String> future3 = future1.zip(future2).map(
|
|
|
|
|
new Mapper<scala.Tuple2<String, String>, String>() {
|
|
|
|
|
public String apply(scala.Tuple2<String, String> zipped) {
|
|
|
|
|
return zipped._1() + " " + zipped._2();
|
|
|
|
|
}
|
|
|
|
|
}, ec);
|
2012-01-24 16:31:20 +01:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
future3.onComplete(new PrintResult<Try<String>>(), system.dispatcher());
|
2012-10-23 15:06:54 +02:00
|
|
|
//#zip
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
String result = Await.result(future3, timeout.duration());
|
2012-02-10 16:02:37 +01:00
|
|
|
assertEquals("foo bar", result);
|
2012-01-24 16:31:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2012-02-10 16:02:37 +01:00
|
|
|
//#fallback-to
|
2012-07-22 21:40:09 +02:00
|
|
|
Future<String> future1 = Futures.failed(new IllegalStateException("OHNOES1"));
|
|
|
|
|
Future<String> future2 = Futures.failed(new IllegalStateException("OHNOES2"));
|
|
|
|
|
Future<String> future3 = Futures.successful("bar");
|
2012-09-26 10:56:25 +02:00
|
|
|
// Will have "bar" in this case
|
|
|
|
|
Future<String> future4 = future1.fallbackTo(future2).fallbackTo(future3);
|
2018-11-22 16:18:10 +01:00
|
|
|
future4.onComplete(new PrintResult<Try<String>>(), system.dispatcher());
|
2012-10-23 15:06:54 +02:00
|
|
|
//#fallback-to
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(5));
|
|
|
|
|
String result = Await.result(future4, timeout.duration());
|
2012-02-10 16:02:37 +01:00
|
|
|
assertEquals("bar", result);
|
2012-01-24 16:31:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-20 19:49:01 +02:00
|
|
|
@Test(expected = IllegalStateException.class)
|
2015-01-30 18:34:03 +01:00
|
|
|
@SuppressWarnings("unchecked")
|
2012-08-20 19:49:01 +02:00
|
|
|
public void useAfter() throws Exception {
|
|
|
|
|
//#after
|
|
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
Future<String> failExc = Futures.failed(new IllegalStateException("OHNOES1"));
|
2018-08-25 09:26:43 +09:00
|
|
|
Timeout delay = Timeout.create(Duration.ofMillis(200));
|
2018-08-23 22:43:17 +09:00
|
|
|
Future<String> delayed = Patterns.after(delay.duration(),
|
2012-08-20 19:49:01 +02:00
|
|
|
system.scheduler(), ec, failExc);
|
|
|
|
|
Future<String> future = future(new Callable<String>() {
|
|
|
|
|
public String call() throws InterruptedException {
|
|
|
|
|
Thread.sleep(1000);
|
|
|
|
|
return "foo";
|
|
|
|
|
}
|
|
|
|
|
}, ec);
|
2013-05-29 17:20:18 +02:00
|
|
|
Future<String> result = Futures.firstCompletedOf(
|
|
|
|
|
Arrays.<Future<String>>asList(future, delayed), ec);
|
2012-08-20 19:49:01 +02:00
|
|
|
//#after
|
2018-08-23 22:43:17 +09:00
|
|
|
Timeout timeout = Timeout.create(Duration.ofSeconds(2));
|
|
|
|
|
Await.result(result, timeout.duration());
|
2012-08-20 19:49:01 +02:00
|
|
|
}
|
|
|
|
|
|
2018-03-26 14:56:20 +03:00
|
|
|
@Test
|
|
|
|
|
public void useRetry() throws Exception {
|
|
|
|
|
|
|
|
|
|
//#retry
|
|
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
Callable<CompletionStage<String>> attempt = () -> CompletableFuture.completedFuture("test");
|
2018-04-11 16:47:36 +02:00
|
|
|
CompletionStage<String> retriedFuture = retry(attempt, 3, java.time.Duration.ofMillis(200), system.scheduler(), ec);
|
2018-03-26 14:56:20 +03:00
|
|
|
//#retry
|
|
|
|
|
|
|
|
|
|
retriedFuture.toCompletableFuture().get(2, SECONDS);
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-12 21:46:37 +01:00
|
|
|
@Test
|
|
|
|
|
public void thenApplyCompletionThread() throws Exception {
|
|
|
|
|
//#apply-completion-thread
|
|
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
|
|
|
|
|
|
|
|
|
Future<String> scalaFuture = Futures.future(() -> {
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("akka.actor.default-dispatcher"));
|
|
|
|
|
countDownLatch.await(); // do not complete yet
|
|
|
|
|
return "hello";
|
|
|
|
|
}, ec);
|
|
|
|
|
|
|
|
|
|
CompletionStage<String> fromScalaFuture = FutureConverters.toJava(scalaFuture)
|
|
|
|
|
.thenApply(s -> { // 1
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("ForkJoinPool.commonPool"));
|
|
|
|
|
return s;
|
|
|
|
|
})
|
|
|
|
|
.thenApply(s -> { // 2
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("ForkJoinPool.commonPool"));
|
|
|
|
|
return s;
|
|
|
|
|
})
|
|
|
|
|
.thenApply(s -> { // 3
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("ForkJoinPool.commonPool"));
|
|
|
|
|
return s;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
countDownLatch.countDown(); // complete scalaFuture
|
|
|
|
|
//#apply-completion-thread
|
|
|
|
|
|
|
|
|
|
fromScalaFuture.toCompletableFuture().get(2, SECONDS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void thenApplyMainThread() throws Exception {
|
|
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
|
|
|
|
|
//#apply-main-thread
|
|
|
|
|
Future<String> scalaFuture = Futures.future(() -> {
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("akka.actor.default-dispatcher"));
|
|
|
|
|
return "hello";
|
|
|
|
|
}, ec);
|
|
|
|
|
|
|
|
|
|
CompletionStage<String> completedStage = FutureConverters.toJava(scalaFuture)
|
|
|
|
|
.thenApply(s -> { // 1
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("ForkJoinPool.commonPool"));
|
|
|
|
|
return s;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
completedStage.toCompletableFuture().get(2, SECONDS); // complete current CompletionStage
|
|
|
|
|
final String currentThread = Thread.currentThread().getName();
|
|
|
|
|
|
|
|
|
|
CompletionStage<String> stage2 = completedStage
|
|
|
|
|
.thenApply(s -> { // 2
|
|
|
|
|
assertThat(Thread.currentThread().getName(), is(currentThread));
|
|
|
|
|
return s;
|
|
|
|
|
})
|
|
|
|
|
.thenApply(s -> { // 3
|
|
|
|
|
assertThat(Thread.currentThread().getName(), is(currentThread));
|
|
|
|
|
return s;
|
|
|
|
|
});
|
|
|
|
|
//#apply-main-thread
|
|
|
|
|
|
|
|
|
|
stage2.toCompletableFuture().get(2, SECONDS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void thenApplyAsyncDefault() throws Exception {
|
|
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
|
|
|
|
|
Future<String> scalaFuture = Futures.future(() -> {
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("akka.actor.default-dispatcher"));
|
|
|
|
|
return "hello";
|
|
|
|
|
}, ec);
|
|
|
|
|
|
|
|
|
|
//#apply-async-default
|
|
|
|
|
CompletionStage<String> fromScalaFuture = FutureConverters.toJava(scalaFuture)
|
|
|
|
|
.thenApplyAsync(s -> { // 1
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("ForkJoinPool.commonPool"));
|
|
|
|
|
return s;
|
|
|
|
|
})
|
|
|
|
|
.thenApplyAsync(s -> { // 2
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("ForkJoinPool.commonPool"));
|
|
|
|
|
return s;
|
|
|
|
|
})
|
|
|
|
|
.thenApplyAsync(s -> { // 3
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("ForkJoinPool.commonPool"));
|
|
|
|
|
return s;
|
|
|
|
|
});
|
|
|
|
|
//#apply-async-default
|
|
|
|
|
|
|
|
|
|
fromScalaFuture.toCompletableFuture().get(2, SECONDS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void thenApplyAsyncExecutor() throws Exception {
|
|
|
|
|
final ExecutionContext ec = system.dispatcher();
|
|
|
|
|
|
|
|
|
|
Future<String> scalaFuture = Futures.future(() -> {
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("akka.actor.default-dispatcher"));
|
|
|
|
|
return "hello";
|
|
|
|
|
}, ec);
|
|
|
|
|
|
|
|
|
|
//#apply-async-executor
|
|
|
|
|
final Executor ex = system.dispatcher();
|
|
|
|
|
|
|
|
|
|
CompletionStage<String> fromScalaFuture = FutureConverters.toJava(scalaFuture)
|
|
|
|
|
.thenApplyAsync(s -> {
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("akka.actor.default-dispatcher"));
|
|
|
|
|
return s;
|
|
|
|
|
}, ex)
|
|
|
|
|
.thenApplyAsync(s -> {
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("akka.actor.default-dispatcher"));
|
|
|
|
|
return s;
|
|
|
|
|
}, ex)
|
|
|
|
|
.thenApplyAsync(s -> {
|
|
|
|
|
assertThat(Thread.currentThread().getName(), containsString("akka.actor.default-dispatcher"));
|
|
|
|
|
return s;
|
|
|
|
|
}, ex);
|
|
|
|
|
//#apply-async-executor
|
|
|
|
|
|
|
|
|
|
fromScalaFuture.toCompletableFuture().get(2, SECONDS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
public static class MyActor extends AbstractActor {
|
|
|
|
|
@Override
|
|
|
|
|
public Receive createReceive() {
|
|
|
|
|
return receiveBuilder()
|
|
|
|
|
.match(String.class, msg -> {
|
2017-03-16 09:30:00 +01:00
|
|
|
getSender().tell(msg.toUpperCase(), getSelf());
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
})
|
|
|
|
|
.match(Integer.class, i -> {
|
|
|
|
|
if (i < 0) {
|
2017-03-16 09:30:00 +01:00
|
|
|
getSender().tell(new Failure(new ArithmeticException("Negative values not supported")), getSelf());
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
} else {
|
2017-03-16 09:30:00 +01:00
|
|
|
getSender().tell(i, getSelf());
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.build();
|
2011-12-15 22:31:12 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|