@Test public void reusingComponents() throws Exception { final Source<Integer, NotUsed> nestedSource = Source.single(0) // An atomic source .map(i -> i + 1) // an atomic processing stage .named("nestedSource"); // wraps up the current Source and gives it a name final Flow<Integer, Integer, NotUsed> nestedFlow = Flow.of(Integer.class) .filter(i -> i != 0) // an atomic processing stage .map(i -> i - 2) // another atomic processing stage .named("nestedFlow"); // wraps up the Flow, and gives it a name final Sink<Integer, NotUsed> nestedSink = nestedFlow .to(Sink.fold(0, (acc, i) -> acc + i)) // wire an atomic sink to the nestedFlow .named("nestedSink"); // wrap it up // #reuse // Create a RunnableGraph from our components final RunnableGraph<NotUsed> runnableGraph = nestedSource.to(nestedSink); // Usage is uniform, no matter if modules are composite or atomic final RunnableGraph<NotUsed> runnableGraph2 = Source.single(0).to(Sink.fold(0, (acc, i) -> acc + i)); // #reuse }
@Test public void parseLines() throws Exception { final Source<ByteString, NotUsed> compressed = Source.single(gzip("Hello World")); // #decompress-gzip final Source<String, NotUsed> uncompressed = compressed.via(Compression.gunzip(100)).map(b -> b.utf8String()); // #decompress-gzip uncompressed.runWith(Sink.head(), mat).toCompletableFuture().get(1, TimeUnit.SECONDS); }
@Test public void complexGraph() throws Exception { // #complex-graph RunnableGraph.fromGraph( GraphDSL.create( builder -> { final Outlet<Integer> A = builder.add(Source.single(0)).out(); final UniformFanOutShape<Integer, Integer> B = builder.add(Broadcast.create(2)); final UniformFanInShape<Integer, Integer> C = builder.add(Merge.create(2)); final FlowShape<Integer, Integer> D = builder.add(Flow.of(Integer.class).map(i -> i + 1)); final UniformFanOutShape<Integer, Integer> E = builder.add(Balance.create(2)); final UniformFanInShape<Integer, Integer> F = builder.add(Merge.create(2)); final Inlet<Integer> G = builder.add(Sink.<Integer>foreach(System.out::println)).in(); builder.from(F).toFanIn(C); builder.from(A).viaFanOut(B).viaFanIn(C).toFanIn(F); builder.from(B).via(D).viaFanOut(E).toFanIn(F); builder.from(E).toInlet(G); return ClosedShape.getInstance(); })); // #complex-graph // #complex-graph-alt RunnableGraph.fromGraph( GraphDSL.create( builder -> { final SourceShape<Integer> A = builder.add(Source.single(0)); final UniformFanOutShape<Integer, Integer> B = builder.add(Broadcast.create(2)); final UniformFanInShape<Integer, Integer> C = builder.add(Merge.create(2)); final FlowShape<Integer, Integer> D = builder.add(Flow.of(Integer.class).map(i -> i + 1)); final UniformFanOutShape<Integer, Integer> E = builder.add(Balance.create(2)); final UniformFanInShape<Integer, Integer> F = builder.add(Merge.create(2)); final SinkShape<Integer> G = builder.add(Sink.foreach(System.out::println)); builder.from(F.out()).toInlet(C.in(0)); builder.from(A).toInlet(B.in()); builder.from(B.out(0)).toInlet(C.in(1)); builder.from(C.out()).toInlet(F.in(0)); builder.from(B.out(1)).via(D).toInlet(E.in()); builder.from(E.out(0)).toInlet(F.in(1)); builder.from(E.out(1)).to(G); return ClosedShape.getInstance(); })); // #complex-graph-alt }
public void demonstrateAGraphStageWithATimer() throws Exception { // tests: 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), result.toCompletableFuture().get(3, TimeUnit.SECONDS)); }
public void streamFile() throws IOException, FileNotFoundException, InterruptedException, ExecutionException { String url = "http://example.com"; // #stream-to-file File file = File.createTempFile("stream-to-file-", ".txt"); FileOutputStream outputStream = new FileOutputStream(file); // Make the request CompletionStage<StreamedResponse> futureResponse = ws.url(url).setMethod("GET").stream(); CompletionStage<File> downloadedFile = futureResponse.thenCompose( res -> { Source<ByteString, ?> responseBody = res.getBody(); // The sink that writes to the output stream Sink<ByteString, scala.concurrent.Future<scala.runtime.BoxedUnit>> outputWriter = Sink.<ByteString>foreach(bytes -> outputStream.write(bytes.toArray())); // Converts the materialized Scala Future into a Java8 `CompletionStage` Sink<ByteString, CompletionStage<?>> convertedOutputWriter = outputWriter.mapMaterializedValue(FutureConverters::toJava); // materialize and run the stream CompletionStage<File> result = responseBody .runWith(convertedOutputWriter, materializer) .whenComplete( (value, error) -> { // Close the output stream whether there was an error or not try { outputStream.close(); } catch (IOException e) { } }) .thenApply(v -> file); return result; }); // #stream-to-file downloadedFile.toCompletableFuture().get(); file.delete(); }
public void demonstrateACustomMaterializedValue() throws Exception { // tests: RunnableGraph<CompletionStage<Integer>> flow = Source.from(Arrays.asList(1, 2, 3)) .viaMat(new FirstValue(), Keep.right()) .to(Sink.ignore()); CompletionStage<Integer> result = flow.run(mat); assertEquals(new Integer(1), result.toCompletableFuture().get(3, TimeUnit.SECONDS)); }
@Test public void demonstrateCustomSourceUsage() throws Exception { // #simple-source-usage // A GraphStage is a proper Graph, just like what GraphDSL.create would return Graph<SourceShape<Integer>, NotUsed> sourceGraph = new NumbersSource(); // Create a Source from the Graph to access the DSL Source<Integer, NotUsed> mySource = Source.fromGraph(sourceGraph); // Returns 55 CompletionStage<Integer> result1 = mySource.take(10).runFold(0, (sum, next) -> sum + next, mat); // The source is reusable. This returns 5050 CompletionStage<Integer> result2 = mySource.take(100).runFold(0, (sum, next) -> sum + next, mat); // #simple-source-usage assertEquals(result1.toCompletableFuture().get(3, TimeUnit.SECONDS), (Integer) 55); assertEquals(result2.toCompletableFuture().get(3, TimeUnit.SECONDS), (Integer) 5050); }
@Test public void demonstrateASimplerOneToManyStage() throws Exception { // tests: Graph<FlowShape<Integer, Integer>, NotUsed> duplicator = Flow.fromGraph(new Duplicator2<Integer>()); CompletionStage<Integer> result = Source.from(Arrays.asList(1, 2, 3)).via(duplicator).runFold(0, (n, sum) -> n + sum, mat); assertEquals(new Integer(12), result.toCompletableFuture().get(3, TimeUnit.SECONDS)); }
@Test public void demonstrateFilterAndMap() { final SilenceSystemOut.System System = SilenceSystemOut.get(); // #first-sample // #authors-filter-map final Source<Author, NotUsed> authors = tweets.filter(t -> t.hashtags().contains(AKKA)).map(t -> t.author); // #first-sample // #authors-filter-map new Object() { // #authors-collect JavaPartialFunction<Tweet, Author> collectFunction = new JavaPartialFunction<Tweet, Author>() { public Author apply(Tweet t, boolean isCheck) { if (t.hashtags().contains(AKKA)) { if (isCheck) return null; // to spare the expensive or side-effecting code return t.author; } else { throw noMatch(); } } }; final Source<Author, NotUsed> authors = tweets.collect(collectFunction); // #authors-collect }; // #first-sample // #authors-foreachsink-println authors.runWith(Sink.foreach(a -> System.out.println(a)), mat); // #first-sample // #authors-foreachsink-println // #authors-foreach-println authors.runForeach(a -> System.out.println(a), mat); // #authors-foreach-println }
@Test public void demonstrateMaterializeMultipleTimes() { final Source<Tweet, NotUsed> tweetsInMinuteFromNow = tweets; // not really in second, just acting as if // #tweets-runnable-flow-materialized-twice final Sink<Integer, CompletionStage<Integer>> sumSink = Sink.<Integer, Integer>fold(0, (acc, elem) -> acc + elem); 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 CompletionStage<Integer> morningTweetsCount = counterRunnableGraph.run(mat); // and once in the evening, reusing the blueprint final CompletionStage<Integer> eveningTweetsCount = counterRunnableGraph.run(mat); // #tweets-runnable-flow-materialized-twice }
@Test public void nonNestedFlow() throws Exception { // #non-nested-flow Source.single(0) .map(i -> i + 1) .filter(i -> i != 0) .map(i -> i - 2) .to(Sink.fold(0, (acc, i) -> acc + i)); // ... where is the nesting? // #non-nested-flow }
@Test public void demonstrateAnAsynchronousSideChannel() throws Exception { // tests: CompletableFuture<Done> switchF = new CompletableFuture<>(); Graph<FlowShape<Integer, Integer>, NotUsed> killSwitch = Flow.fromGraph(new KillSwitch<>(switchF)); ExecutionContext ec = system.dispatcher(); CompletionStage<Integer> valueAfterKill = switchF.thenApply(in -> 4); CompletionStage<Integer> result = Source.from(Arrays.asList(1, 2, 3)) .concat(Source.fromCompletionStage(valueAfterKill)) .via(killSwitch) .runFold(0, (n, sum) -> n + sum, mat); switchF.complete(Done.getInstance()); assertEquals(new Integer(6), result.toCompletableFuture().get(3, TimeUnit.SECONDS)); }
@Test public void closedGraph() throws Exception { // #embed-closed final RunnableGraph<NotUsed> closed1 = Source.single(0).to(Sink.foreach(System.out::println)); final RunnableGraph<NotUsed> closed2 = RunnableGraph.fromGraph( GraphDSL.create( builder -> { final ClosedShape embeddedClosed = builder.add(closed1); return embeddedClosed; // Could return ClosedShape.getInstance() })); // #embed-closed }
@Test public void nestedFlow() throws Exception { // #nested-flow final Source<Integer, NotUsed> nestedSource = Source.single(0) // An atomic source .map(i -> i + 1) // an atomic processing stage .named("nestedSource"); // wraps up the current Source and gives it a name final Flow<Integer, Integer, NotUsed> nestedFlow = Flow.of(Integer.class) .filter(i -> i != 0) // an atomic processing stage .map(i -> i - 2) // another atomic processing stage .named("nestedFlow"); // wraps up the Flow, and gives it a name final Sink<Integer, NotUsed> nestedSink = nestedFlow .to(Sink.fold(0, (acc, i) -> acc + i)) // wire an atomic sink to the nestedFlow .named("nestedSink"); // wrap it up // Create a RunnableGraph final RunnableGraph<NotUsed> runnableGraph = nestedSource.to(nestedSink); // #nested-flow }
@Test public void demonstrateAManyToOneElementGraphStage() throws Exception { // tests: Graph<FlowShape<Integer, Integer>, NotUsed> evenFilter = Flow.fromGraph(new Filter<Integer>(n -> n % 2 == 0)); 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), result.toCompletableFuture().get(3, TimeUnit.SECONDS)); }
public void streamSimpleRequest() { String url = "http://example.com"; // #stream-count-bytes // Make the request CompletionStage<StreamedResponse> futureResponse = ws.url(url).setMethod("GET").stream(); CompletionStage<Long> bytesReturned = futureResponse.thenCompose( res -> { Source<ByteString, ?> responseBody = res.getBody(); // Count the number of bytes returned Sink<ByteString, scala.concurrent.Future<Long>> bytesSum = Sink.fold(0L, (total, bytes) -> total + bytes.length()); // Converts the materialized Scala Future into a Java8 `CompletionStage` Sink<ByteString, CompletionStage<Long>> convertedBytesSum = bytesSum.mapMaterializedValue(FutureConverters::toJava); return responseBody.runWith(convertedBytesSum, materializer); }); // #stream-count-bytes }
public void demonstrateADetachedGraphStage() throws Exception { // tests: CompletionStage<Integer> result1 = Source.from(Arrays.asList(1, 2, 3)) .via(new TwoBuffer<>()) .runFold(0, (acc, n) -> acc + n, mat); 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); RunnableGraph<NotUsed> flow2 = Source.fromPublisher(publisher).via(new TwoBuffer<>()).to(Sink.fromSubscriber(subscriber)); flow2.run(mat); Subscription sub = subscriber.expectSubscription(); // this happens even though the subscriber has not signalled any demand publisher.sendNext(1); publisher.sendNext(2); sub.cancel(); }
@Test public void demonstrateChainingOfGraphStages() throws Exception { Graph<SinkShape<Integer>, CompletionStage<String>> sink = Sink.fold("", (acc, n) -> acc + n.toString()); // #graph-stage-chain 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)) .runWith(sink, mat); // #graph-stage-chain assertEquals("1122", resultFuture.toCompletableFuture().get(3, TimeUnit.SECONDS)); }
@Test public void partialGraph() throws Exception { // #partial-graph final Graph<FlowShape<Integer, Integer>, NotUsed> partial = GraphDSL.create( builder -> { final UniformFanOutShape<Integer, Integer> B = builder.add(Broadcast.create(2)); final UniformFanInShape<Integer, Integer> C = builder.add(Merge.create(2)); final UniformFanOutShape<Integer, Integer> E = builder.add(Balance.create(2)); final UniformFanInShape<Integer, Integer> F = builder.add(Merge.create(2)); builder.from(F.out()).toInlet(C.in(0)); builder.from(B).viaFanIn(C).toFanIn(F); builder .from(B) .via(builder.add(Flow.of(Integer.class).map(i -> i + 1))) .viaFanOut(E) .toFanIn(F); return new FlowShape<Integer, Integer>(B.in(), E.out(1)); }); // #partial-graph // #partial-use Source.single(0).via(partial).to(Sink.ignore()); // #partial-use // #partial-flow-dsl // Convert the partial graph of FlowShape to a Flow to get // access to the fluid DSL (for example to be able to call .filter()) final Flow<Integer, Integer, NotUsed> flow = Flow.fromGraph(partial); // Simple way to create a graph backed Source final Source<Integer, NotUsed> source = Source.fromGraph( GraphDSL.create( builder -> { final UniformFanInShape<Integer, Integer> merge = builder.add(Merge.create(2)); builder.from(builder.add(Source.single(0))).toFanIn(merge); builder.from(builder.add(Source.from(Arrays.asList(2, 3, 4)))).toFanIn(merge); // Exposing exactly one output port return new SourceShape<Integer>(merge.out()); })); // Building a Sink with a nested Flow, using the fluid DSL final Sink<Integer, NotUsed> sink = Flow.of(Integer.class).map(i -> i * 2).drop(10).named("nestedFlow").to(Sink.head()); // Putting all together final RunnableGraph<NotUsed> closed = source.via(flow.filter(i -> i > 1)).to(sink); // #partial-flow-dsl }
@Test public void materializedValues() throws Exception { // #mat-combine-1 // Materializes to Promise<BoxedUnit> (red) 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, CompletableFuture<Optional<Integer>>> nestedSource = source.viaMat(flow1, Keep.left()).named("nestedSource"); // #mat-combine-1 // #mat-combine-2 // Materializes to BoxedUnit (orange) final Flow<Integer, ByteString, NotUsed> flow2 = Flow.of(Integer.class).map(i -> ByteString.fromString(i.toString())); // Materializes to Future<OutgoingConnection> (yellow) final Flow<ByteString, ByteString, CompletionStage<OutgoingConnection>> flow3 = Tcp.get(system).outgoingConnection("localhost", 8080); // Materializes to Future<OutgoingConnection> (yellow) 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, CompletionStage<String>> sink = Sink.<String, ByteString>fold("", (acc, i) -> acc + i.utf8String()); // Materializes to Pair<Future<OutgoingConnection>, Future<String>> (blue) 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<CompletionStage<MyClass>> runnableGraph = nestedSource.toMat(nestedSink, Combiner::f); // #mat-combine-4b }
public void run(final Materializer mat) throws TimeoutException, InterruptedException, ExecutionException { // #backpressure-by-readline 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); completion.toCompletableFuture().get(1, TimeUnit.SECONDS); // #backpressure-by-readline }
@Test public void demonstrateOneToOne() throws Exception { // tests: final Graph<FlowShape<String, Integer>, NotUsed> stringLength = Flow.fromGraph( new Map<String, Integer>( new Function<String, Integer>() { @Override public Integer apply(String str) { return str.length(); } })); CompletionStage<Integer> result = Source.from(Arrays.asList("one", "two", "three")) .via(stringLength) .runFold(0, (sum, n) -> sum + n, mat); assertEquals(new Integer(11), result.toCompletableFuture().get(3, TimeUnit.SECONDS)); }
@Test public void mustSignalFailureViaIoResult() throws Exception { final OutputStream os = new OutputStream() { volatile int left = 3; public void write(int data) { if (left == 0) { throw new RuntimeException("Can't accept more data."); } left -= 1; } }; final CompletionStage<IOResult> resultFuture = Source.single(ByteString.fromString("123456")) .runWith(StreamConverters.fromOutputStream(() -> os), materializer); final IOResult result = resultFuture.toCompletableFuture().get(3, TimeUnit.SECONDS); assertFalse(result.wasSuccessful()); assertTrue(result.getError().getMessage().equals("Can't accept more data.")); }
@Test public void attributes() throws Exception { // #attributes-inheritance final Source<Integer, NotUsed> nestedSource = Source.single(0).map(i -> i + 1).named("nestedSource"); // Wrap, no inputBuffer set final Flow<Integer, Integer, NotUsed> nestedFlow = Flow.of(Integer.class) .filter(i -> i != 0) .via( Flow.of(Integer.class) .map(i -> i - 2) .withAttributes(Attributes.inputBuffer(4, 4))) // override .named("nestedFlow"); // Wrap, no inputBuffer set final Sink<Integer, NotUsed> nestedSink = nestedFlow .to(Sink.fold(0, (acc, i) -> acc + i)) // wire an atomic sink to the nestedFlow .withAttributes( Attributes.name("nestedSink").and(Attributes.inputBuffer(3, 3))); // override // #attributes-inheritance }
Request buildRequest() { RequestBuilder builder = new RequestBuilder(method); builder.setUrl(url); builder.setQueryParams(new FluentStringsMap(queryParameters)); builder.setHeaders(headers); if (body == null) { // do nothing } else if (body instanceof String) { String stringBody = ((String) body); FluentCaseInsensitiveStringsMap headers = new FluentCaseInsensitiveStringsMap(this.headers); // Detect and maybe add charset String contentType = headers.getFirstValue(HttpHeaders.Names.CONTENT_TYPE); if (contentType == null) { contentType = "text/plain"; } Charset charset = HttpUtils.parseCharset(contentType); if (charset == null) { charset = StandardCharsets.UTF_8; List<String> contentTypeList = new ArrayList<String>(); contentTypeList.add(contentType + "; charset=utf-8"); headers.replace(HttpHeaders.Names.CONTENT_TYPE, contentTypeList); } byte[] bodyBytes; bodyBytes = stringBody.getBytes(charset); // If using a POST with OAuth signing, the builder looks at // getFormParams() rather than getBody() and constructs the signature // based on the form params. if (contentType.equals(HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED)) { Map<String, List<String>> stringListMap = FormUrlEncodedParser.parseAsJava(stringBody, "utf-8"); for (String key : stringListMap.keySet()) { List<String> values = stringListMap.get(key); for (String value : values) { builder.addFormParam(key, value); } } } else { builder.setBody(stringBody); } builder.setHeaders(headers); builder.setBodyCharset(charset); } else if (body instanceof JsonNode) { JsonNode jsonBody = (JsonNode) body; FluentCaseInsensitiveStringsMap headers = new FluentCaseInsensitiveStringsMap(this.headers); List<String> contentType = new ArrayList<String>(); contentType.add("application/json; charset=utf-8"); headers.replace(HttpHeaders.Names.CONTENT_TYPE, contentType); String bodyStr = Json.stringify(jsonBody); byte[] bodyBytes; try { bodyBytes = bodyStr.getBytes("utf-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } builder.setBody(bodyStr); builder.setHeaders(headers); builder.setBodyCharset(StandardCharsets.UTF_8); } else if (body instanceof File) { File fileBody = (File) body; FileBodyGenerator bodyGenerator = new FileBodyGenerator(fileBody); builder.setBody(bodyGenerator); } else if (body instanceof InputStream) { InputStream inputStreamBody = (InputStream) body; InputStreamBodyGenerator bodyGenerator = new InputStreamBodyGenerator(inputStreamBody); builder.setBody(bodyGenerator); } else if (body instanceof Source) { Source<ByteString, ?> sourceBody = (Source<ByteString, ?>) body; Publisher<ByteBuffer> publisher = sourceBody.map(ByteString::toByteBuffer).runWith(Sink.asPublisher(false), materializer); builder.setBody(publisher); } else { throw new IllegalStateException("Impossible body: " + body); } if (this.timeout == -1 || this.timeout > 0) { builder.setRequestTimeout(this.timeout); } if (this.followRedirects != null) { builder.setFollowRedirect(this.followRedirects); } if (this.virtualHost != null) { builder.setVirtualHost(this.virtualHost); } if (this.username != null && this.password != null && this.scheme != null) { builder.setRealm(auth(this.username, this.password, this.scheme)); } if (this.calculator != null) { if (this.calculator instanceof OAuth.OAuthCalculator) { OAuthSignatureCalculator calc = ((OAuth.OAuthCalculator) this.calculator).getCalculator(); builder.setSignatureCalculator(calc); } else { throw new IllegalStateException("Use OAuth.OAuthCalculator"); } } return builder.build(); }
public void requestExamples() { // #ws-holder WSRequest request = ws.url("http://example.com"); // #ws-holder // #ws-complex-holder WSRequest complexRequest = request .setHeader("headerKey", "headerValue") .setRequestTimeout(1000) .setQueryParameter("paramKey", "paramValue"); // #ws-complex-holder // #ws-get CompletionStage<WSResponse> responsePromise = complexRequest.get(); // #ws-get String url = "http://example.com"; // #ws-auth ws.url(url).setAuth("user", "password", WSAuthScheme.BASIC).get(); // #ws-auth // #ws-follow-redirects ws.url(url).setFollowRedirects(true).get(); // #ws-follow-redirects // #ws-query-parameter ws.url(url).setQueryParameter("paramKey", "paramValue"); // #ws-query-parameter // #ws-header ws.url(url).setHeader("headerKey", "headerValue").get(); // #ws-header String jsonString = "{\"key1\":\"value1\"}"; // #ws-header-content-type ws.url(url).setHeader("Content-Type", "application/json").post(jsonString); // OR ws.url(url).setContentType("application/json").post(jsonString); // #ws-header-content-type // #ws-timeout ws.url(url).setRequestTimeout(1000).get(); // #ws-timeout // #ws-post-form-data ws.url(url) .setContentType("application/x-www-form-urlencoded") .post("key1=value1&key2=value2"); // #ws-post-form-data // #ws-post-json JsonNode json = Json.newObject().put("key1", "value1").put("key2", "value2"); ws.url(url).post(json); // #ws-post-json String value = IntStream.range(0, 100).boxed().map(i -> "abcdefghij").reduce("", (a, b) -> a + b); ByteString seedValue = ByteString.fromString(value); Stream<ByteString> largeSource = IntStream.range(0, 10).boxed().map(i -> seedValue); Source<ByteString, ?> largeImage = Source.from(largeSource.collect(Collectors.toList())); // #ws-stream-request CompletionStage<WSResponse> wsResponse = ws.url(url).setBody(largeImage).execute("PUT"); // #ws-stream-request }
public static void main(String[] args) { Outlet<Integer> outlet = null; Outlet<Integer> outlet1 = null; Outlet<Integer> outlet2 = null; Inlet<Integer> inlet = null; Inlet<Integer> inlet1 = null; Inlet<Integer> inlet2 = null; Flow<Integer, Integer, BoxedUnit> flow = Flow.of(Integer.class); Flow<Integer, Integer, BoxedUnit> flow1 = Flow.of(Integer.class); Flow<Integer, Integer, BoxedUnit> flow2 = Flow.of(Integer.class); Promise<Option<Integer>> promise = null; { Graph<SourceShape<Integer>, BoxedUnit> graphSource = null; Graph<SinkShape<Integer>, BoxedUnit> graphSink = null; Graph<FlowShape<Integer, Integer>, BoxedUnit> graphFlow = null; // #flow-wrap Source<Integer, BoxedUnit> source = Source.fromGraph(graphSource); Sink<Integer, BoxedUnit> sink = Sink.fromGraph(graphSink); Flow<Integer, Integer, BoxedUnit> aflow = Flow.fromGraph(graphFlow); Flow.fromSinkAndSource(Sink.<Integer>head(), Source.single(0)); Flow.fromSinkAndSourceMat(Sink.<Integer>head(), Source.single(0), Keep.left()); // #flow-wrap Graph<BidiShape<Integer, Integer, Integer, Integer>, BoxedUnit> bidiGraph = null; // #bidi-wrap BidiFlow<Integer, Integer, Integer, Integer, BoxedUnit> bidiFlow = BidiFlow.fromGraph(bidiGraph); BidiFlow.fromFlows(flow1, flow2); BidiFlow.fromFlowsMat(flow1, flow2, Keep.both()); // #bidi-wrap } { // #graph-create GraphDSL.create( builder -> { // ... return ClosedShape.getInstance(); }); GraphDSL.create( builder -> { // ... return new FlowShape<>(inlet, outlet); }); // #graph-create } { // #graph-create-2 GraphDSL.create( builder -> { // ... return SourceShape.of(outlet); }); GraphDSL.create( builder -> { // ... return SinkShape.of(inlet); }); GraphDSL.create( builder -> { // ... return FlowShape.of(inlet, outlet); }); GraphDSL.create( builder -> { // ... return BidiShape.of(inlet1, outlet1, inlet2, outlet2); }); // #graph-create-2 } { // #graph-builder GraphDSL.create( builder -> { builder.from(outlet).toInlet(inlet); builder.from(outlet).via(builder.add(flow)).toInlet(inlet); builder.from(builder.add(Source.single(0))).to(builder.add(Sink.head())); // ... return ClosedShape.getInstance(); }); // #graph-builder } // #source-creators Source<Integer, Promise<Option<Integer>>> src = Source.<Integer>maybe(); // Complete the promise with an empty option to emulate the old lazyEmpty promise.trySuccess(scala.Option.empty()); final Source<String, Cancellable> ticks = Source.tick( FiniteDuration.create(0, TimeUnit.MILLISECONDS), FiniteDuration.create(200, TimeUnit.MILLISECONDS), "tick"); final Source<Integer, BoxedUnit> pubSource = Source.fromPublisher(TestPublisher.<Integer>manualProbe(true, sys)); final Source<Integer, BoxedUnit> futSource = Source.fromFuture(Futures.successful(42)); final Source<Integer, Subscriber<Integer>> subSource = Source.<Integer>asSubscriber(); // #source-creators // #sink-creators final Sink<Integer, BoxedUnit> subSink = Sink.fromSubscriber(TestSubscriber.<Integer>manualProbe(sys)); // #sink-creators // #sink-as-publisher final Sink<Integer, Publisher<Integer>> pubSink = Sink.<Integer>asPublisher(false); final Sink<Integer, Publisher<Integer>> pubSinkFanout = Sink.<Integer>asPublisher(true); // #sink-as-publisher // #empty-flow Flow<Integer, Integer, BoxedUnit> emptyFlow = Flow.<Integer>create(); // or Flow<Integer, Integer, BoxedUnit> emptyFlow2 = Flow.of(Integer.class); // #empty-flow // #flatMapConcat Flow.<Source<Integer, BoxedUnit>>create() .<Integer, BoxedUnit>flatMapConcat( new Function<Source<Integer, BoxedUnit>, Source<Integer, BoxedUnit>>() { @Override public Source<Integer, BoxedUnit> apply(Source<Integer, BoxedUnit> param) throws Exception { return param; } }); // #flatMapConcat Uri uri = null; // #raw-query final akka.japi.Option<String> theRawQueryString = uri.rawQueryString(); // #raw-query // #query-param final akka.japi.Option<String> aQueryParam = uri.query().get("a"); // #query-param // #file-source-sink final Source<ByteString, Future<Long>> fileSrc = FileIO.fromFile(new File(".")); final Source<ByteString, Future<Long>> otherFileSrc = FileIO.fromFile(new File("."), 1024); final Sink<ByteString, Future<Long>> fileSink = FileIO.toFile(new File(".")); // #file-source-sink // #input-output-stream-source-sink final Source<ByteString, Future<java.lang.Long>> inputStreamSrc = StreamConverters.fromInputStream( new Creator<InputStream>() { public InputStream create() { return new SomeInputStream(); } }); final Source<ByteString, Future<java.lang.Long>> otherInputStreamSrc = StreamConverters.fromInputStream( new Creator<InputStream>() { public InputStream create() { return new SomeInputStream(); } }, 1024); final Sink<ByteString, Future<java.lang.Long>> outputStreamSink = StreamConverters.fromOutputStream( new Creator<OutputStream>() { public OutputStream create() { return new SomeOutputStream(); } }); // #input-output-stream-source-sink // #output-input-stream-source-sink final FiniteDuration timeout = FiniteDuration.Zero(); final Source<ByteString, OutputStream> outputStreamSrc = StreamConverters.asOutputStream(); final Source<ByteString, OutputStream> otherOutputStreamSrc = StreamConverters.asOutputStream(timeout); final Sink<ByteString, InputStream> someInputStreamSink = StreamConverters.asInputStream(); final Sink<ByteString, InputStream> someOtherInputStreamSink = StreamConverters.asInputStream(timeout); // #output-input-stream-source-sink }
abstract static class Model { // #model public static class Author { public final String handle; public Author(String handle) { this.handle = handle; } // ... // #model @Override public String toString() { return "Author(" + handle + ")"; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Author author = (Author) o; if (handle != null ? !handle.equals(author.handle) : author.handle != null) { return false; } return true; } @Override public int hashCode() { return handle != null ? handle.hashCode() : 0; } // #model } // #model // #model public static class Hashtag { public final String name; public Hashtag(String name) { this.name = name; } // ... // #model @Override public int hashCode() { return name.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Hashtag other = (Hashtag) obj; return name.equals(other.name); } @Override public String toString() { return "Hashtag(" + name + ")"; } // #model } // #model // #model public static class Tweet { public final Author author; public final long timestamp; public final String body; public Tweet(Author author, long timestamp, String body) { this.author = author; this.timestamp = timestamp; this.body = body; } public Set<Hashtag> hashtags() { return Arrays.asList(body.split(" ")) .stream() .filter(a -> a.startsWith("#")) .map(a -> new Hashtag(a)) .collect(Collectors.toSet()); } // ... // #model @Override public String toString() { return "Tweet(" + author + "," + timestamp + "," + body + ")"; } // #model } // #model // #model public static final Hashtag AKKA = new Hashtag("#akka"); // #model public static final Source<Tweet, NotUsed> tweets = Source.from( Arrays.asList( new Tweet[] { new Tweet(new Author("rolandkuhn"), System.currentTimeMillis(), "#akka rocks!"), new Tweet(new Author("patriknw"), System.currentTimeMillis(), "#akka !"), new Tweet(new Author("bantonsson"), System.currentTimeMillis(), "#akka !"), new Tweet(new Author("drewhk"), System.currentTimeMillis(), "#akka !"), new Tweet( new Author("ktosopl"), System.currentTimeMillis(), "#akka on the rocks!"), new Tweet(new Author("mmartynas"), System.currentTimeMillis(), "wow #akka !"), new Tweet(new Author("akkateam"), System.currentTimeMillis(), "#akka rocks!"), new Tweet(new Author("bananaman"), System.currentTimeMillis(), "#bananas rock!"), new Tweet(new Author("appleman"), System.currentTimeMillis(), "#apples rock!"), new Tweet( new Author("drama"), System.currentTimeMillis(), "we compared #apples to #oranges!") })); }