Merge pull request #19578 from akka/wip-19440-completionStage-RK

#19440 replace Scala Future usage with CompletionStage in javadsl
This commit is contained in:
Roland Kuhn 2016-01-24 22:14:18 +01:00
commit 6ba20ac673
118 changed files with 1646 additions and 1379 deletions

View file

@ -22,7 +22,9 @@ import akka.http.javadsl.Http;
import scala.util.Try;
import static akka.http.javadsl.ConnectHttp.toHost;
import static akka.pattern.Patterns.*;
import static akka.pattern.PatternsCS.*;
import java.util.concurrent.CompletionStage;
@SuppressWarnings("unused")
public class HttpClientExampleDocTest {
@ -34,9 +36,9 @@ public class HttpClientExampleDocTest {
final ActorSystem system = ActorSystem.create();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final Flow<HttpRequest, HttpResponse, Future<OutgoingConnection>> connectionFlow =
final Flow<HttpRequest, HttpResponse, CompletionStage<OutgoingConnection>> connectionFlow =
Http.get(system).outgoingConnection(toHost("akka.io", 80));
final Future<HttpResponse> responseFuture =
final CompletionStage<HttpResponse> responseFuture =
Source.single(HttpRequest.create("/"))
.via(connectionFlow)
.runWith(Sink.<HttpResponse>head(), materializer);
@ -58,7 +60,7 @@ public class HttpClientExampleDocTest {
// construct a pool client flow with context type `Integer`
final Future<Pair<Try<HttpResponse>, Integer>> responseFuture =
final CompletionStage<Pair<Try<HttpResponse>, Integer>> responseFuture =
Source
.single(Pair.create(HttpRequest.create("/"), 42))
.via(poolClientFlow)
@ -72,7 +74,7 @@ public class HttpClientExampleDocTest {
final ActorSystem system = ActorSystem.create();
final Materializer materializer = ActorMaterializer.create(system);
final Future<HttpResponse> responseFuture =
final CompletionStage<HttpResponse> responseFuture =
Http.get(system)
.singleRequest(HttpRequest.create("http://akka.io"), materializer);
//#single-request-example
@ -92,7 +94,7 @@ public class HttpClientExampleDocTest {
}).build());
}
Future<HttpResponse> fetch(String url) {
CompletionStage<HttpResponse> fetch(String url) {
return http.singleRequest(HttpRequest.create(url), materializer);
}
}

View file

@ -6,32 +6,25 @@ package docs.http.javadsl.server;
//#binding-failure-high-level-example
import akka.actor.ActorSystem;
import akka.dispatch.OnFailure;
import akka.http.javadsl.model.ContentTypes;
import akka.http.javadsl.server.*;
import akka.http.javadsl.server.values.Parameters;
import akka.http.scaladsl.Http;
import scala.concurrent.Future;
import java.io.IOException;
import java.util.concurrent.CompletionStage;
@SuppressWarnings("unchecked")
public class HighLevelServerBindFailureExample {
public static void main(String[] args) throws IOException {
// boot up server using the route as defined below
final ActorSystem system = ActorSystem.create();
// HttpApp.bindRoute expects a route being provided by HttpApp.createRoute
Future<Http.ServerBinding> bindingFuture =
CompletionStage<Http.ServerBinding> bindingFuture =
new HighLevelServerExample().bindRoute("localhost", 8080, system);
bindingFuture.onFailure(new OnFailure() {
@Override
public void onFailure(Throwable failure) throws Throwable {
bindingFuture.exceptionally(failure -> {
System.err.println("Something very bad happened! " + failure.getMessage());
system.terminate();
}
}, system.dispatcher());
return null;
});
system.terminate();
}

View file

@ -13,6 +13,10 @@ import akka.http.javadsl.server.values.BasicCredentials;
import akka.http.javadsl.server.values.HttpBasicAuthenticator;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.scaladsl.model.headers.Authorization;
import java.util.Optional;
import java.util.concurrent.CompletionStage;
import org.junit.Test;
import scala.Option;
import scala.concurrent.Future;
@ -27,7 +31,7 @@ public class HttpBasicAuthenticatorExample extends JUnitRouteTest {
private final String hardcodedPassword = "correcthorsebatterystaple";
public Future<Option<String>> authenticate(BasicCredentials credentials) {
public CompletionStage<Optional<String>> authenticate(BasicCredentials credentials) {
// this is where your actual authentication logic would go
if (credentials.available() && // no anonymous access
credentials.verify(hardcodedPassword)) {

View file

@ -30,13 +30,10 @@ import akka.stream.stage.PushStage;
import akka.stream.stage.SyncDirective;
import akka.stream.stage.TerminationDirective;
import akka.util.ByteString;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.duration.FiniteDuration;
import scala.runtime.BoxedUnit;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
@SuppressWarnings("unused")
@ -47,20 +44,17 @@ public class HttpServerExampleDocTest {
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, Future<ServerBinding>> serverSource =
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind("localhost", 8080, materializer);
Future<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(
new Procedure<IncomingConnection>() {
@Override
public void apply(IncomingConnection connection) throws Exception {
System.out.println("Accepted new connection from " + connection.remoteAddress());
// ... and then actually handle the connection
}
})).run(materializer);
CompletionStage<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(connection -> {
System.out.println("Accepted new connection from " + connection.remoteAddress());
// ... and then actually handle the connection
}
)).run(materializer);
//#binding-example
Await.result(serverBindingFuture, new FiniteDuration(3, TimeUnit.SECONDS));
serverBindingFuture.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
public static void bindingFailureExample() throws Exception {
@ -68,27 +62,21 @@ public class HttpServerExampleDocTest {
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, Future<ServerBinding>> serverSource =
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind("localhost", 80, materializer);
Future<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(
new Procedure<IncomingConnection>() {
@Override
public void apply(IncomingConnection connection) throws Exception {
System.out.println("Accepted new connection from " + connection.remoteAddress());
// ... and then actually handle the connection
}
})).run(materializer);
CompletionStage<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(connection -> {
System.out.println("Accepted new connection from " + connection.remoteAddress());
// ... and then actually handle the connection
}
)).run(materializer);
serverBindingFuture.onFailure(new OnFailure() {
@Override
public void onFailure(Throwable failure) throws Throwable {
serverBindingFuture.whenCompleteAsync((binding, failure) -> {
// possibly report the failure somewhere...
}
}, system.dispatcher());
//#binding-failure-handling
Await.result(serverBindingFuture, new FiniteDuration(3, TimeUnit.SECONDS));
serverBindingFuture.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
public static void connectionSourceFailureExample() throws Exception {
@ -96,7 +84,7 @@ public class HttpServerExampleDocTest {
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, Future<ServerBinding>> serverSource =
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind("localhost", 8080, materializer);
Flow<IncomingConnection, IncomingConnection, NotUsed> failureDetection =
@ -114,19 +102,16 @@ public class HttpServerExampleDocTest {
}
});
Future<ServerBinding> serverBindingFuture =
CompletionStage<ServerBinding> serverBindingFuture =
serverSource
.via(failureDetection) // feed signals through our custom stage
.to(Sink.foreach(
new Procedure<IncomingConnection>() {
@Override
public void apply(IncomingConnection connection) throws Exception {
System.out.println("Accepted new connection from " + connection.remoteAddress());
// ... and then actually handle the connection
}
})).run(materializer);
.to(Sink.foreach(connection -> {
System.out.println("Accepted new connection from " + connection.remoteAddress());
// ... and then actually handle the connection
}))
.run(materializer);
//#incoming-connections-source-failure-handling
Await.result(serverBindingFuture, new FiniteDuration(3, TimeUnit.SECONDS));
serverBindingFuture.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
public static void connectionStreamFailureExample() throws Exception {
@ -134,7 +119,7 @@ public class HttpServerExampleDocTest {
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, Future<ServerBinding>> serverSource =
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind("localhost", 8080, materializer);
Flow<HttpRequest, HttpRequest, NotUsed> failureDetection =
@ -163,14 +148,14 @@ public class HttpServerExampleDocTest {
.withEntity(entity);
});
Future<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(con -> {
System.out.println("Accepted new connection from " + con.remoteAddress());
con.handleWith(httpEcho, materializer);
CompletionStage<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(conn -> {
System.out.println("Accepted new connection from " + conn.remoteAddress());
conn.handleWith(httpEcho, materializer);
}
)).run(materializer);
//#connection-stream-failure-handling
Await.result(serverBindingFuture, new FiniteDuration(3, TimeUnit.SECONDS));
serverBindingFuture.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
public static void fullServerExample() throws Exception {
@ -181,7 +166,7 @@ public class HttpServerExampleDocTest {
//#full-server-example
final Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, Future<ServerBinding>> serverSource =
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind("localhost", 8080, materializer);
//#request-handler
@ -219,21 +204,17 @@ public class HttpServerExampleDocTest {
};
//#request-handler
Future<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(
new Procedure<IncomingConnection>() {
@Override
public void apply(IncomingConnection connection) throws Exception {
System.out.println("Accepted new connection from " + connection.remoteAddress());
CompletionStage<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(connection -> {
System.out.println("Accepted new connection from " + connection.remoteAddress());
connection.handleWithSyncHandler(requestHandler, materializer);
// this is equivalent to
//connection.handleWith(Flow.of(HttpRequest.class).map(requestHandler), materializer);
}
connection.handleWithSyncHandler(requestHandler, materializer);
// this is equivalent to
//connection.handleWith(Flow.of(HttpRequest.class).map(requestHandler), materializer);
})).run(materializer);
//#full-server-example
Await.result(serverBindingFuture, new FiniteDuration(1, TimeUnit.SECONDS)); // will throw if binding fails
serverBindingFuture.toCompletableFuture().get(1, TimeUnit.SECONDS); // will throw if binding fails
System.out.println("Press ENTER to stop.");
new BufferedReader(new InputStreamReader(System.in)).readLine();
} finally {

View file

@ -16,6 +16,10 @@ import akka.http.javadsl.server.values.OAuth2Authenticator;
import akka.http.javadsl.server.values.OAuth2Credentials;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.scaladsl.model.headers.Authorization;
import java.util.Optional;
import java.util.concurrent.CompletionStage;
import org.junit.Test;
import scala.Option;
import scala.concurrent.Future;
@ -31,7 +35,7 @@ public class OAuth2AuthenticatorExample extends JUnitRouteTest {
private final String hardcodedToken = "token";
@Override
public Future<Option<String>> authenticate(OAuth2Credentials credentials) {
public CompletionStage<Optional<String>> authenticate(OAuth2Credentials credentials) {
// this is where your actual authentication logic would go, looking up the user
// based on the token or something in that direction
if (credentials.available() && // no anonymous access

View file

@ -7,6 +7,7 @@ package docs.http.javadsl.server;
//#websocket-example-using-core
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import akka.NotUsed;
@ -50,7 +51,7 @@ public class WebSocketCoreExample {
try {
final Materializer materializer = ActorMaterializer.create(system);
Future<ServerBinding> serverBindingFuture =
CompletionStage<ServerBinding> serverBindingFuture =
Http.get(system).bindAndHandleSync(
new Function<HttpRequest, HttpResponse>() {
public HttpResponse apply(HttpRequest request) throws Exception {
@ -59,7 +60,7 @@ public class WebSocketCoreExample {
}, "localhost", 8080, materializer);
// will throw if binding fails
Await.result(serverBindingFuture, new FiniteDuration(1, TimeUnit.SECONDS));
serverBindingFuture.toCompletableFuture().get(1, TimeUnit.SECONDS);
System.out.println("Press ENTER to stop.");
new BufferedReader(new InputStreamReader(System.in)).readLine();
} finally {

View file

@ -4,7 +4,7 @@
package docs.persistence;
import static akka.pattern.Patterns.ask;
import static akka.pattern.PatternsCS.ask;
import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;
@ -42,6 +42,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
public class PersistenceQueryDocTest {
@ -343,7 +344,7 @@ public class PersistenceQueryDocTest {
//#projection-into-different-store-simple-classes
class ExampleStore {
Future<Void> save(Object any) {
CompletionStage<Void> save(Object any) {
// ...
//#projection-into-different-store-simple-classes
return null;
@ -379,13 +380,13 @@ public class PersistenceQueryDocTest {
this.name = name;
}
public Future<Long> saveProgress(long offset) {
public CompletionStage<Long> saveProgress(long offset) {
// ...
//#projection-into-different-store
return null;
//#projection-into-different-store
}
public Future<Long> latestOffset() {
public CompletionStage<Long> latestOffset() {
// ...
//#projection-into-different-store
return null;
@ -412,17 +413,13 @@ public class PersistenceQueryDocTest {
final Props writerProps = Props.create(TheOneWhoWritesToQueryJournal.class, "bid");
final ActorRef writer = system.actorOf(writerProps, "bid-projection-writer");
long startFromOffset = Await.result(bidProjection.latestOffset(), timeout.duration());
long startFromOffset = bidProjection.latestOffset().toCompletableFuture().get(3, TimeUnit.SECONDS);
readJournal
.eventsByTag("bid", startFromOffset)
.<Long>mapAsync(8, envelope -> {
final Future<Object> f = ask(writer, envelope.event(), timeout);
return f.<Long>map(new Mapper<Object, Long>() {
@Override public Long apply(Object in) {
return envelope.offset();
}
}, system.dispatcher());
.mapAsync(8, envelope -> {
final CompletionStage<Object> f = ask(writer, envelope.event(), timeout);
return f.thenApplyAsync(in -> envelope.offset(), system.dispatcher());
})
.mapAsync(1, offset -> bidProjection.saveProgress(offset))
.runWith(Sink.ignore(), mat);

View file

@ -6,6 +6,7 @@ package docs.stream;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import akka.NotUsed;
@ -221,16 +222,15 @@ public class BidiFlowDocTest {
);
final Flow<Message, Message, NotUsed> flow =
stack.atop(stack.reversed()).join(pingpong);
final Future<List<Message>> result = Source
final CompletionStage<List<Message>> result = Source
.from(Arrays.asList(0, 1, 2))
.<Message> map(id -> new Ping(id))
.via(flow)
.grouped(10)
.runWith(Sink.<List<Message>> head(), mat);
final FiniteDuration oneSec = Duration.create(1, TimeUnit.SECONDS);
assertArrayEquals(
new Message[] { new Pong(0), new Pong(1), new Pong(2) },
Await.result(result, oneSec).toArray(new Message[0]));
result.toCompletableFuture().get(1, TimeUnit.SECONDS).toArray(new Message[0]));
//#compose
}
}

View file

@ -5,6 +5,8 @@ package docs.stream;
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import akka.NotUsed;
import akka.stream.ClosedShape;
@ -215,27 +217,23 @@ public class CompositionDocTest {
//#mat-combine-4a
static class MyClass {
private Promise<Optional<Integer>> p;
private CompletableFuture<Optional<Integer>> p;
private OutgoingConnection conn;
public MyClass(Promise<Optional<Integer>> p, OutgoingConnection conn) {
public MyClass(CompletableFuture<Optional<Integer>> p, OutgoingConnection conn) {
this.p = p;
this.conn = conn;
}
public void close() {
p.success(Optional.empty());
p.complete(Optional.empty());
}
}
static class Combiner {
static Future<MyClass> f(Promise<Optional<Integer>> p,
Pair<Future<OutgoingConnection>, Future<String>> rest) {
return rest.first().map(new Mapper<OutgoingConnection, MyClass>() {
public MyClass apply(OutgoingConnection c) {
return new MyClass(p, c);
}
}, system.dispatcher());
static CompletionStage<MyClass> f(CompletableFuture<Optional<Integer>> p,
Pair<CompletionStage<OutgoingConnection>, CompletionStage<String>> rest) {
return rest.first().thenApply(c -> new MyClass(p, c));
}
}
//#mat-combine-4a
@ -244,13 +242,13 @@ public class CompositionDocTest {
public void materializedValues() throws Exception {
//#mat-combine-1
// Materializes to Promise<BoxedUnit> (red)
final Source<Integer, Promise<Optional<Integer>>> source = Source.<Integer>maybe();
final Source<Integer, CompletableFuture<Optional<Integer>>> source = Source.<Integer>maybe();
// Materializes to BoxedUnit (black)
final Flow<Integer, Integer, NotUsed> flow1 = Flow.of(Integer.class).take(100);
// Materializes to Promise<Option<>> (red)
final Source<Integer, Promise<Optional<Integer>>> nestedSource =
final Source<Integer, CompletableFuture<Optional<Integer>>> nestedSource =
source.viaMat(flow1, Keep.left()).named("nestedSource");
//#mat-combine-1
@ -260,27 +258,27 @@ public class CompositionDocTest {
.map(i -> ByteString.fromString(i.toString()));
// Materializes to Future<OutgoingConnection> (yellow)
final Flow<ByteString, ByteString, Future<OutgoingConnection>> flow3 =
final Flow<ByteString, ByteString, CompletionStage<OutgoingConnection>> flow3 =
Tcp.get(system).outgoingConnection("localhost", 8080);
// Materializes to Future<OutgoingConnection> (yellow)
final Flow<Integer, ByteString, Future<OutgoingConnection>> nestedFlow =
final Flow<Integer, ByteString, CompletionStage<OutgoingConnection>> nestedFlow =
flow2.viaMat(flow3, Keep.right()).named("nestedFlow");
//#mat-combine-2
//#mat-combine-3
// Materializes to Future<String> (green)
final Sink<ByteString, Future<String>> sink = Sink
.fold("", (acc, i) -> acc + i.utf8String());
final Sink<ByteString, CompletionStage<String>> sink =
Sink.<String, ByteString> fold("", (acc, i) -> acc + i.utf8String());
// Materializes to Pair<Future<OutgoingConnection>, Future<String>> (blue)
final Sink<Integer, Pair<Future<OutgoingConnection>, Future<String>>> nestedSink =
final Sink<Integer, Pair<CompletionStage<OutgoingConnection>, CompletionStage<String>>> nestedSink =
nestedFlow.toMat(sink, Keep.both());
//#mat-combine-3
//#mat-combine-4b
// Materializes to Future<MyClass> (purple)
final RunnableGraph<Future<MyClass>> runnableGraph =
final RunnableGraph<CompletionStage<MyClass>> runnableGraph =
nestedSource.toMat(nestedSink, Combiner::f);
//#mat-combine-4b
}

View file

@ -6,6 +6,8 @@ package docs.stream;
import static org.junit.Assert.assertEquals;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@ -55,15 +57,12 @@ public class FlowDocTest {
// returns new Source<Integer>, with `map()` appended
final Source<Integer, NotUsed> zeroes = source.map(x -> 0);
final Sink<Integer, Future<Integer>> fold =
Sink.fold(0, (agg, next) -> agg + next);
final Sink<Integer, CompletionStage<Integer>> fold =
Sink.<Integer, Integer> fold(0, (agg, next) -> agg + next);
zeroes.runWith(fold, mat); // 0
//#source-immutable
int result = Await.result(
zeroes.runWith(fold, mat),
Duration.create(3, TimeUnit.SECONDS)
);
int result = zeroes.runWith(fold, mat).toCompletableFuture().get(3, TimeUnit.SECONDS);
assertEquals(0, result);
}
@ -73,18 +72,18 @@ public class FlowDocTest {
final Source<Integer, NotUsed> source =
Source.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
// note that the Future is scala.concurrent.Future
final Sink<Integer, Future<Integer>> sink =
Sink.fold(0, (aggr, next) -> aggr + next);
final Sink<Integer, CompletionStage<Integer>> sink =
Sink.<Integer, Integer> fold(0, (aggr, next) -> aggr + next);
// connect the Source to the Sink, obtaining a RunnableFlow
final RunnableGraph<Future<Integer>> runnable =
final RunnableGraph<CompletionStage<Integer>> runnable =
source.toMat(sink, Keep.right());
// materialize the flow
final Future<Integer> sum = runnable.run(mat);
final CompletionStage<Integer> sum = runnable.run(mat);
//#materialization-in-steps
int result = Await.result(sum, Duration.create(3, TimeUnit.SECONDS));
int result = sum.toCompletableFuture().get(3, TimeUnit.SECONDS);
assertEquals(55, result);
}
@ -93,14 +92,14 @@ public class FlowDocTest {
//#materialization-runWith
final Source<Integer, NotUsed> source =
Source.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
final Sink<Integer, Future<Integer>> sink =
Sink.fold(0, (aggr, next) -> aggr + next);
final Sink<Integer, CompletionStage<Integer>> sink =
Sink.<Integer, Integer> fold(0, (aggr, next) -> aggr + next);
// materialize the flow, getting the Sinks materialized value
final Future<Integer> sum = source.runWith(sink, mat);
final CompletionStage<Integer> sum = source.runWith(sink, mat);
//#materialization-runWith
int result = Await.result(sum, Duration.create(3, TimeUnit.SECONDS));
int result = sum.toCompletableFuture().get(3, TimeUnit.SECONDS);
assertEquals(55, result);
}
@ -108,21 +107,21 @@ public class FlowDocTest {
public void materializedMapUnique() throws Exception {
//#stream-reuse
// connect the Source to the Sink, obtaining a RunnableGraph
final Sink<Integer, Future<Integer>> sink =
Sink.fold(0, (aggr, next) -> aggr + next);
final RunnableGraph<Future<Integer>> runnable =
final Sink<Integer, CompletionStage<Integer>> sink =
Sink.<Integer, Integer> fold(0, (aggr, next) -> aggr + next);
final RunnableGraph<CompletionStage<Integer>> runnable =
Source.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)).toMat(sink, Keep.right());
// get the materialized value of the FoldSink
final Future<Integer> sum1 = runnable.run(mat);
final Future<Integer> sum2 = runnable.run(mat);
final CompletionStage<Integer> sum1 = runnable.run(mat);
final CompletionStage<Integer> sum2 = runnable.run(mat);
// sum1 and sum2 are different Futures!
//#stream-reuse
int result1 = Await.result(sum1, Duration.create(3, TimeUnit.SECONDS));
int result1 = sum1.toCompletableFuture().get(3, TimeUnit.SECONDS);
assertEquals(55, result1);
int result2 = Await.result(sum2, Duration.create(3, TimeUnit.SECONDS));
int result2 = sum2.toCompletableFuture().get(3, TimeUnit.SECONDS);
assertEquals(55, result2);
}
@ -222,40 +221,40 @@ public class FlowDocTest {
//#flow-mat-combine
// An empty source that can be shut down explicitly from the outside
Source<Integer, Promise<Optional<Integer>>> source = Source.<Integer>maybe();
Source<Integer, CompletableFuture<Optional<Integer>>> source = Source.<Integer>maybe();
// A flow that internally throttles elements to 1/second, and returns a Cancellable
// which can be used to shut down the stream
Flow<Integer, Integer, Cancellable> flow = throttler;
// A sink that returns the first element of a stream in the returned Future
Sink<Integer, Future<Integer>> sink = Sink.head();
Sink<Integer, CompletionStage<Integer>> sink = Sink.head();
// By default, the materialized value of the leftmost stage is preserved
RunnableGraph<Promise<Optional<Integer>>> r1 = source.via(flow).to(sink);
RunnableGraph<CompletableFuture<Optional<Integer>>> r1 = source.via(flow).to(sink);
// Simple selection of materialized values by using Keep.right
RunnableGraph<Cancellable> r2 = source.viaMat(flow, Keep.right()).to(sink);
RunnableGraph<Future<Integer>> r3 = source.via(flow).toMat(sink, Keep.right());
RunnableGraph<CompletionStage<Integer>> r3 = source.via(flow).toMat(sink, Keep.right());
// Using runWith will always give the materialized values of the stages added
// by runWith() itself
Future<Integer> r4 = source.via(flow).runWith(sink, mat);
Promise<Optional<Integer>> r5 = flow.to(sink).runWith(source, mat);
Pair<Promise<Optional<Integer>>, Future<Integer>> r6 = flow.runWith(source, sink, mat);
CompletionStage<Integer> r4 = source.via(flow).runWith(sink, mat);
CompletableFuture<Optional<Integer>> r5 = flow.to(sink).runWith(source, mat);
Pair<CompletableFuture<Optional<Integer>>, CompletionStage<Integer>> r6 = flow.runWith(source, sink, mat);
// Using more complext combinations
RunnableGraph<Pair<Promise<Optional<Integer>>, Cancellable>> r7 =
RunnableGraph<Pair<CompletableFuture<Optional<Integer>>, Cancellable>> r7 =
source.viaMat(flow, Keep.both()).to(sink);
RunnableGraph<Pair<Promise<Optional<Integer>>, Future<Integer>>> r8 =
RunnableGraph<Pair<CompletableFuture<Optional<Integer>>, CompletionStage<Integer>>> r8 =
source.via(flow).toMat(sink, Keep.both());
RunnableGraph<Pair<Pair<Promise<Optional<Integer>>, Cancellable>, Future<Integer>>> r9 =
RunnableGraph<Pair<Pair<CompletableFuture<Optional<Integer>>, Cancellable>, CompletionStage<Integer>>> r9 =
source.viaMat(flow, Keep.both()).toMat(sink, Keep.both());
RunnableGraph<Pair<Cancellable, Future<Integer>>> r10 =
RunnableGraph<Pair<Cancellable, CompletionStage<Integer>>> r10 =
source.viaMat(flow, Keep.right()).toMat(sink, Keep.both());
// It is also possible to map over the materialized values. In r9 we had a
@ -264,9 +263,9 @@ public class FlowDocTest {
RunnableGraph<Cancellable> r11 =
r9.mapMaterializedValue( (nestedTuple) -> {
Promise<Optional<Integer>> p = nestedTuple.first().first();
CompletableFuture<Optional<Integer>> p = nestedTuple.first().first();
Cancellable c = nestedTuple.first().second();
Future<Integer> f = nestedTuple.second();
CompletionStage<Integer> f = nestedTuple.second();
// Picking the Cancellable, but we could also construct a domain class here
return c;

View file

@ -6,6 +6,7 @@ package docs.stream;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import akka.NotUsed;
@ -49,14 +50,14 @@ public class FlowErrorDocTest {
final Materializer mat = ActorMaterializer.create(system);
final Source<Integer, NotUsed> source = Source.from(Arrays.asList(0, 1, 2, 3, 4, 5))
.map(elem -> 100 / elem);
final Sink<Integer, Future<Integer>> fold =
Sink.fold(0, (acc, elem) -> acc + elem);
final Future<Integer> result = source.runWith(fold, mat);
final Sink<Integer, CompletionStage<Integer>> fold =
Sink.<Integer, Integer> fold(0, (acc, elem) -> acc + elem);
final CompletionStage<Integer> result = source.runWith(fold, mat);
// division by zero will fail the stream and the
// result here will be a Future completed with Failure(ArithmeticException)
//#stop
Await.result(result, Duration.create(3, TimeUnit.SECONDS));
result.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
@Test
@ -73,14 +74,14 @@ public class FlowErrorDocTest {
system);
final Source<Integer, NotUsed> source = Source.from(Arrays.asList(0, 1, 2, 3, 4, 5))
.map(elem -> 100 / elem);
final Sink<Integer, Future<Integer>> fold =
final Sink<Integer, CompletionStage<Integer>> fold =
Sink.fold(0, (acc, elem) -> acc + elem);
final Future<Integer> result = source.runWith(fold, mat);
final CompletionStage<Integer> result = source.runWith(fold, mat);
// the element causing division by zero will be dropped
// result here will be a Future completed with Success(228)
//#resume
assertEquals(Integer.valueOf(228), Await.result(result, Duration.create(3, TimeUnit.SECONDS)));
assertEquals(Integer.valueOf(228), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@Test
@ -98,14 +99,14 @@ public class FlowErrorDocTest {
.withAttributes(ActorAttributes.withSupervisionStrategy(decider));
final Source<Integer, NotUsed> source = Source.from(Arrays.asList(0, 1, 2, 3, 4, 5))
.via(flow);
final Sink<Integer, Future<Integer>> fold =
Sink.fold(0, (acc, elem) -> acc + elem);
final Future<Integer> result = source.runWith(fold, mat);
final Sink<Integer, CompletionStage<Integer>> fold =
Sink.<Integer, Integer> fold(0, (acc, elem) -> acc + elem);
final CompletionStage<Integer> result = source.runWith(fold, mat);
// the elements causing division by zero will be dropped
// result here will be a Future completed with Success(150)
//#resume-section
assertEquals(Integer.valueOf(150), Await.result(result, Duration.create(3, TimeUnit.SECONDS)));
assertEquals(Integer.valueOf(150), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@Test
@ -126,7 +127,7 @@ public class FlowErrorDocTest {
.withAttributes(ActorAttributes.withSupervisionStrategy(decider));
final Source<Integer, NotUsed> source = Source.from(Arrays.asList(1, 3, -1, 5, 7))
.via(flow);
final Future<List<Integer>> result = source.grouped(1000)
final CompletionStage<List<Integer>> result = source.grouped(1000)
.runWith(Sink.<List<Integer>>head(), mat);
// the negative element cause the scan stage to be restarted,
// i.e. start from 0 again
@ -135,7 +136,7 @@ public class FlowErrorDocTest {
assertEquals(
Arrays.asList(0, 1, 4, 0, 5, 12),
Await.result(result, Duration.create(3, TimeUnit.SECONDS)));
result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
}

View file

@ -7,6 +7,7 @@ import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import akka.NotUsed;
@ -46,15 +47,15 @@ public class FlowGraphDocTest {
public void demonstrateBuildSimpleGraph() throws Exception {
//#simple-flow-graph
final Source<Integer, NotUsed> in = Source.from(Arrays.asList(1, 2, 3, 4, 5));
final Sink<List<String>, Future<List<String>>> sink = Sink.head();
final Sink<List<Integer>, Future<List<Integer>>> sink2 = Sink.head();
final Sink<List<String>, CompletionStage<List<String>>> sink = Sink.head();
final Sink<List<Integer>, CompletionStage<List<Integer>>> sink2 = Sink.head();
final Flow<Integer, Integer, NotUsed> f1 = Flow.of(Integer.class).map(elem -> elem + 10);
final Flow<Integer, Integer, NotUsed> f2 = Flow.of(Integer.class).map(elem -> elem + 20);
final Flow<Integer, String, NotUsed> f3 = Flow.of(Integer.class).map(elem -> elem.toString());
final Flow<Integer, Integer, NotUsed> f4 = Flow.of(Integer.class).map(elem -> elem + 30);
final RunnableGraph<Future<List<String>>> result =
RunnableGraph.<Future<List<String>>>fromGraph(
final RunnableGraph<CompletionStage<List<String>>> result =
RunnableGraph.<CompletionStage<List<String>>>fromGraph(
GraphDSL
.create(
sink,
@ -70,7 +71,7 @@ public class FlowGraphDocTest {
return ClosedShape.getInstance();
}));
//#simple-flow-graph
final List<String> list = Await.result(result.run(mat), Duration.create(3, TimeUnit.SECONDS));
final List<String> list = result.run(mat).toCompletableFuture().get(3, TimeUnit.SECONDS);
final String[] res = list.toArray(new String[] {});
Arrays.sort(res, null);
assertArrayEquals(new String[] { "31", "32", "33", "34", "35", "41", "42", "43", "44", "45" }, res);
@ -105,12 +106,12 @@ public class FlowGraphDocTest {
@Test
public void demonstrateReusingFlowInGraph() throws Exception {
//#flow-graph-reusing-a-flow
final Sink<Integer, Future<Integer>> topHeadSink = Sink.head();
final Sink<Integer, Future<Integer>> bottomHeadSink = Sink.head();
final Sink<Integer, CompletionStage<Integer>> topHeadSink = Sink.head();
final Sink<Integer, CompletionStage<Integer>> bottomHeadSink = Sink.head();
final Flow<Integer, Integer, NotUsed> sharedDoubler = Flow.of(Integer.class).map(elem -> elem * 2);
final RunnableGraph<Pair<Future<Integer>, Future<Integer>>> g =
RunnableGraph.<Pair<Future<Integer>, Future<Integer>>>fromGraph(
final RunnableGraph<Pair<CompletionStage<Integer>, CompletionStage<Integer>>> g =
RunnableGraph.<Pair<CompletionStage<Integer>, CompletionStage<Integer>>>fromGraph(
GraphDSL.create(
topHeadSink, // import this sink into the graph
bottomHeadSink, // and this as well
@ -127,24 +128,22 @@ public class FlowGraphDocTest {
)
);
//#flow-graph-reusing-a-flow
final Pair<Future<Integer>, Future<Integer>> pair = g.run(mat);
assertEquals(Integer.valueOf(2), Await.result(pair.first(), Duration.create(3, TimeUnit.SECONDS)));
assertEquals(Integer.valueOf(2), Await.result(pair.second(), Duration.create(3, TimeUnit.SECONDS)));
final Pair<CompletionStage<Integer>, CompletionStage<Integer>> pair = g.run(mat);
assertEquals(Integer.valueOf(2), pair.first().toCompletableFuture().get(3, TimeUnit.SECONDS));
assertEquals(Integer.valueOf(2), pair.second().toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@Test
public void demonstrateMatValue() throws Exception {
//#flow-graph-matvalue
final Sink<Integer, Future<Integer>> foldSink = Sink.<Integer, Integer> fold(0, (a, b) -> {
final Sink<Integer, CompletionStage<Integer>> foldSink = Sink.<Integer, Integer> fold(0, (a, b) -> {
return a + b;
});
final Flow<Future<Integer>, Integer, NotUsed> flatten = Flow.<Future<Integer>>create()
.mapAsync(4, x -> {
return x;
});
final Flow<CompletionStage<Integer>, Integer, NotUsed> flatten =
Flow.<CompletionStage<Integer>>create().mapAsync(4, x -> x);
final Flow<Integer, Integer, Future<Integer>> foldingFlow = Flow.fromGraph(
final Flow<Integer, Integer, CompletionStage<Integer>> foldingFlow = Flow.fromGraph(
GraphDSL.create(foldSink,
(b, fold) -> {
return FlowShape.of(
@ -155,7 +154,7 @@ public class FlowGraphDocTest {
//#flow-graph-matvalue-cycle
// This cannot produce any value:
final Source<Integer, Future<Integer>> cyclicSource = Source.fromGraph(
final Source<Integer, CompletionStage<Integer>> cyclicSource = Source.fromGraph(
GraphDSL.create(foldSink,
(b, fold) -> {
// - Fold cannot complete until its upstream mapAsync completes

View file

@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Predicate;
@ -154,11 +155,11 @@ public class FlowStagesDocTest {
@Test
public void demonstrateVariousPushPullStages() throws Exception {
final Sink<Integer, Future<List<Integer>>> sink =
final Sink<Integer, CompletionStage<List<Integer>>> sink =
Flow.of(Integer.class).grouped(10).toMat(Sink.head(), Keep.right());
//#stage-chain
final RunnableGraph<Future<List<Integer>>> runnable =
final RunnableGraph<CompletionStage<List<Integer>>> runnable =
Source
.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
.transform(() -> new Filter<Integer>(elem -> elem % 2 == 0))
@ -168,7 +169,7 @@ public class FlowStagesDocTest {
//#stage-chain
assertEquals(Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5),
Await.result(runnable.run(mat), FiniteDuration.create(3, TimeUnit.SECONDS)));
runnable.run(mat).toCompletableFuture().get(3, TimeUnit.SECONDS));
}
//#detached

View file

@ -31,6 +31,9 @@ import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
@ -101,14 +104,14 @@ public class GraphStageDocTest {
Source<Integer, NotUsed> mySource = Source.fromGraph(sourceGraph);
// Returns 55
Future<Integer> result1 = mySource.take(10).runFold(0, (sum, next) -> sum + next, mat);
CompletionStage<Integer> result1 = mySource.take(10).runFold(0, (sum, next) -> sum + next, mat);
// The source is reusable. This returns 5050
Future<Integer> result2 = mySource.take(100).runFold(0, (sum, next) -> sum + next, mat);
CompletionStage<Integer> result2 = mySource.take(100).runFold(0, (sum, next) -> sum + next, mat);
//#simple-source-usage
assertEquals(Await.result(result1, Duration.create(3, "seconds")), (Integer) 55);
assertEquals(Await.result(result2, Duration.create(3, "seconds")), (Integer) 5050);
assertEquals(result1.toCompletableFuture().get(3, TimeUnit.SECONDS), (Integer) 55);
assertEquals(result2.toCompletableFuture().get(3, TimeUnit.SECONDS), (Integer) 5050);
}
@ -169,12 +172,12 @@ public class GraphStageDocTest {
}
}));
Future<Integer> result =
CompletionStage<Integer> result =
Source.from(Arrays.asList("one", "two", "three"))
.via(stringLength)
.runFold(0, (sum, n) -> sum + n, mat);
assertEquals(new Integer(11), Await.result(result, Duration.create(3, "seconds")));
assertEquals(new Integer(11), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
//#many-to-one
@ -231,12 +234,12 @@ public class GraphStageDocTest {
Graph<FlowShape<Integer, Integer>, NotUsed> evenFilter =
Flow.fromGraph(new Filter<Integer>(n -> n % 2 == 0));
Future<Integer> result =
CompletionStage<Integer> result =
Source.from(Arrays.asList(1, 2, 3, 4, 5, 6))
.via(evenFilter)
.runFold(0, (elem, sum) -> sum + elem, mat);
assertEquals(new Integer(12), Await.result(result, Duration.create(3, "seconds")));
assertEquals(new Integer(12), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
//#one-to-many
@ -300,12 +303,12 @@ public class GraphStageDocTest {
Graph<FlowShape<Integer, Integer>, NotUsed> duplicator =
Flow.fromGraph(new Duplicator<Integer>());
Future<Integer> result =
CompletionStage<Integer> result =
Source.from(Arrays.asList(1, 2, 3))
.via(duplicator)
.runFold(0, (n, sum) -> n + sum, mat);
assertEquals(new Integer(12), Await.result(result, Duration.create(3, "seconds")));
assertEquals(new Integer(12), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@ -357,20 +360,20 @@ public class GraphStageDocTest {
Graph<FlowShape<Integer, Integer>, NotUsed> duplicator =
Flow.fromGraph(new Duplicator2<Integer>());
Future<Integer> result =
CompletionStage<Integer> result =
Source.from(Arrays.asList(1, 2, 3))
.via(duplicator)
.runFold(0, (n, sum) -> n + sum, mat);
assertEquals(new Integer(12), Await.result(result, Duration.create(3, "seconds")));
assertEquals(new Integer(12), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@Test
public void demonstrateChainingOfGraphStages() throws Exception {
Graph<SinkShape<Integer>, Future<String>> sink = Sink.fold("", (acc, n) -> acc + n.toString());
Graph<SinkShape<Integer>, CompletionStage<String>> sink = Sink.fold("", (acc, n) -> acc + n.toString());
//#graph-stage-chain
Future<String> resultFuture = Source.from(Arrays.asList(1,2,3,4,5))
CompletionStage<String> resultFuture = Source.from(Arrays.asList(1,2,3,4,5))
.via(new Filter<Integer>((n) -> n % 2 == 0))
.via(new Duplicator<Integer>())
.via(new Map<Integer, Integer>((n) -> n / 2))
@ -378,7 +381,7 @@ public class GraphStageDocTest {
//#graph-stage-chain
assertEquals("1122", Await.result(resultFuture, Duration.create(3, "seconds")));
assertEquals("1122", resultFuture.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@ -386,9 +389,9 @@ public class GraphStageDocTest {
// will close upstream when the future completes
public class KillSwitch<A> extends GraphStage<FlowShape<A, A>> {
private final Future<Done> switchF;
private final CompletionStage<Done> switchF;
public KillSwitch(Future<Done> switchF) {
public KillSwitch(CompletionStage<Done> switchF) {
this.switchF = switchF;
}
@ -430,12 +433,7 @@ public class GraphStageDocTest {
});
ExecutionContext ec = system.dispatcher();
switchF.onSuccess(new OnSuccess<Done>() {
@Override
public void onSuccess(Done result) throws Throwable {
callback.invoke(Done.getInstance());
}
}, ec);
switchF.thenAccept(callback::invoke);
}
};
}
@ -446,29 +444,23 @@ public class GraphStageDocTest {
public void demonstrateAnAsynchronousSideChannel() throws Exception{
// tests:
Promise<Done> switchF = Futures.promise();
CompletableFuture<Done> switchF = new CompletableFuture<>();
Graph<FlowShape<Integer, Integer>, NotUsed> killSwitch =
Flow.fromGraph(new KillSwitch<>(switchF.future()));
Flow.fromGraph(new KillSwitch<>(switchF));
ExecutionContext ec = system.dispatcher();
// TODO this is probably racey, is there a way to make sure it happens after?
Future<Integer> valueAfterKill = switchF.future().flatMap(new Mapper<Done, Future<Integer>>() {
@Override
public Future<Integer> apply(Done parameter) {
return Futures.successful(4);
}
}, ec);
CompletionStage<Integer> valueAfterKill = switchF.thenApply(in -> 4);
Future<Integer> result =
Source.from(Arrays.asList(1, 2, 3)).concat(Source.fromFuture(valueAfterKill))
CompletionStage<Integer> result =
Source.from(Arrays.asList(1, 2, 3)).concat(Source.fromCompletionStage(valueAfterKill))
.via(killSwitch)
.runFold(0, (n, sum) -> n + sum, mat);
switchF.success(Done.getInstance());
switchF.complete(Done.getInstance());
assertEquals(new Integer(6), Await.result(result, Duration.create(3, "seconds")));
assertEquals(new Integer(6), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@ -531,18 +523,18 @@ public class GraphStageDocTest {
public void demonstrateAGraphStageWithATimer() throws Exception {
// tests:
Future<Integer> result =
CompletionStage<Integer> result =
Source.from(Arrays.asList(1, 2, 3))
.via(new TimedGate<>(Duration.create(2, "seconds")))
.takeWithin(Duration.create(250, "millis"))
.runFold(0, (n, sum) -> n + sum, mat);
assertEquals(new Integer(1), Await.result(result, Duration.create(3, "seconds")));
assertEquals(new Integer(1), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
//#materialized
public class FirstValue<A> extends GraphStageWithMaterializedValue<FlowShape<A, A>, Future<A>> {
public class FirstValue<A> extends GraphStageWithMaterializedValue<FlowShape<A, A>, CompletionStage<A>> {
public final Inlet<A> in = Inlet.create("FirstValue.in");
public final Outlet<A> out = Outlet.create("FirstValue.out");
@ -554,7 +546,7 @@ public class GraphStageDocTest {
}
@Override
public Tuple2<GraphStageLogic, Future<A>> createLogicAndMaterializedValue(Attributes inheritedAttributes) {
public Tuple2<GraphStageLogic, CompletionStage<A>> createLogicAndMaterializedValue(Attributes inheritedAttributes) {
Promise<A> promise = Futures.promise();
GraphStageLogic logic = new GraphStageLogic(shape) {
@ -592,13 +584,13 @@ public class GraphStageDocTest {
public void demonstrateACustomMaterializedValue() throws Exception {
// tests:
RunnableGraph<Future<Integer>> flow = Source.from(Arrays.asList(1, 2, 3))
RunnableGraph<CompletionStage<Integer>> flow = Source.from(Arrays.asList(1, 2, 3))
.viaMat(new FirstValue(), Keep.right())
.to(Sink.ignore());
Future<Integer> result = flow.run(mat);
CompletionStage<Integer> result = flow.run(mat);
assertEquals(new Integer(1), Await.result(result, Duration.create(3, "seconds")));
assertEquals(new Integer(1), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@ -685,11 +677,11 @@ public class GraphStageDocTest {
public void demonstrateADetachedGraphStage() throws Exception {
// tests:
Future<Integer> result1 = Source.from(Arrays.asList(1, 2, 3))
CompletionStage<Integer> result1 = Source.from(Arrays.asList(1, 2, 3))
.via(new TwoBuffer<>())
.runFold(0, (acc, n) -> acc + n, mat);
assertEquals(new Integer(6), Await.result(result1, Duration.create(3, "seconds")));
assertEquals(new Integer(6), result1.toCompletableFuture().get(3, TimeUnit.SECONDS));
TestSubscriber.ManualProbe<Integer> subscriber = TestSubscriber.manualProbe(system);
TestPublisher.Probe<Integer> publisher = TestPublisher.probe(0, system);

View file

@ -6,8 +6,6 @@ package docs.stream;
import akka.NotUsed;
import akka.actor.*;
import akka.dispatch.Futures;
import akka.dispatch.MessageDispatcher;
import akka.japi.pf.ReceiveBuilder;
import akka.stream.*;
import akka.stream.javadsl.*;
@ -21,14 +19,15 @@ import docs.stream.TwitterStreamQuickstartDocTest.Model.Tweet;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import scala.concurrent.ExecutionContext;
import scala.concurrent.Future;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import static akka.pattern.Patterns.ask;
import static akka.pattern.PatternsCS.ask;
import static docs.stream.TwitterStreamQuickstartDocTest.Model.AKKA;
import static docs.stream.TwitterStreamQuickstartDocTest.Model.tweets;
import static junit.framework.TestCase.assertTrue;
@ -64,26 +63,26 @@ public class IntegrationDocTest {
class AddressSystem {
//#email-address-lookup
public Future<Optional<String>> lookupEmail(String handle)
public CompletionStage<Optional<String>> lookupEmail(String handle)
//#email-address-lookup
{
return Futures.successful(Optional.of(handle + "@somewhere.com"));
return CompletableFuture.completedFuture(Optional.of(handle + "@somewhere.com"));
}
//#phone-lookup
public Future<Optional<String>> lookupPhoneNumber(String handle)
public CompletionStage<Optional<String>> lookupPhoneNumber(String handle)
//#phone-lookup
{
return Futures.successful(Optional.of("" + handle.hashCode()));
return CompletableFuture.completedFuture(Optional.of("" + handle.hashCode()));
}
}
class AddressSystem2 {
//#email-address-lookup2
public Future<String> lookupEmail(String handle)
public CompletionStage<String> lookupEmail(String handle)
//#email-address-lookup2
{
return Futures.successful(handle + "@somewhere.com");
return CompletableFuture.completedFuture(handle + "@somewhere.com");
}
}
@ -177,11 +176,11 @@ public class IntegrationDocTest {
}
//#email-server-send
public Future<Email> send(Email email) {
public CompletionStage<Email> send(Email email) {
// ...
//#email-server-send
probe.tell(email.to, ActorRef.noSender());
return Futures.successful(email);
return CompletableFuture.completedFuture(email);
//#email-server-send
}
//#email-server-send
@ -258,21 +257,21 @@ public class IntegrationDocTest {
//#sometimes-slow-service
static class SometimesSlowService {
private final ExecutionContext ec;
public SometimesSlowService(ExecutionContext ec) {
private final Executor ec;
public SometimesSlowService(Executor ec) {
this.ec = ec;
}
private final AtomicInteger runningCount = new AtomicInteger();
public Future<String> convert(String s) {
public CompletionStage<String> convert(String s) {
System.out.println("running: " + s + "(" + runningCount.incrementAndGet() + ")");
return Futures.future(() -> {
return CompletableFuture.supplyAsync(() -> {
if (!s.isEmpty() && Character.isLowerCase(s.charAt(0)))
Thread.sleep(500);
try { Thread.sleep(500); } catch (InterruptedException e) {}
else
Thread.sleep(20);
try { Thread.sleep(20); } catch (InterruptedException e) {}
System.out.println("completed: " + s + "(" + runningCount.decrementAndGet() + ")");
return s.toUpperCase();
}, ec);
@ -399,15 +398,12 @@ public class IntegrationDocTest {
.map(o -> o.get());
//#blocking-mapAsync
final MessageDispatcher blockingEc = system.dispatchers().lookup("blocking-dispatcher");
final Executor blockingEc = system.dispatchers().lookup("blocking-dispatcher");
final RunnableGraph<NotUsed> sendTextMessages =
phoneNumbers
.mapAsync(4, phoneNo ->
Futures.future(() ->
smsServer.send(new TextMessage(phoneNo, "I like your tweet")),
blockingEc)
)
.mapAsync(4, phoneNo -> CompletableFuture.supplyAsync(() ->
smsServer.send(new TextMessage(phoneNo, "I like your tweet")), blockingEc))
.to(Sink.ignore());
sendTextMessages.run(mat);
@ -518,7 +514,7 @@ public class IntegrationDocTest {
{
//#sometimes-slow-mapAsync
final MessageDispatcher blockingEc = system.dispatchers().lookup("blocking-dispatcher");
final Executor blockingEc = system.dispatchers().lookup("blocking-dispatcher");
final SometimesSlowService service = new SometimesSlowService(blockingEc);
final ActorMaterializer mat = ActorMaterializer.create(
@ -563,7 +559,7 @@ public class IntegrationDocTest {
{
//#sometimes-slow-mapAsyncUnordered
final MessageDispatcher blockingEc = system.dispatchers().lookup("blocking-dispatcher");
final Executor blockingEc = system.dispatchers().lookup("blocking-dispatcher");
final SometimesSlowService service = new SometimesSlowService(blockingEc);
final ActorMaterializer mat = ActorMaterializer.create(

View file

@ -7,6 +7,7 @@ package docs.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
@ -72,13 +73,12 @@ public class RateTransformationDocTest {
});
//#conflate-summarize
final Future<List<Tuple3<Double, Double, Integer>>> fut = Source.repeat(0).map(i -> r.nextGaussian())
final CompletionStage<List<Tuple3<Double, Double, Integer>>> fut = Source.repeat(0).map(i -> r.nextGaussian())
.via(statsFlow)
.grouped(10)
.runWith(Sink.head(), mat);
final Duration timeout = Duration.create(100, TimeUnit.MILLISECONDS);
Await.result(fut, timeout);
fut.toCompletableFuture().get(1, TimeUnit.SECONDS);
}
@Test
@ -97,12 +97,11 @@ public class RateTransformationDocTest {
.mapConcat(d -> d);
//#conflate-sample
final Future<Double> fut = Source.from(new ArrayList<Double>(Collections.nCopies(1000, 1.0)))
final CompletionStage<Double> fut = Source.from(new ArrayList<Double>(Collections.nCopies(1000, 1.0)))
.via(sampleFlow)
.runWith(Sink.fold(0.0, (agg, next) -> agg + next), mat);
final Duration timeout = Duration.create(1, TimeUnit.SECONDS);
final Double count = Await.result(fut, timeout);
final Double count = fut.toCompletableFuture().get(1, TimeUnit.SECONDS);
}
@Test
@ -112,17 +111,16 @@ public class RateTransformationDocTest {
.expand(in -> Stream.iterate(in, i -> i).iterator());
//#expand-last
final Pair<TestPublisher.Probe<Double>, Future<List<Double>>> probeFut = TestSource.<Double> probe(system)
final Pair<TestPublisher.Probe<Double>, CompletionStage<List<Double>>> probeFut = TestSource.<Double> probe(system)
.via(lastFlow)
.grouped(10)
.toMat(Sink.head(), Keep.both())
.run(mat);
final TestPublisher.Probe<Double> probe = probeFut.first();
final Future<List<Double>> fut = probeFut.second();
final CompletionStage<List<Double>> fut = probeFut.second();
probe.sendNext(1.0);
final Duration timeout = Duration.create(1, TimeUnit.SECONDS);
final List<Double> expanded = Await.result(fut, timeout);
final List<Double> expanded = fut.toCompletableFuture().get(1, TimeUnit.SECONDS);
assertEquals(expanded.size(), 10);
assertEquals(expanded.stream().mapToDouble(d -> d).sum(), 10, 0.1);
}

View file

@ -6,6 +6,7 @@ package docs.stream;
import static org.junit.Assert.assertEquals;
import java.util.*;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import akka.Done;
@ -58,10 +59,10 @@ public class StreamPartialFlowGraphDocTest {
new Inlet[] {zip1.in0(), zip1.in1(), zip2.in1()});
});
final Sink<Integer, Future<Integer>> resultSink = Sink.<Integer>head();
final Sink<Integer, CompletionStage<Integer>> resultSink = Sink.<Integer>head();
final RunnableGraph<Future<Integer>> g =
RunnableGraph.<Future<Integer>>fromGraph(
final RunnableGraph<CompletionStage<Integer>> g =
RunnableGraph.<CompletionStage<Integer>>fromGraph(
GraphDSL.create(resultSink, (builder, sink) -> {
// import the partial flow graph explicitly
final UniformFanInShape<Integer, Integer> pm = builder.add(pickMaxOfThree);
@ -73,9 +74,9 @@ public class StreamPartialFlowGraphDocTest {
return ClosedShape.getInstance();
}));
final Future<Integer> max = g.run(mat);
final CompletionStage<Integer> max = g.run(mat);
//#simple-partial-flow-graph
assertEquals(Integer.valueOf(3), Await.result(max, Duration.create(3, TimeUnit.SECONDS)));
assertEquals(Integer.valueOf(3), max.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
//#source-from-partial-flow-graph
@ -110,10 +111,10 @@ public class StreamPartialFlowGraphDocTest {
return SourceShape.of(zip.out());
}));
final Future<Pair<Integer, Integer>> firstPair =
final CompletionStage<Pair<Integer, Integer>> firstPair =
pairs.runWith(Sink.<Pair<Integer, Integer>>head(), mat);
//#source-from-partial-flow-graph
assertEquals(new Pair<>(0, 1), Await.result(firstPair, Duration.create(3, TimeUnit.SECONDS)));
assertEquals(new Pair<>(0, 1), firstPair.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@Test
@ -132,12 +133,12 @@ public class StreamPartialFlowGraphDocTest {
}));
//#flow-from-partial-flow-graph
final Future<Pair<Integer, String>> matSink =
final CompletionStage<Pair<Integer, String>> matSink =
//#flow-from-partial-flow-graph
Source.single(1).via(pairs).runWith(Sink.<Pair<Integer, String>>head(), mat);
//#flow-from-partial-flow-graph
assertEquals(new Pair<>(1, "1"), Await.result(matSink, Duration.create(3, TimeUnit.SECONDS)));
assertEquals(new Pair<>(1, "1"), matSink.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@ -150,12 +151,12 @@ public class StreamPartialFlowGraphDocTest {
final Source<Integer, NotUsed> sources = Source.combine(source1, source2, new ArrayList<>(),
i -> Merge.<Integer>create(i));
//#source-combine
final Future<Integer> result=
final CompletionStage<Integer> result=
//#source-combine
sources.runWith(Sink.<Integer, Integer>fold(0, (a,b) -> a + b), mat);
//#source-combine
assertEquals(Integer.valueOf(3), Await.result(result, Duration.create(3, TimeUnit.SECONDS)));
assertEquals(Integer.valueOf(3), result.toCompletableFuture().get(3, TimeUnit.SECONDS));
}
@Test
@ -165,7 +166,7 @@ public class StreamPartialFlowGraphDocTest {
//#sink-combine
Sink<Integer, NotUsed> sendRemotely = Sink.actorRef(actorRef, "Done");
Sink<Integer, Future<Done>> localProcessing = Sink.<Integer>foreach(a -> { /*do something useful*/ } );
Sink<Integer, CompletionStage<Done>> localProcessing = Sink.<Integer>foreach(a -> { /*do something useful*/ } );
Sink<Integer, NotUsed> sinks = Sink.combine(sendRemotely,localProcessing, new ArrayList<>(), a -> Broadcast.create(a));
Source.<Integer>from(Arrays.asList(new Integer[]{0, 1, 2})).runWith(sinks, mat);

View file

@ -6,6 +6,9 @@ package docs.stream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import akka.NotUsed;
@ -13,7 +16,6 @@ import org.junit.*;
import static org.junit.Assert.assertEquals;
import akka.actor.*;
import akka.dispatch.Futures;
import akka.testkit.*;
import akka.japi.Pair;
import akka.stream.*;
@ -23,7 +25,6 @@ import akka.stream.testkit.javadsl.*;
import akka.testkit.TestProbe;
import scala.util.*;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;
@ -48,13 +49,13 @@ public class StreamTestKitDocTest {
@Test
public void strictCollection() throws Exception {
//#strict-collection
final Sink<Integer, Future<Integer>> sinkUnderTest = Flow.of(Integer.class)
final Sink<Integer, CompletionStage<Integer>> sinkUnderTest = Flow.of(Integer.class)
.map(i -> i * 2)
.toMat(Sink.fold(0, (agg, next) -> agg + next), Keep.right());
final Future<Integer> future = Source.from(Arrays.asList(1, 2, 3, 4))
final CompletionStage<Integer> future = Source.from(Arrays.asList(1, 2, 3, 4))
.runWith(sinkUnderTest, mat);
final Integer result = Await.result(future, Duration.create(1, TimeUnit.SECONDS));
final Integer result = future.toCompletableFuture().get(1, TimeUnit.SECONDS);
assert(result == 20);
//#strict-collection
}
@ -65,11 +66,10 @@ public class StreamTestKitDocTest {
final Source<Integer, NotUsed> sourceUnderTest = Source.repeat(1)
.map(i -> i * 2);
final Future<List<Integer>> future = sourceUnderTest
final CompletionStage<List<Integer>> future = sourceUnderTest
.grouped(10)
.runWith(Sink.head(), mat);
final List<Integer> result =
Await.result(future, Duration.create(1, TimeUnit.SECONDS));
final List<Integer> result = future.toCompletableFuture().get(1, TimeUnit.SECONDS);
assertEquals(result, Collections.nCopies(10, 2));
//#grouped-infinite
}
@ -80,9 +80,9 @@ public class StreamTestKitDocTest {
final Flow<Integer, Integer, NotUsed> flowUnderTest = Flow.of(Integer.class)
.takeWhile(i -> i < 5);
final Future<Integer> future = Source.from(Arrays.asList(1, 2, 3, 4, 5, 6))
final CompletionStage<Integer> future = Source.from(Arrays.asList(1, 2, 3, 4, 5, 6))
.via(flowUnderTest).runWith(Sink.fold(0, (agg, next) -> agg + next), mat);
final Integer result = Await.result(future, Duration.create(1, TimeUnit.SECONDS));
final Integer result = future.toCompletableFuture().get(1, TimeUnit.SECONDS);
assert(result == 10);
//#folded-stream
}
@ -95,10 +95,10 @@ public class StreamTestKitDocTest {
.grouped(2);
final TestProbe probe = new TestProbe(system);
final Future<List<List<Integer>>> future = sourceUnderTest
final CompletionStage<List<List<Integer>>> future = sourceUnderTest
.grouped(2)
.runWith(Sink.head(), mat);
akka.pattern.Patterns.pipe(future, system.dispatcher()).to(probe.ref());
akka.pattern.PatternsCS.pipe(future, system.dispatcher()).to(probe.ref());
probe.expectMsg(Duration.create(1, TimeUnit.SECONDS),
Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4))
);
@ -129,23 +129,23 @@ public class StreamTestKitDocTest {
@Test
public void sourceActorRef() throws Exception {
//#source-actorref
final Sink<Integer, Future<String>> sinkUnderTest = Flow.of(Integer.class)
final Sink<Integer, CompletionStage<String>> sinkUnderTest = Flow.of(Integer.class)
.map(i -> i.toString())
.toMat(Sink.fold("", (agg, next) -> agg + next), Keep.right());
final Pair<ActorRef, Future<String>> refAndFuture =
final Pair<ActorRef, CompletionStage<String>> refAndCompletionStage =
Source.<Integer>actorRef(8, OverflowStrategy.fail())
.toMat(sinkUnderTest, Keep.both())
.run(mat);
final ActorRef ref = refAndFuture.first();
final Future<String> future = refAndFuture.second();
final ActorRef ref = refAndCompletionStage.first();
final CompletionStage<String> future = refAndCompletionStage.second();
ref.tell(1, ActorRef.noSender());
ref.tell(2, ActorRef.noSender());
ref.tell(3, ActorRef.noSender());
ref.tell(new akka.actor.Status.Success("done"), ActorRef.noSender());
final String result = Await.result(future, Duration.create(1, TimeUnit.SECONDS));
final String result = future.toCompletableFuture().get(1, TimeUnit.SECONDS);
assertEquals(result, "123");
//#source-actorref
}
@ -180,19 +180,23 @@ public class StreamTestKitDocTest {
@Test
public void injectingFailure() throws Exception {
//#injecting-failure
final Sink<Integer, Future<Integer>> sinkUnderTest = Sink.head();
final Sink<Integer, CompletionStage<Integer>> sinkUnderTest = Sink.head();
final Pair<TestPublisher.Probe<Integer>, Future<Integer>> probeAndFuture =
final Pair<TestPublisher.Probe<Integer>, CompletionStage<Integer>> probeAndCompletionStage =
TestSource.<Integer>probe(system)
.toMat(sinkUnderTest, Keep.both())
.run(mat);
final TestPublisher.Probe<Integer> probe = probeAndFuture.first();
final Future<Integer> future = probeAndFuture.second();
final TestPublisher.Probe<Integer> probe = probeAndCompletionStage.first();
final CompletionStage<Integer> future = probeAndCompletionStage.second();
probe.sendError(new Exception("boom"));
Await.ready(future, Duration.create(1, TimeUnit.SECONDS));
final Throwable exception = ((Failure)future.value().get()).exception();
assertEquals(exception.getMessage(), "boom");
try {
future.toCompletableFuture().get(1, TimeUnit.SECONDS);
assert false;
} catch (ExecutionException ee) {
final Throwable exception = ee.getCause();
assertEquals(exception.getMessage(), "boom");
}
//#injecting-failure
}
@ -200,11 +204,11 @@ public class StreamTestKitDocTest {
public void testSourceAndTestSink() throws Exception {
//#test-source-and-sink
final Flow<Integer, Integer, NotUsed> flowUnderTest = Flow.of(Integer.class)
.mapAsyncUnordered(2, sleep -> akka.pattern.Patterns.after(
.mapAsyncUnordered(2, sleep -> akka.pattern.PatternsCS.after(
Duration.create(10, TimeUnit.MILLISECONDS),
system.scheduler(),
system.dispatcher(),
Futures.successful(sleep)
CompletableFuture.completedFuture(sleep)
));
final Pair<TestPublisher.Probe<Integer>, TestSubscriber.Probe<Integer>> pubAndSub =

View file

@ -26,6 +26,8 @@ import scala.concurrent.duration.FiniteDuration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
@ -199,14 +201,14 @@ public class TwitterStreamQuickstartDocTest {
}
static class Example2 {
public void run(final Materializer mat) throws TimeoutException, InterruptedException {
public void run(final Materializer mat) throws TimeoutException, InterruptedException, ExecutionException {
//#backpressure-by-readline
final Future<?> completion =
final CompletionStage<Done> completion =
Source.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
.map(i -> { System.out.println("map => " + i); return i; })
.runForeach(i -> System.console().readLine("Element = %s continue reading? [press enter]\n", i), mat);
Await.ready(completion, FiniteDuration.create(1, TimeUnit.MINUTES));
completion.toCompletableFuture().get(1, TimeUnit.SECONDS);
//#backpressure-by-readline
}
}
@ -276,8 +278,8 @@ public class TwitterStreamQuickstartDocTest {
@Test
public void demonstrateBroadcast() {
final Sink<Author, Future<Done>> writeAuthors = Sink.ignore();
final Sink<Hashtag, Future<Done>> writeHashtags = Sink.ignore();
final Sink<Author, CompletionStage<Done>> writeAuthors = Sink.ignore();
final Sink<Hashtag, CompletionStage<Done>> writeHashtags = Sink.ignore();
//#flow-graph-broadcast
RunnableGraph.fromGraph(GraphDSL.create(b -> {
@ -317,24 +319,21 @@ public class TwitterStreamQuickstartDocTest {
@Test
public void demonstrateCountOnFiniteStream() {
//#tweets-fold-count
final Sink<Integer, Future<Integer>> sumSink =
final Sink<Integer, CompletionStage<Integer>> sumSink =
Sink.<Integer, Integer>fold(0, (acc, elem) -> acc + elem);
final RunnableGraph<Future<Integer>> counter =
final RunnableGraph<CompletionStage<Integer>> counter =
tweets.map(t -> 1).toMat(sumSink, Keep.right());
final Future<Integer> sum = counter.run(mat);
final CompletionStage<Integer> sum = counter.run(mat);
sum.foreach(new Foreach<Integer>() {
public void each(Integer c) {
System.out.println("Total tweets processed: " + c);
}
}, system.dispatcher());
sum.thenAcceptAsync(c -> System.out.println("Total tweets processed: " + c),
system.dispatcher());
//#tweets-fold-count
new Object() {
//#tweets-fold-count-oneline
final Future<Integer> sum = tweets.map(t -> 1).runWith(sumSink, mat);
final CompletionStage<Integer> sum = tweets.map(t -> 1).runWith(sumSink, mat);
//#tweets-fold-count-oneline
};
}
@ -344,18 +343,18 @@ public class TwitterStreamQuickstartDocTest {
final Source<Tweet, NotUsed> tweetsInMinuteFromNow = tweets; // not really in second, just acting as if
//#tweets-runnable-flow-materialized-twice
final Sink<Integer, Future<Integer>> sumSink =
final Sink<Integer, CompletionStage<Integer>> sumSink =
Sink.<Integer, Integer>fold(0, (acc, elem) -> acc + elem);
final RunnableGraph<Future<Integer>> counterRunnableGraph =
final RunnableGraph<CompletionStage<Integer>> counterRunnableGraph =
tweetsInMinuteFromNow
.filter(t -> t.hashtags().contains(AKKA))
.map(t -> 1)
.toMat(sumSink, Keep.right());
// materialize the stream once in the morning
final Future<Integer> morningTweetsCount = counterRunnableGraph.run(mat);
final CompletionStage<Integer> morningTweetsCount = counterRunnableGraph.run(mat);
// and once in the evening, reusing the blueprint
final Future<Integer> eveningTweetsCount = counterRunnableGraph.run(mat);
final CompletionStage<Integer> eveningTweetsCount = counterRunnableGraph.run(mat);
//#tweets-runnable-flow-materialized-twice
}

View file

@ -3,10 +3,9 @@
*/
package docs.stream.io;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.CompletionStage;
import akka.Done;
import akka.actor.ActorSystem;
@ -15,7 +14,6 @@ import akka.stream.io.IOResult;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.FileIO;
import docs.stream.SilenceSystemOut;
import docs.stream.cookbook.RecipeParseLines;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@ -56,10 +54,10 @@ public class StreamFileDocTest {
try {
//#file-source
Sink<ByteString, Future<Done>> printlnSink =
Sink.foreach(chunk -> System.out.println(chunk.utf8String()));
Sink<ByteString, CompletionStage<Done>> printlnSink =
Sink.<ByteString> foreach(chunk -> System.out.println(chunk.utf8String()));
Future<IOResult> ioResult =
CompletionStage<IOResult> ioResult =
FileIO.fromFile(file)
.to(printlnSink)
.run(mat);
@ -74,7 +72,7 @@ public class StreamFileDocTest {
final File file = File.createTempFile(getClass().getName(), ".tmp");
try {
Sink<ByteString, Future<IOResult>> fileSink =
Sink<ByteString, CompletionStage<IOResult>> fileSink =
//#custom-dispatcher-code
FileIO.toFile(file)
.withAttributes(ActorAttributes.dispatcher("custom-blocking-io-dispatcher"));

View file

@ -3,6 +3,7 @@
*/
package docs.stream.io;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ConcurrentLinkedQueue;
import akka.NotUsed;
@ -60,14 +61,14 @@ public class StreamTcpDocTest {
{
//#echo-server-simple-bind
// IncomingConnection and ServerBinding imported from Tcp
final Source<IncomingConnection, Future<ServerBinding>> connections =
final Source<IncomingConnection, CompletionStage<ServerBinding>> connections =
Tcp.get(system).bind("127.0.0.1", 8889);
//#echo-server-simple-bind
}
{
final InetSocketAddress localhost = SocketUtils.temporaryServerAddress();
final Source<IncomingConnection, Future<ServerBinding>> connections =
final Source<IncomingConnection, CompletionStage<ServerBinding>> connections =
Tcp.get(system).bind(localhost.getHostName(), localhost.getPort()); // TODO getHostString in Java7
//#echo-server-simple-handle
@ -93,7 +94,7 @@ public class StreamTcpDocTest {
final TestProbe serverProbe = new TestProbe(system);
final Source<IncomingConnection,Future<ServerBinding>> connections =
final Source<IncomingConnection,CompletionStage<ServerBinding>> connections =
Tcp.get(system).bind(localhost.getHostName(), localhost.getPort()); // TODO getHostString in Java7
//#welcome-banner-chat-server
connections.runForeach(connection -> {
@ -146,14 +147,14 @@ public class StreamTcpDocTest {
{
//#repl-client
final Flow<ByteString, ByteString, Future<OutgoingConnection>> connection =
final Flow<ByteString, ByteString, CompletionStage<OutgoingConnection>> connection =
Tcp.get(system).outgoingConnection("127.0.0.1", 8889);
//#repl-client
}
{
final Flow<ByteString, ByteString, Future<OutgoingConnection>> connection =
Tcp.get(system).outgoingConnection(localhost.getHostName(), localhost.getPort()); // TODO getHostString in Java7
final Flow<ByteString, ByteString, CompletionStage<OutgoingConnection>> connection =
Tcp.get(system).outgoingConnection(localhost.getHostString(), localhost.getPort());
//#repl-client
final PushStage<String, ByteString> replParser = new PushStage<String, ByteString>() {

View file

@ -20,12 +20,10 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import scala.Tuple2;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.duration.FiniteDuration;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
@ -97,9 +95,9 @@ public class RecipeByteStrings extends RecipeTest {
rawBytes.transform(() -> new Chunker(CHUNK_LIMIT));
//#bytestring-chunker2
Future<List<ByteString>> chunksFuture = chunksStream.grouped(10).runWith(Sink.head(), mat);
CompletionStage<List<ByteString>> chunksFuture = chunksStream.grouped(10).runWith(Sink.head(), mat);
List<ByteString> chunks = Await.result(chunksFuture, FiniteDuration.create(3, TimeUnit.SECONDS));
List<ByteString> chunks = chunksFuture.toCompletableFuture().get(3, TimeUnit.SECONDS);
for (ByteString chunk : chunks) {
assertTrue(chunk.size() <= 2);
@ -159,9 +157,7 @@ public class RecipeByteStrings extends RecipeTest {
ByteString.fromArray(new byte[] { 4, 5, 6 }),
ByteString.fromArray(new byte[] { 7, 8, 9, 10 })));
FiniteDuration threeSeconds = FiniteDuration.create(3, TimeUnit.SECONDS);
List<ByteString> got = Await.result(bytes1.via(limiter).grouped(10).runWith(Sink.head(), mat), threeSeconds);
List<ByteString> got = bytes1.via(limiter).grouped(10).runWith(Sink.head(), mat).toCompletableFuture().get(3, TimeUnit.SECONDS);
ByteString acc = ByteString.empty();
for (ByteString b : got) {
acc = acc.concat(b);
@ -170,7 +166,7 @@ public class RecipeByteStrings extends RecipeTest {
boolean thrown = false;
try {
Await.result(bytes2.via(limiter).grouped(10).runWith(Sink.head(), mat), threeSeconds);
bytes2.via(limiter).grouped(10).runWith(Sink.head(), mat).toCompletableFuture().get(3, TimeUnit.SECONDS);
} catch (IllegalStateException ex) {
thrown = true;
}
@ -194,8 +190,7 @@ public class RecipeByteStrings extends RecipeTest {
Source<ByteString, NotUsed> compacted = rawBytes.map(bs -> bs.compact());
//#compacting-bytestrings
FiniteDuration timeout = FiniteDuration.create(3, TimeUnit.SECONDS);
List<ByteString> got = Await.result(compacted.grouped(10).runWith(Sink.head(), mat), timeout);
List<ByteString> got = compacted.grouped(10).runWith(Sink.head(), mat).toCompletableFuture().get(3, TimeUnit.SECONDS);
for (ByteString byteString : got) {
assertTrue(byteString.isCompact());

View file

@ -18,8 +18,6 @@ import akka.util.ByteString;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -89,7 +87,7 @@ public class RecipeDigest extends RecipeTest {
.transform(() -> digestCalculator("SHA-256"));
//#calculating-digest2
ByteString got = Await.result(digest.runWith(Sink.head(), mat), Duration.create(3, TimeUnit.SECONDS));
ByteString got = digest.runWith(Sink.head(), mat).toCompletableFuture().get(3, TimeUnit.SECONDS);
assertEquals(ByteString.fromInts(
0x24, 0x8d, 0x6a, 0x61,
0xd2, 0x06, 0x38, 0xb8,

View file

@ -16,6 +16,7 @@ import scala.concurrent.Future;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletionStage;
public class RecipeDroppyBroadcast extends RecipeTest {
static ActorSystem system;
@ -38,7 +39,7 @@ public class RecipeDroppyBroadcast extends RecipeTest {
new JavaTestKit(system) {
//#droppy-bcast
// Makes a sink drop elements if too slow
public <T> Sink<T, Future<Done>> droppySink(Sink<T, Future<Done>> sink, int size) {
public <T> Sink<T, CompletionStage<Done>> droppySink(Sink<T, CompletionStage<Done>> sink, int size) {
return Flow.<T> create()
.buffer(size, OverflowStrategy.dropHead())
.toMat(sink, Keep.right());
@ -51,9 +52,9 @@ public class RecipeDroppyBroadcast extends RecipeTest {
nums.add(i + 1);
}
final Sink<Integer, Future<Done>> mySink1 = Sink.ignore();
final Sink<Integer, Future<Done>> mySink2 = Sink.ignore();
final Sink<Integer, Future<Done>> mySink3 = Sink.ignore();
final Sink<Integer, CompletionStage<Done>> mySink1 = Sink.ignore();
final Sink<Integer, CompletionStage<Done>> mySink2 = Sink.ignore();
final Sink<Integer, CompletionStage<Done>> mySink3 = Sink.ignore();
final Source<Integer, NotUsed> myData = Source.from(nums);

View file

@ -13,8 +13,6 @@ import akka.testkit.JavaTestKit;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import scala.concurrent.Await;
import scala.concurrent.duration.FiniteDuration;
import java.util.Arrays;
import java.util.List;
@ -50,8 +48,7 @@ public class RecipeFlattenList extends RecipeTest {
Source<Message, NotUsed> flattened = myData.mapConcat(i -> i);
//#flattening-lists
List<Message> got = Await.result(flattened.grouped(10).runWith(Sink.head(), mat),
new FiniteDuration(1, TimeUnit.SECONDS));
List<Message> got = flattened.grouped(10).runWith(Sink.head(), mat).toCompletableFuture().get(1, TimeUnit.SECONDS);
assertEquals(got.get(0), new Message("1"));
assertEquals(got.get(1), new Message("2"));
assertEquals(got.get(2), new Message("3"));

View file

@ -7,7 +7,7 @@ import akka.NotUsed;
import akka.actor.*;
import akka.dispatch.Mapper;
import akka.japi.pf.ReceiveBuilder;
import akka.pattern.Patterns;
import akka.pattern.PatternsCS;
import akka.stream.*;
import akka.stream.javadsl.*;
import akka.stream.testkit.TestSubscriber;
@ -25,6 +25,7 @@ import scala.runtime.BoxedUnit;
import java.util.*;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import static junit.framework.TestCase.assertTrue;
@ -150,14 +151,9 @@ public class RecipeGlobalRateLimit extends RecipeTest {
return f.mapAsync(parallelism, element -> {
final Timeout triggerTimeout = new Timeout(maxAllowedWait);
final Future<Object> limiterTriggerFuture =
Patterns.ask(limiter, Limiter.WANT_TO_PASS, triggerTimeout);
return limiterTriggerFuture.map(new Mapper<Object, T>() {
@Override
public T apply(Object parameter) {
return element;
}
}, system.dispatcher());
final CompletionStage<Object> limiterTriggerFuture =
PatternsCS.ask(limiter, Limiter.WANT_TO_PASS, triggerTimeout);
return limiterTriggerFuture.thenApplyAsync(response -> element, system.dispatcher());
});
}
//#global-limiter-flow

View file

@ -23,6 +23,7 @@ import scala.concurrent.duration.FiniteDuration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import static java.util.stream.Collectors.toList;
@ -125,7 +126,7 @@ public class RecipeMultiGroupByTest extends RecipeTest {
});
//#multi-groupby
Future<List<String>> result = multiGroups
CompletionStage<List<String>> result = multiGroups
.grouped(10)
.mergeSubstreams()
.map(pair -> {
@ -135,7 +136,7 @@ public class RecipeMultiGroupByTest extends RecipeTest {
.grouped(10)
.runWith(Sink.head(), mat);
List<String> got = Await.result(result, FiniteDuration.create(3, TimeUnit.SECONDS));
List<String> got = result.toCompletableFuture().get(3, TimeUnit.SECONDS);
assertTrue(got.contains("1[1: a, 1: b, all: c, all: d, 1: e]"));
assertTrue(got.contains("2[all: c, all: d]"));
}

View file

@ -15,8 +15,6 @@ import akka.util.ByteString;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import scala.concurrent.Await;
import scala.concurrent.duration.FiniteDuration;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
@ -53,7 +51,7 @@ public class RecipeParseLines extends RecipeTest {
.map(b -> b.utf8String());
//#parse-lines
Await.result(lines.grouped(10).runWith(Sink.head(), mat), new FiniteDuration(1, TimeUnit.SECONDS));
lines.grouped(10).runWith(Sink.head(), mat).toCompletableFuture().get(1, TimeUnit.SECONDS);
}
}

View file

@ -25,6 +25,8 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class RecipeReduceByKeyTest extends RecipeTest {
@ -63,8 +65,8 @@ public class RecipeReduceByKeyTest extends RecipeTest {
.mergeSubstreams();
//#word-count
final Future<List<Pair<String, Integer>>> f = counts.grouped(10).runWith(Sink.head(), mat);
final Set<Pair<String, Integer>> result = Await.result(f, getRemainingTime()).stream().collect(Collectors.toSet());
final CompletionStage<List<Pair<String, Integer>>> f = counts.grouped(10).runWith(Sink.head(), mat);
final Set<Pair<String, Integer>> result = f.toCompletableFuture().get(3, TimeUnit.SECONDS).stream().collect(Collectors.toSet());
final Set<Pair<String, Integer>> expected = new HashSet<>();
expected.add(new Pair<>("hello", 2));
expected.add(new Pair<>("world", 1));
@ -106,8 +108,8 @@ public class RecipeReduceByKeyTest extends RecipeTest {
(left, right) -> left + right));
//#reduce-by-key-general2
final Future<List<Pair<String, Integer>>> f = counts.grouped(10).runWith(Sink.head(), mat);
final Set<Pair<String, Integer>> result = Await.result(f, getRemainingTime()).stream().collect(Collectors.toSet());
final CompletionStage<List<Pair<String, Integer>>> f = counts.grouped(10).runWith(Sink.head(), mat);
final Set<Pair<String, Integer>> result = f.toCompletableFuture().get(3, TimeUnit.SECONDS).stream().collect(Collectors.toSet());
final Set<Pair<String, Integer>> expected = new HashSet<>();
expected.add(new Pair<>("hello", 2));
expected.add(new Pair<>("world", 1));

View file

@ -19,6 +19,7 @@ import scala.concurrent.duration.FiniteDuration;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
public class RecipeToStrict extends RecipeTest {
@ -45,11 +46,11 @@ public class RecipeToStrict extends RecipeTest {
final int MAX_ALLOWED_SIZE = 100;
//#draining-to-list
final Future<List<String>> strings = myData
final CompletionStage<List<String>> strings = myData
.grouped(MAX_ALLOWED_SIZE).runWith(Sink.head(), mat);
//#draining-to-list
Await.result(strings, new FiniteDuration(1, TimeUnit.SECONDS));
strings.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
};
}

View file

@ -17,6 +17,7 @@ import scala.concurrent.duration.FiniteDuration;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertTrue;
@ -72,9 +73,8 @@ public class RecipeWorkerPool extends RecipeTest {
Source<Message, NotUsed> processedJobs = data.via(balancer);
//#worker-pool2
FiniteDuration timeout = FiniteDuration.create(200, TimeUnit.MILLISECONDS);
Future<List<String>> future = processedJobs.map(m -> m.msg).grouped(10).runWith(Sink.head(), mat);
List<String> got = Await.result(future, timeout);
CompletionStage<List<String>> future = processedJobs.map(m -> m.msg).grouped(10).runWith(Sink.head(), mat);
List<String> got = future.toCompletableFuture().get(1, TimeUnit.SECONDS);
assertTrue(got.contains("1 done"));
assertTrue(got.contains("2 done"));
assertTrue(got.contains("3 done"));

View file

@ -137,11 +137,11 @@ re-materialized the respective pool is automatically and transparently restarted
In addition to the automatic shutdown via the configured idle timeouts it's also possible to trigger the immediate
shutdown of a specific pool by calling ``shutdown()`` on the :class:`HostConnectionPool` instance that the pool client
flow materializes into. This ``shutdown()`` call produces a ``Future[Unit]`` which is fulfilled when the pool
flow materializes into. This ``shutdown()`` call produces a ``CompletionStage<Done>`` which is fulfilled when the pool
termination has been completed.
It's also possible to trigger the immediate termination of *all* connection pools in the ``ActorSystem`` at the same
time by calling ``Http.get(system).shutdownAllConnectionPools()``. This call too produces a ``Future[Unit]`` which is fulfilled when
time by calling ``Http.get(system).shutdownAllConnectionPools()``. This call too produces a ``CompletionStage<Done>`` which is fulfilled when
all pools have terminated.

View file

@ -38,7 +38,7 @@ Sometimes your HTTP client needs are very basic. You simply need the HTTP respon
want to bother with setting up a full-blown streaming infrastructure.
For these cases Akka HTTP offers the ``Http().singleRequest(...)`` method, which simply turns an ``HttpRequest`` instance
into ``Future<HttpResponse>``. Internally the request is dispatched across the (cached) host connection pool for the
into ``CompletionStage<HttpResponse>``. Internally the request is dispatched across the (cached) host connection pool for the
request's effective URI.
Just like in the case of the super-pool flow described above the request must have either an absolute URI or a valid
@ -48,7 +48,7 @@ Just like in the case of the super-pool flow described above the request must ha
Using the Future-Based API in Actors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When using the ``Future`` based API from inside an ``Actor``, all the usual caveats apply to how one should deal
When using the ``CompletionStage`` based API from inside an ``Actor``, all the usual caveats apply to how one should deal
with the futures completion. For example you should not access the Actors state from within the Future's callbacks
(such as ``map``, ``onComplete``, ...) and instead you should use the ``pipe`` pattern to pipe the result back
to the Actor as a message:

View file

@ -129,7 +129,7 @@ Entity types ``HttpEntityStrict``, ``HttpEntityDefault``, and ``HttpEntityChunke
which allows to use them for requests and responses. In contrast, ``HttpEntityCloseDelimited`` can only be used for responses.
Streaming entity types (i.e. all but ``HttpEntityStrict``) cannot be shared or serialized. To create a strict, sharable copy of an
entity or message use ``HttpEntity.toStrict`` or ``HttpMessage.toStrict`` which returns a ``Future`` of the object with
entity or message use ``HttpEntity.toStrict`` or ``HttpMessage.toStrict`` which returns a ``CompletionStage`` of the object with
the body data collected into a ``ByteString``.
The class ``HttpEntities`` contains static methods to create entities from common types easily.

View file

@ -104,8 +104,8 @@ Deferring Result Creation
Sometimes a handler cannot directly complete the request but needs to do some processing asynchronously. In this case
the completion of a request needs to be deferred until the result has been generated. This is supported by the routing
DSL in two ways: either you can use one of the ``handleWithAsyncN`` methods passing an ``AsyncHandlerN`` which
returns a ``Future<RouteResult>``, i.e. an eventual ``RouteResult``, or you can also use a regular handler as shown
above and use ``RequestContext.completeWith`` for completion which takes an ``Future<RouteResult>`` as an argument.
returns a ``CompletionStage<RouteResult>``, i.e. an eventual ``RouteResult``, or you can also use a regular handler as shown
above and use ``RequestContext.completeWith`` for completion which takes an ``CompletionStage<RouteResult>`` as an argument.
This is demonstrated in the following example. Consider a asynchronous service defined like this
(making use of Java 8 lambdas):
@ -117,16 +117,17 @@ Here the calculator runs the actual calculation in the background and only event
service should provide a front-end to that service without having to block while waiting for the results. As explained
above this can be done in two ways.
First, you can use ``handleWithAsyncN`` to be able to return a ``Future<RouteResult>``:
First, you can use ``handleWithAsyncN`` to be able to return a ``CompletionStage<RouteResult>``:
.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
:include: async-handler-1
The handler invokes the service and then maps the calculation result to a ``RouteResult`` using ``Future.map`` and
returns the resulting ``Future<RouteResult>``.
The handler invokes the service and then maps the calculation result to a ``RouteResult`` using ``CompletionStage.thenApplyAsync`` and
returns the resulting ``CompletionStage<RouteResult>``. Note that you should always explicitly provide an executor that designates
where the future transformation task is executed, using the JDKs global ForkJoinPool is not recommended.
Otherwise, you can also still use ``handleWithN`` and use ``RequestContext.completeWith`` to "convert" a
``Future<RouteResult>`` into a ``RouteResult`` as shown here:
``CompletionStage<RouteResult>`` into a ``RouteResult`` as shown here:
.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
:include: async-handler-2

View file

@ -88,7 +88,7 @@ Bind failures
^^^^^^^^^^^^^
For example the server might be unable to bind to the given port. For example when the port
is already taken by another application, or if the port is privileged (i.e. only usable by ``root``).
In this case the "binding future" will fail immediatly, and we can react to if by listening on the Future's completion:
In this case the "binding future" will fail immediatly, and we can react to if by listening on the CompletionStage's completion:
.. includecode:: ../../code/docs/http/javadsl/server/HighLevelServerBindFailureExample.java
:include: binding-failure-high-level-example

View file

@ -12,7 +12,7 @@ Http basic auth allows for protection of one or more routes with a username and
To use it you subclass ``HttpBasicAuthenticator`` and provide your authentication logic.
There are two factory methods to create the authentication results to return from the authentication logic:
``authenticateAs(T)`` and ``refuseAccess()``. If the authentication is not very quick in memory, for example
calls a database, make sure you do not block the web server thread by executing that in a separate ``Future``
calls a database, make sure you do not block the web server thread by executing that in a separate ``CompletionStage``
and then ``flatMap`` the result into the authentication result.
When you use the authenticator in your routes you must reference the concrete authenticator twice,

View file

@ -18,7 +18,7 @@ the request can either be refused by returning the return value of ``refuseAcces
with an object that is application specific by returning the return value of ``authenticateAs(T)``.
If the authentication is not very quick in memory, for example calls a separate authentication server
to verify the token, make sure you do not block the web server thread by executing that in a separate ``Future``
to verify the token, make sure you do not block the web server thread by executing that in a separate ``CompletionStage``
and then ``flatMap`` the result into the authentication result.
.. note:: OAuth2 Bearer Token sends the token as clear text and should ONLY EVER be used over

View file

@ -26,7 +26,7 @@ RouteResult
The ``RouteResult`` is an opaque structure that represents possible results of evaluating a route. A ``RouteResult``
can only be created by using one of the methods of the ``RequestContext``. A result can either be a response, if
it was generated by one of the ``completeX`` methods, it can be an eventual result, i.e. a ``Future<RouteResult`` if
it was generated by one of the ``completeX`` methods, it can be an eventual result, i.e. a ``CompletionStage<RouteResult`` if
``completeWith`` was used or a rejection that contains information about why the route could not handle the request.

View file

@ -95,7 +95,7 @@ Requests are handled by calling one of the ``handleWithXXX`` methods with a hand
- a ``Flow<HttpRequest, HttpResponse, ?>`` for ``handleWith``,
- a function ``Function<HttpRequest, HttpResponse>`` for ``handleWithSyncHandler``,
- a function ``Function<HttpRequest, Future<HttpResponse>>`` for ``handleWithAsyncHandler``.
- a function ``Function<HttpRequest, CompletionStage<HttpResponse>>`` for ``handleWithAsyncHandler``.
Here is a complete example:
@ -192,7 +192,7 @@ Bind failures
The first type of failure is when the server is unable to bind to the given port. For example when the port
is already taken by another application, or if the port is privileged (i.e. only usable by ``root``).
In this case the "binding future" will fail immediatly, and we can react to if by listening on the Future's completion:
In this case the "binding future" will fail immediatly, and we can react to if by listening on the CompletionStages completion:
.. includecode:: ../../code/docs/http/javadsl/server/HttpServerExampleDocTest.java
:include: binding-failure-handling

View file

@ -7,6 +7,25 @@ Migration Guide 2.0.x to 2.4.x
General notes
=============
Java DSL now uses Java 8 types: CompletionStage and Optional
------------------------------------------------------------
In order to provide a top-notch Java API we switched from Scalas Future and Akkas
``akka.japi.Option`` interim solutions to the JDKs own types for deferred computation
and optional results. This has been done throughout Streams & HTTP, most notably changing most
materialized types, but also the signature of the ``mapAsync`` combinator and the
asynchronous route result combinators in the HTTP DSL.
The ``akka.pattern`` package has been updated with a new set of implementations within
the ``PatternCS`` class that provide the ability to interact between Actors and Futures
(or streams) for ``CompletionStage``.
Should you have the need to use Scala Futures with these new Java APIs please use
the ``scala-java8-compat`` library that comes as a dependency of Akka. For more
information see `the documentation``_.
.. _`the documentation`:: https://github.com/scala/scala-java8-compat
akka.Done and akka.NotUsed replacing Unit and BoxedUnit
-------------------------------------------------------

View file

@ -253,7 +253,7 @@ type is of the nested module (indicated by the color *red* on the diagram):
.. includecode:: ../code/docs/stream/CompositionDocTest.java#mat-combine-1
Next, we create a composite :class:`Flow` from two smaller components. Here, the second enclosed :class:`Flow` has a
materialized type of :class:`Future<OutgoingConnection>`, and we propagate this to the parent by using ``Keep.right()``
materialized type of :class:`CompletionStage<OutgoingConnection>`, and we propagate this to the parent by using ``Keep.right()``
as the combiner function (indicated by the color *yellow* on the diagram):
.. includecode:: ../code/docs/stream/CompositionDocTest.java#mat-combine-2
@ -267,7 +267,7 @@ we use ``Keep.both()`` to get a :class:`Pair` of them as the materialized type o
As the last example, we wire together ``nestedSource`` and ``nestedSink`` and we use a custom combiner function to
create a yet another materialized type of the resulting :class:`RunnableGraph`. This combiner function just ignores
the :class:`Future<Sink>` part, and wraps the other two values in a custom case class :class:`MyClass`
the :class:`CompletionStage<Sink>` part, and wraps the other two values in a custom case class :class:`MyClass`
(indicated by color *purple* on the diagram):
.. includecode:: ../code/docs/stream/CompositionDocTest.java#mat-combine-4a

View file

@ -60,7 +60,7 @@ In this recipe we will use the ``grouped`` stream operation that groups incoming
size collections (it can be seen as the almost opposite version of the "Flattening a stream of sequences" recipe
we showed before). By using a ``grouped(MAX_ALLOWED_SIZE)`` we create a stream of groups
with maximum size of ``MaxAllowedSeqSize`` and then we take the first element of this stream by attaching a ``Sink.head()``. What we get is a
:class:`Future` containing a sequence with all the elements of the original up to ``MAX_ALLOWED_SIZE`` size (further
:class:`CompletionStage` containing a sequence with all the elements of the original up to ``MAX_ALLOWED_SIZE`` size (further
elements are dropped).
.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeToStrict.java#draining-to-list

View file

@ -67,7 +67,7 @@ Assume that we can lookup their email address using:
.. includecode:: ../code/docs/stream/IntegrationDocTest.java#email-address-lookup2
The ``Future`` is completed with ``Failure`` if the email is not found.
The ``CompletionStage`` is completed normally if the email is not found.
Transforming the stream of authors to a stream of email addresses by using the ``lookupEmail``
service can be done with ``mapAsync`` and we use ``Supervision.getResumingDecider`` to drop
@ -76,4 +76,4 @@ unknown email addresses:
.. includecode:: ../code/docs/stream/IntegrationDocTest.java#email-addresses-mapAsync-supervision
If we would not use ``Resume`` the default stopping strategy would complete the stream
with failure on the first ``Future`` that was completed with ``Failure``.
with failure on the first ``CompletionStage`` that was completed exceptionally.

View file

@ -80,7 +80,7 @@ one actor prepare the work, and then have it be materialized at some completely
After running (materializing) the ``RunnableGraph`` we get a special container object, the ``MaterializedMap``. Both
sources and sinks are able to put specific objects into this map. Whether they put something in or not is implementation
dependent. For example a ``FoldSink`` will make a ``Future`` available in this map which will represent the result
dependent. For example a ``FoldSink`` will make a ``CompletionStage`` available in this map which will represent the result
of the folding process over the stream. In general, a stream can expose multiple materialized values,
but it is quite common to be interested in only the value of the Source or the Sink in the stream. For this reason
there is a convenience method called ``runWith()`` available for ``Sink``, ``Source`` or ``Flow`` requiring, respectively,
@ -105,7 +105,7 @@ of the given sink or source.
Since a stream can be materialized multiple times, the ``MaterializedMap`` returned is different for each materialization.
In the example below we create two running materialized instance of the stream that we described in the ``runnable``
variable, and both materializations give us a different ``Future`` from the map even though we used the same ``sink``
variable, and both materializations give us a different ``CompletionStage`` from the map even though we used the same ``sink``
to refer to the future:
.. includecode:: ../code/docs/stream/FlowDocTest.java#stream-reuse

View file

@ -222,7 +222,7 @@ times to acquire the necessary number of outlets.
.. includecode:: ../code/docs/stream/FlowGraphDocTest.java#flow-graph-matvalue
Be careful not to introduce a cycle where the materialized value actually contributes to the materialized value.
The following example demonstrates a case where the materialized ``Future`` of a fold is fed back to the fold itself.
The following example demonstrates a case where the materialized ``CompletionStage`` of a fold is fed back to the fold itself.
.. includecode:: ../code/docs/stream/FlowGraphDocTest.java#flow-graph-matvalue-cycle

View file

@ -169,7 +169,7 @@ Finally, sending the emails:
.. includecode:: ../code/docs/stream/IntegrationDocTest.java#send-emails
``mapAsync`` is applying the given function that is calling out to the external service to
each of the elements as they pass through this processing step. The function returns a :class:`Future`
each of the elements as they pass through this processing step. The function returns a :class:`CompletionStage`
and the value of that future will be emitted downstreams. The number of Futures
that shall run in parallel is given as the first argument to ``mapAsync``.
These Futures may complete in any order, but the elements that are emitted
@ -190,8 +190,8 @@ is not important and then we can use the more efficient ``mapAsyncUnordered``:
.. includecode:: ../code/docs/stream/IntegrationDocTest.java#external-service-mapAsyncUnordered
In the above example the services conveniently returned a :class:`Future` of the result.
If that is not the case you need to wrap the call in a :class:`Future`. If the service call
In the above example the services conveniently returned a :class:`CompletionStage` of the result.
If that is not the case you need to wrap the call in a :class:`CompletionStage`. If the service call
involves blocking you must also make sure that you run it on a dedicated execution context, to
avoid starvation and disturbance of other tasks in the system.
@ -215,7 +215,7 @@ external service, you can use ``ask``:
.. includecode:: ../code/docs/stream/IntegrationDocTest.java#save-tweets
Note that if the ``ask`` is not completed within the given timeout the stream is completed with failure.
If that is not desired outcome you can use ``recover`` on the ``ask`` :class:`Future`.
If that is not desired outcome you can use ``recover`` on the ``ask`` :class:`CompletionStage`.
Illustrating ordering and parallelism
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -16,7 +16,7 @@ Streaming TCP
Accepting connections: Echo Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In order to implement a simple EchoServer we ``bind`` to a given address, which returns a ``Source<IncomingConnection, Future<ServerBinding>>``,
In order to implement a simple EchoServer we ``bind`` to a given address, which returns a ``Source<IncomingConnection, CompletionStage<ServerBinding>>``,
which will emit an :class:`IncomingConnection` element for each new connection that the Server should handle:
.. includecode:: ../code/docs/stream/io/StreamTcpDocTest.java#echo-server-simple-bind

View file

@ -163,21 +163,21 @@ First, let's write such an element counter using ``Flow.of(Class)`` and ``Sink.f
First we prepare a reusable ``Flow`` that will change each incoming tweet into an integer of value ``1``. We'll use this in
order to combine those with a ``Sink.fold`` that will sum all ``Integer`` elements of the stream and make its result available as
a ``Future<Integer>``. Next we connect the ``tweets`` stream to ``count`` with ``via``. Finally we connect the Flow to the previously
a ``CompletionStage<Integer>``. Next we connect the ``tweets`` stream to ``count`` with ``via``. Finally we connect the Flow to the previously
prepared Sink using ``toMat``.
Remember those mysterious ``Mat`` type parameters on ``Source<Out, Mat>``, ``Flow<In, Out, Mat>`` and ``Sink<In, Mat>``?
They represent the type of values these processing parts return when materialized. When you chain these together,
you can explicitly combine their materialized values: in our example we used the ``Keep.right`` predefined function,
which tells the implementation to only care about the materialized type of the stage currently appended to the right.
The materialized type of ``sumSink`` is ``Future<Integer>`` and because of using ``Keep.right``, the resulting :class:`RunnableGraph`
has also a type parameter of ``Future<Integer>``.
The materialized type of ``sumSink`` is ``CompletionStage<Integer>`` and because of using ``Keep.right``, the resulting :class:`RunnableGraph`
has also a type parameter of ``CompletionStage<Integer>``.
This step does *not* yet materialize the
processing pipeline, it merely prepares the description of the Flow, which is now connected to a Sink, and therefore can
be ``run()``, as indicated by its type: ``RunnableGraph<Future<Integer>>``. Next we call ``run()`` which uses the :class:`ActorMaterializer`
be ``run()``, as indicated by its type: ``RunnableGraph<CompletionStage<Integer>>``. Next we call ``run()`` which uses the :class:`ActorMaterializer`
to materialize and run the Flow. The value returned by calling ``run()`` on a ``RunnableGraph<T>`` is of type ``T``.
In our case this type is ``Future<Integer>`` which, when completed, will contain the total length of our tweets stream.
In our case this type is ``CompletionStage<Integer>`` which, when completed, will contain the total length of our tweets stream.
In case of the stream failing, this future would complete with a Failure.
A :class:`RunnableGraph` may be reused

View file

@ -48,7 +48,7 @@ used for writing stream tests that use familiar :class:`TestProbe` from the
:mod:`akka-testkit` API.
One of the more straightforward tests would be to materialize stream to a
:class:`Future` and then use ``pipe`` pattern to pipe the result of that future
:class:`CompletionStage` and then use ``PatternsCS.pipe`` pattern to pipe the result of that future
to the probe.
.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#pipeto-testprobe