diff --git a/akka-docs/src/main/paradox/stream/stream-io.md b/akka-docs/src/main/paradox/stream/stream-io.md index c7f13ad864..b76f6623a6 100644 --- a/akka-docs/src/main/paradox/stream/stream-io.md +++ b/akka-docs/src/main/paradox/stream/stream-io.md @@ -123,6 +123,14 @@ see @java[[Javadoc](http://doc.akka.io/japi/akka/current/akka/stream/javadsl/Framing.html#simpleFramingProtocol-int-)] for more information. +@scala[[JsonFraming](http://doc.akka.io/api/akka/current/akka/stream/scaladsl/JsonFraming$.html)]@java[[JsonFraming](http://doc.akka.io/japi/akka/current/akka/stream/javadsl/JsonFraming.html#objectScanner-int-)] separates valid JSON objects from incoming `ByteString` objects: + +Scala +: @@snip [JsonFramingSpec.scala]($akka$akka-stream-tests/src/test/scala/akka/stream/scaladsl/JsonFramingSpec.scala) { #using-json-framing } + +Java +: @@snip [JsonFramingTest.java]($akka$akka-stream-tests/src/test/java/akka/stream/javadsl/JsonFramingTest.java) { #using-json-framing } + ### TLS Similar factories as shown above for raw TCP but where the data is encrypted using TLS are available from `Tcp` through `outgoingTlsConnection`, `bindTls` and `bindAndHandleTls`, see the @scala[@scaladoc[`Tcp Scaladoc`](akka.stream.scaladsl.Tcp)]@java[@javadoc[`Tcp Javadoc`](akka.stream.javadsl.Tcp)] for details. @@ -133,7 +141,7 @@ Scala : @@snip [TcpSpec.scala]($akka$akka-stream-tests/src/test/scala/akka/stream/io/TcpSpec.scala) { #setting-up-ssl-context } Java -: @@snip [TcpSpec.scala]($akka$akka-stream-tests/src/test/java/akka/stream/javadsl/TcpTest.java) { #setting-up-ssl-context } +: @@snip [TcpTest.java]($akka$akka-stream-tests/src/test/java/akka/stream/javadsl/TcpTest.java) { #setting-up-ssl-context } The `SslContext` and `NegotiateFirstSession` instances can then be used with the binding or outgoing connection factory methods. @@ -162,4 +170,4 @@ Scala : @@snip [StreamFileDocSpec.scala]($code$/scala/docs/stream/io/StreamFileDocSpec.scala) { #custom-dispatcher-code } Java -: @@snip [StreamFileDocTest.java]($code$/java/jdocs/stream/io/StreamFileDocTest.java) { #custom-dispatcher-code } \ No newline at end of file +: @@snip [StreamFileDocTest.java]($code$/java/jdocs/stream/io/StreamFileDocTest.java) { #custom-dispatcher-code } diff --git a/akka-stream-tests/src/test/java/akka/stream/javadsl/JsonFramingTest.java b/akka-stream-tests/src/test/java/akka/stream/javadsl/JsonFramingTest.java new file mode 100644 index 0000000000..2e1d03a959 --- /dev/null +++ b/akka-stream-tests/src/test/java/akka/stream/javadsl/JsonFramingTest.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2015-2018 Lightbend Inc. + */ +package akka.stream.javadsl; + +import akka.util.ByteString; +import akka.stream.StreamTest; +import akka.testkit.AkkaJUnitActorSystemResource; +import akka.testkit.AkkaSpec; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static org.junit.Assert.assertEquals; + +public class JsonFramingTest extends StreamTest { + public JsonFramingTest() { + super(actorSystemResource); + } + + @ClassRule + public static AkkaJUnitActorSystemResource actorSystemResource = + new AkkaJUnitActorSystemResource("JsonFramingTest", AkkaSpec.testConf()); + + @Test + public void mustBeAbleToParseJsonArray() throws InterruptedException, ExecutionException, TimeoutException { + // #using-json-framing + String input = "[{ \"name\" : \"john\" }, { \"name\" : \"Ég get etið gler án þess að meiða mig\" }, { \"name\" : \"jack\" }]"; + CompletionStage> result = Source.single(ByteString.fromString(input)) + .via(JsonFraming.objectScanner(Integer.MAX_VALUE)) + .runFold(new ArrayList(), (acc, entry) -> { + acc.add(entry.utf8String()); + return acc; + }, materializer); + // #using-json-framing + + List frames = result.toCompletableFuture().get(5, TimeUnit.SECONDS); + assertEquals("{ \"name\" : \"john\" }", frames.get(0)); + assertEquals("{ \"name\" : \"Ég get etið gler án þess að meiða mig\" }", frames.get(1)); + assertEquals("{ \"name\" : \"jack\" }", frames.get(2)); + } +} diff --git a/akka-stream-tests/src/test/scala/akka/stream/scaladsl/JsonFramingSpec.scala b/akka-stream-tests/src/test/scala/akka/stream/scaladsl/JsonFramingSpec.scala index 457d08778b..0a0700b916 100644 --- a/akka-stream-tests/src/test/scala/akka/stream/scaladsl/JsonFramingSpec.scala +++ b/akka-stream-tests/src/test/scala/akka/stream/scaladsl/JsonFramingSpec.scala @@ -21,6 +21,7 @@ class JsonFramingSpec extends AkkaSpec { "collecting multiple json" should { "parse json array" in { + // #using-json-framing val input = """ |[ @@ -35,6 +36,7 @@ class JsonFramingSpec extends AkkaSpec { .runFold(Seq.empty[String]) { case (acc, entry) ⇒ acc ++ Seq(entry.utf8String) } + // #using-json-framing result.futureValue shouldBe Seq( """{ "name" : "john" }""",