diff --git a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/ActorTestKit.scala b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/ActorTestKit.scala index e9d6e70a09..0f5f5ac6c8 100644 --- a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/ActorTestKit.scala +++ b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/ActorTestKit.scala @@ -199,4 +199,9 @@ final class ActorTestKit private[akka] (delegate: akka.actor.testkit.typed.scala */ def shutdownTestKit(): Unit = delegate.shutdownTestKit() + /** + * Additional testing utilities for serialization. + */ + val serializationTestKit: SerializationTestKit = new SerializationTestKit(delegate.internalSystem) + } diff --git a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/SerializationTestKit.scala b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/SerializationTestKit.scala new file mode 100644 index 0000000000..86d8fa11b7 --- /dev/null +++ b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/SerializationTestKit.scala @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 Lightbend Inc. + */ + +package akka.actor.testkit.typed.javadsl + +import akka.actor.testkit.typed.scaladsl +import akka.actor.typed.ActorSystem + +/** + * Utilities to test serialization. + */ +class SerializationTestKit(system: ActorSystem[_]) { + + private val delegate = new scaladsl.SerializationTestKit(system) + + /** + * Verify serialization roundtrip. + * Throws exception from serializer if `obj` can't be serialized and deserialized. + * + * @param obj the object to verify + * @param assertEquality if `true` the deserialized object is verified to be equal to `obj`, + * and if not an `AssertionError` is thrown + * @return the deserialized object + */ + def verifySerialization[M](obj: M, assertEquality: Boolean): M = + delegate.verifySerialization(obj, assertEquality) +} diff --git a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/TestKitJunitResource.scala b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/TestKitJunitResource.scala index da89ae0110..b6238cde9f 100644 --- a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/TestKitJunitResource.scala +++ b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/javadsl/TestKitJunitResource.scala @@ -139,6 +139,11 @@ final class TestKitJunitResource(_kit: ActorTestKit) extends ExternalResource { */ def stop[T](ref: ActorRef[T]): Unit = testKit.stop(ref) + /** + * Additional testing utilities for serialization. + */ + def serializationTestKit: SerializationTestKit = testKit.serializationTestKit + override def after(): Unit = { testKit.shutdownTestKit() } diff --git a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/ActorTestKit.scala b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/ActorTestKit.scala index 17da3ffd22..df3151f7b1 100644 --- a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/ActorTestKit.scala +++ b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/ActorTestKit.scala @@ -6,23 +6,23 @@ package akka.actor.testkit.typed.scaladsl import java.util.concurrent.TimeoutException -import akka.actor.typed.scaladsl.AskPattern._ +import scala.concurrent.Await +import scala.concurrent.duration._ + +import akka.actor.testkit.typed.TestKitSettings +import akka.actor.testkit.typed.internal.ActorTestKitGuardian +import akka.actor.testkit.typed.internal.TestKitUtils import akka.actor.typed.ActorRef import akka.actor.typed.ActorSystem import akka.actor.typed.Behavior import akka.actor.typed.Props import akka.actor.typed.Scheduler +import akka.actor.typed.scaladsl.AskPattern._ import akka.annotation.InternalApi -import akka.actor.testkit.typed.TestKitSettings -import akka.actor.testkit.typed.internal.ActorTestKitGuardian -import akka.actor.testkit.typed.internal.TestKitUtils +import akka.util.Timeout import com.typesafe.config.Config import com.typesafe.config.ConfigFactory -import scala.concurrent.Await -import scala.concurrent.duration._ -import akka.util.Timeout - object ActorTestKit { /** @@ -112,7 +112,10 @@ final class ActorTestKit private[akka] (val name: String, val config: Config, se implicit def testKitSettings: TestKitSettings = settings.getOrElse(TestKitSettings(system)) - private val internalSystem: ActorSystem[ActorTestKitGuardian.TestKitCommand] = + /** + * INTERNAL API + */ + @InternalApi private[akka] val internalSystem: ActorSystem[ActorTestKitGuardian.TestKitCommand] = if (config eq ActorTestKit.noConfigSet) ActorSystem(ActorTestKitGuardian.testKitGuardian, name) else ActorSystem(ActorTestKitGuardian.testKitGuardian, name, config) @@ -185,6 +188,11 @@ final class ActorTestKit private[akka] (val name: String, val config: Config, se */ def createTestProbe[M](name: String): TestProbe[M] = TestProbe(name)(system) + /** + * Additional testing utilities for serialization. + */ + val serializationTestKit: SerializationTestKit = new SerializationTestKit(internalSystem) + // FIXME needed for Akka internal tests but, users shouldn't spawn system actors? @InternalApi private[akka] def systemActor[T](behavior: Behavior[T], name: String): ActorRef[T] = diff --git a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/ActorTestKitBase.scala b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/ActorTestKitBase.scala index 5eb1c756bc..e2911ac6c4 100644 --- a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/ActorTestKitBase.scala +++ b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/ActorTestKitBase.scala @@ -100,6 +100,11 @@ abstract class ActorTestKitBase(val testKit: ActorTestKit) { */ def createTestProbe[M](name: String): TestProbe[M] = testKit.createTestProbe(name) + /** + * Additional testing utilities for serialization. + */ + def serializationTestKit: SerializationTestKit = testKit.serializationTestKit + /** * To be implemented by "more" concrete class that can mixin `BeforeAndAfterAll` or similar, * for example `FlatSpecLike with BeforeAndAfterAll`. Implement by calling diff --git a/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/SerializationTestKit.scala b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/SerializationTestKit.scala new file mode 100644 index 0000000000..5aef1c52c9 --- /dev/null +++ b/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/scaladsl/SerializationTestKit.scala @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 Lightbend Inc. + */ + +package akka.actor.testkit.typed.scaladsl + +import akka.actor.typed.scaladsl.adapter._ +import akka.actor.typed.ActorSystem +import akka.serialization.SerializationExtension +import akka.serialization.Serializers + +/** + * Utilities to test serialization. + */ +class SerializationTestKit(system: ActorSystem[_]) { + + private val serialization = SerializationExtension(system.toUntyped) + + /** + * Verify serialization roundtrip. + * Throws exception from serializer if `obj` can't be serialized and deserialized. + * Also tests that the deserialized object is equal to `obj`, and if not an + * `AssertionError` is thrown. + * + * @param obj the object to verify + * @return the deserialized object + */ + def verifySerialization[M](obj: M): M = + verifySerialization(obj, assertEquality = true) + + /** + * Verify serialization roundtrip. + * Throws exception from serializer if `obj` can't be serialized and deserialized. + * + * @param obj the object to verify + * @param assertEquality if `true` the deserialized object is verified to be equal to `obj`, + * and if not an `AssertionError` is thrown + * @return the deserialized object + */ + def verifySerialization[M](obj: M, assertEquality: Boolean): M = { + val result = roundtrip(obj) + if (assertEquality && result != obj) + throw new AssertionError(s"Serialization verification expected $obj, but was $result") + result + } + + /** + * Verify serialization roundtrip. + * Throws exception from serializer if `obj` can't be serialized and deserialized. + * + * @return the deserialized object + */ + private def roundtrip[M](obj: M): M = { + val objAnyRef = obj.asInstanceOf[AnyRef] + val bytes = serialization.serialize(objAnyRef).get + val serializer = serialization.findSerializerFor(objAnyRef) + val manifest = Serializers.manifestFor(serializer, objAnyRef) + serialization.deserialize(bytes, serializer.identifier, manifest).get.asInstanceOf[M] + } +} diff --git a/akka-actor-tests/src/test/resources/reference.conf b/akka-actor-tests/src/test/resources/reference.conf index 5d9918e535..2faba189a0 100644 --- a/akka-actor-tests/src/test/resources/reference.conf +++ b/akka-actor-tests/src/test/resources/reference.conf @@ -3,8 +3,7 @@ akka { library-extensions += "akka.actor.InstanceCountingExtension" actor { - serialize-messages = on - warn-about-java-serializer-usage = off + serialize-messages = off } } diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala index 2bc4dc1881..87111eae86 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala @@ -109,7 +109,10 @@ object ActorRefSpec { } } -class ActorRefSpec extends AkkaSpec with DefaultTimeout { +class ActorRefSpec extends AkkaSpec(""" + # testing Java serialization of ActorRef + akka.actor.allow-java-serialization = on + """) with DefaultTimeout { import akka.actor.ActorRefSpec._ def promiseIntercept(f: => Actor)(to: Promise[Actor]): Actor = diff --git a/akka-actor-tests/src/test/scala/akka/actor/FunctionRefSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/FunctionRefSpec.scala index 46d40d5c6f..150f20e179 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/FunctionRefSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/FunctionRefSpec.scala @@ -36,7 +36,12 @@ object FunctionRefSpec { } -class FunctionRefSpec extends AkkaSpec with ImplicitSender { +class FunctionRefSpec extends AkkaSpec(""" + # test is using Java serialization and relies on serialize-messages=on + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + akka.actor.serialize-messages = on + """) with ImplicitSender { import FunctionRefSpec._ def commonTests(s: ActorRef) = { diff --git a/akka-actor-tests/src/test/scala/akka/actor/PropsCreationSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/PropsCreationSpec.scala index 4f900edb0a..202b582eca 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/PropsCreationSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/PropsCreationSpec.scala @@ -28,7 +28,12 @@ object PropsCreationSpec { } -class PropsCreationSpec extends AkkaSpec("akka.actor.serialize-creators = on") { +class PropsCreationSpec extends AkkaSpec(""" + # test is using Java serialization and relies on serialize-creators=on + akka.actor.serialize-creators = on + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """) { import akka.actor.PropsCreationSpec._ diff --git a/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala index cb4c0b36a3..9143f0860f 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala @@ -36,6 +36,9 @@ object TypedActorSpec { } akka.actor.serializers.sample = "akka.actor.TypedActorSpec$SampleSerializerWithStringManifest$" akka.actor.serialization-bindings."akka.actor.TypedActorSpec$WithStringSerializedClass" = sample + # test is using Java serialization and not priority to convert + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off akka.actor.serialize-messages = off """ diff --git a/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala b/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala index 1434d3cac5..34446cf044 100644 --- a/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala @@ -31,10 +31,8 @@ class ConfigSpec extends AkkaSpec(ConfigFactory.defaultReference(ActorSystem.fin getBoolean("akka.daemonic") should ===(false) - // WARNING: This setting should be off in the default reference.conf, but should be on when running - // the test suite. - getBoolean("akka.actor.serialize-messages") should ===(true) - settings.SerializeAllMessages should ===(true) + getBoolean("akka.actor.serialize-messages") should ===(false) + settings.SerializeAllMessages should ===(false) getInt("akka.scheduler.ticks-per-wheel") should ===(512) getDuration("akka.scheduler.tick-duration", TimeUnit.MILLISECONDS) should ===(10L) @@ -76,6 +74,9 @@ class ConfigSpec extends AkkaSpec(ConfigFactory.defaultReference(ActorSystem.fin getBoolean("akka.coordinated-shutdown.run-by-actor-system-terminate") should ===(true) settings.CoordinatedShutdownRunByActorSystemTerminate should ===(true) + + getBoolean("akka.actor.allow-java-serialization") should ===(false) + settings.AllowJavaSerialization should ===(false) } { diff --git a/akka-actor-tests/src/test/scala/akka/routing/ConsistentHashingRouterSpec.scala b/akka-actor-tests/src/test/scala/akka/routing/ConsistentHashingRouterSpec.scala index 0c70f6b841..7c186cae06 100644 --- a/akka-actor-tests/src/test/scala/akka/routing/ConsistentHashingRouterSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/routing/ConsistentHashingRouterSpec.scala @@ -18,6 +18,11 @@ import akka.testkit._ object ConsistentHashingRouterSpec { val config = """ + akka.actor { + serialize-messages = off + # consistent hashing is serializing the hash key, unless it's bytes or string + allow-java-serialization = on + } akka.actor.deployment { /router1 { router = consistent-hashing-pool diff --git a/akka-actor-tests/src/test/scala/akka/serialization/PrimitivesSerializationSpec.scala b/akka-actor-tests/src/test/scala/akka/serialization/PrimitivesSerializationSpec.scala new file mode 100644 index 0000000000..8c77cf6f54 --- /dev/null +++ b/akka-actor-tests/src/test/scala/akka/serialization/PrimitivesSerializationSpec.scala @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2009-2019 Lightbend Inc. + */ + +package akka.serialization + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +import scala.util.Random + +import akka.testkit.AkkaSpec +import akka.util.ByteString +import com.typesafe.config.ConfigFactory + +object PrimitivesSerializationSpec { + val serializationTestOverrides = "" + + val testConfig = ConfigFactory.parseString(serializationTestOverrides).withFallback(AkkaSpec.testConf) +} + +class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.testConfig) { + + val buffer = { + val b = ByteBuffer.allocate(4096) + b.order(ByteOrder.LITTLE_ENDIAN) + b + } + + val serialization = SerializationExtension(system) + + def verifySerialization(msg: AnyRef): Unit = { + val serializer = serialization.serializerFor(msg.getClass) + serializer.fromBinary(serializer.toBinary(msg), None) should ===(msg) + } + + def verifySerializationByteBuffer(msg: AnyRef): Unit = { + val serializer = serialization.serializerFor(msg.getClass).asInstanceOf[Serializer with ByteBufferSerializer] + buffer.clear() + serializer.toBinary(msg, buffer) + buffer.flip() + + // also make sure that the Array and ByteBuffer formats are equal, given LITTLE_ENDIAN + val array1 = new Array[Byte](buffer.remaining()) + buffer.get(array1) + val array2 = serializer.toBinary(msg) + ByteString(array1) should ===(ByteString(array2)) + + buffer.rewind() + serializer.fromBinary(buffer, "") should ===(msg) + } + + "LongSerializer" must { + Seq(0L, 1L, -1L, Long.MinValue, Long.MinValue + 1L, Long.MaxValue, Long.MaxValue - 1L) + .map(_.asInstanceOf[AnyRef]) + .foreach { item => + s"resolve serializer for value $item" in { + serialization.serializerFor(item.getClass).getClass should ===(classOf[LongSerializer]) + } + + s"serialize and de-serialize value $item" in { + verifySerialization(item) + } + + s"serialize and de-serialize value $item using ByteBuffers" in { + verifySerializationByteBuffer(item) + } + } + + "have right serializer id" in { + // checking because moved to akka-actor + serialization.serializerFor(1L.asInstanceOf[AnyRef].getClass).identifier === 18 + } + + } + + "IntSerializer" must { + Seq(0, 1, -1, Int.MinValue, Int.MinValue + 1, Int.MaxValue, Int.MaxValue - 1).map(_.asInstanceOf[AnyRef]).foreach { + item => + s"resolve serializer for value $item" in { + serialization.serializerFor(item.getClass).getClass should ===(classOf[IntSerializer]) + } + + s"serialize and de-serialize value $item" in { + verifySerialization(item) + } + + s"serialize and de-serialize value $item using ByteBuffers" in { + verifySerializationByteBuffer(item) + } + } + + "have right serializer id" in { + // checking because moved to akka-actor + serialization.serializerFor(1L.asInstanceOf[AnyRef].getClass).identifier === 19 + } + } + + "Boolean" must { + Seq(false, true, java.lang.Boolean.FALSE, java.lang.Boolean.TRUE).map(_.asInstanceOf[AnyRef]).zipWithIndex.foreach { + case (item, i) => + s"resolve serializer for value $item ($i)" in { + serialization.serializerFor(item.getClass).getClass should ===(classOf[BooleanSerializer]) + } + + s"serialize and de-serialize value $item ($i)" in { + verifySerialization(item) + } + + s"serialize and de-serialize value $item ($i) using ByteBuffers" in { + verifySerializationByteBuffer(item) + } + } + + "have right serializer id ($i)" in { + // checking because moved to akka-actor + serialization.serializerFor(true.asInstanceOf[AnyRef].getClass).identifier === 35 + } + } + + "StringSerializer" must { + val random = Random.nextString(256) + Seq("empty string" -> "", "hello" -> "hello", "árvíztűrőütvefúrógép" -> "árvíztűrőütvefúrógép", "random" -> random) + .foreach { + case (scenario, item) => + s"resolve serializer for [$scenario]" in { + serialization.serializerFor(item.getClass).getClass should ===(classOf[StringSerializer]) + } + + s"serialize and de-serialize [$scenario]" in { + verifySerialization(item) + } + + s"serialize and de-serialize value [$scenario] using ByteBuffers" in { + verifySerializationByteBuffer(item) + } + } + + "have right serializer id" in { + // checking because moved to akka-actor + serialization.serializerFor(1L.asInstanceOf[AnyRef].getClass).identifier === 20 + } + + } + + "ByteStringSerializer" must { + Seq( + "empty string" -> ByteString.empty, + "simple content" -> ByteString("hello"), + "concatenated content" -> (ByteString("hello") ++ ByteString("world")), + "sliced content" -> ByteString("helloabc").take(5), + "large concatenated" -> + (ByteString(Array.fill[Byte](1000)(1)) ++ ByteString(Array.fill[Byte](1000)(2)))).foreach { + case (scenario, item) => + s"resolve serializer for [$scenario]" in { + val serializer = SerializationExtension(system) + serializer.serializerFor(item.getClass).getClass should ===(classOf[ByteStringSerializer]) + } + + s"serialize and de-serialize [$scenario]" in { + verifySerialization(item) + } + + s"serialize and de-serialize value [$scenario] using ByteBuffers" in { + verifySerializationByteBuffer(item) + } + } + + "have right serializer id" in { + // checking because moved to akka-actor + serialization.serializerFor(1L.asInstanceOf[AnyRef].getClass).identifier === 21 + } + + } + +} diff --git a/akka-actor-tests/src/test/scala/akka/serialization/SerializationSetupSpec.scala b/akka-actor-tests/src/test/scala/akka/serialization/SerializationSetupSpec.scala index 0a637742e7..51caa6f93e 100644 --- a/akka-actor-tests/src/test/scala/akka/serialization/SerializationSetupSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/serialization/SerializationSetupSpec.scala @@ -11,11 +11,9 @@ import java.util.{ Date => SerializableDummy } import akka.actor.setup.ActorSystemSetup import akka.actor.{ ActorSystem, BootstrapSetup, ExtendedActorSystem } -import akka.testkit.{ AkkaSpec, TestKit, TestProbe } +import akka.testkit.{ AkkaSpec, TestKit } import com.typesafe.config.ConfigFactory -import scala.concurrent.duration._ - class ConfigurationDummy class ProgrammaticDummy @@ -58,6 +56,8 @@ object SerializationSetupSpec { akka { actor { serialize-messages = off + + allow-java-serialization = on # this is by default on, but tests are running with off, use defaults here warn-about-java-serializer-usage = on @@ -91,6 +91,14 @@ class SerializationSetupSpec import SerializationSetupSpec._ + private def verifySerialization(sys: ActorSystem, obj: AnyRef): Unit = { + val serialization = SerializationExtension(sys) + val bytes = serialization.serialize(obj).get + val serializer = serialization.findSerializerFor(obj) + val manifest = Serializers.manifestFor(serializer, obj) + serialization.deserialize(bytes, serializer.identifier, manifest).get + } + "The serialization settings" should { "allow for programmatic configuration of serializers" in { @@ -165,15 +173,18 @@ class SerializationSetupSpec } "have replaced java serializer" in { - val p = TestProbe()(addedJavaSerializationViaSettingsSystem) // only receiver has the serialization disabled + // allow-java-serialization = on in `system` + val serializer = SerializationExtension(system).findSerializerFor(new ProgrammaticJavaDummy) + serializer.getClass should ===(classOf[JavaSerializer]) - p.ref ! new ProgrammaticJavaDummy - SerializationExtension(system).findSerializerFor(new ProgrammaticJavaDummy).toBinary(new ProgrammaticJavaDummy) - // should not receive this one, it would have been java serialization! - p.expectNoMessage(100.millis) + // should not allow deserialization, it would have been java serialization! + val serializer2 = + SerializationExtension(addedJavaSerializationViaSettingsSystem).findSerializerFor(new ProgrammaticJavaDummy) + serializer2.getClass should ===(classOf[DisabledJavaSerializer]) + serializer2.identifier should ===(serializer.identifier) - p.ref ! new ProgrammaticDummy - p.expectMsgType[ProgrammaticDummy] + verifySerialization(system, new ProgrammaticDummy) + verifySerialization(addedJavaSerializationViaSettingsSystem, new ProgrammaticDummy) } "disable java serialization also for incoming messages if serializer id usually would have found the serializer" in { diff --git a/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala b/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala index bc09212173..4efe5905de 100644 --- a/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala @@ -5,14 +5,16 @@ package akka.serialization import language.postfixOps + import akka.testkit.{ AkkaSpec, EventFilter } import akka.actor._ import java.io._ import scala.concurrent.Await -import akka.util.{ unused, Timeout } +import akka.util.{ unused, Timeout } import scala.concurrent.duration._ + import com.typesafe.config._ import akka.pattern.ask import java.nio.ByteOrder @@ -22,6 +24,7 @@ import akka.actor.dungeon.SerializationCheckFailedException import com.github.ghik.silencer.silent import test.akka.serialization.NoVerification import SerializationTests._ +import akka.util.ByteString object SerializationTests { @@ -38,12 +41,12 @@ object SerializationTests { serialization-bindings { "akka.serialization.SerializationTests$$Person" = java "akka.serialization.SerializationTests$$Address" = java - "akka.serialization.TestSerializable" = test + "akka.serialization.SerializationTests$$Marker" = test "akka.serialization.SerializationTests$$PlainMessage" = test "akka.serialization.SerializationTests$$A" = java "akka.serialization.SerializationTests$$B" = test "akka.serialization.SerializationTests$$D" = test - "akka.serialization.TestSerializable2" = test2 + "akka.serialization.SerializationTests$$Marker2" = test2 "akka.serialization.SerializationTests$$AbstractOther" = other } } @@ -56,13 +59,15 @@ object SerializationTests { final case class Record(id: Int, person: Person) + protected[akka] trait Marker + protected[akka] trait Marker2 @silent // can't use unused otherwise case class below gets a deprecated - class SimpleMessage(s: String) extends TestSerializable + class SimpleMessage(s: String) extends Marker @silent class ExtendedSimpleMessage(s: String, i: Int) extends SimpleMessage(s) - trait AnotherInterface extends TestSerializable + trait AnotherInterface extends Marker class AnotherMessage extends AnotherInterface @@ -74,7 +79,7 @@ object SerializationTests { class BothTestSerializableAndJavaSerializable(s: String) extends SimpleMessage(s) with Serializable - class BothTestSerializableAndTestSerializable2(@unused s: String) extends TestSerializable with TestSerializable2 + class BothTestSerializableAndTestSerializable2(@unused s: String) extends Marker with Marker2 trait A trait B @@ -93,6 +98,7 @@ object SerializationTests { actor { serialize-messages = on serialize-creators = on + allow-java-serialization = on } } """ @@ -120,6 +126,18 @@ object SerializationTests { ActorSystem("SerializationSystem", mostlyReferenceConf) } + def allowJavaSerializationSystem: ActorSystem = { + val referenceConf = ConfigFactory.defaultReference() + val conf = ConfigFactory + .parseString(""" + akka.actor.warn-about-java-serializer-usage = on + akka.actor.allow-java-serialization = on + """) + .withFallback(ConfigFactory.parseString(serializeConf)) + .withFallback(AkkaSpec.testConf.withFallback(referenceConf)) + ActorSystem("SerializationSystem", conf) + } + val systemMessageMultiSerializerConf = """ akka { actor { @@ -139,36 +157,18 @@ object SerializationTests { class SerializeSpec extends AkkaSpec(SerializationTests.serializeConf) { val ser = SerializationExtension(system) - import ser._ val address = SerializationTests.Address("120", "Monroe Street", "Santa Clara", "95050") - val person = SerializationTests.Person( - "debasish ghosh", - 25, - SerializationTests.Address("120", "Monroe Street", "Santa Clara", "95050")) "Serialization" must { "have correct bindings" in { ser.bindings.collectFirst { case (c, s) if c == address.getClass => s.getClass } should ===( - Some(classOf[JavaSerializer])) + Some(classOf[DisabledJavaSerializer])) ser.bindings.collectFirst { case (c, s) if c == classOf[PlainMessage] => s.getClass } should ===( Some(classOf[NoopSerializer])) } - "serialize Address" in { - assert(deserialize(serialize(address).get, classOf[SerializationTests.Address]).get === address) - } - - "serialize Person" in { - assert(deserialize(serialize(person).get, classOf[Person]).get === person) - } - - "serialize record with default serializer" in { - val r = Record(100, person) - assert(deserialize(serialize(r).get, classOf[Record]).get === r) - } - "not serialize ActorCell" in { val a = system.actorOf(Props(new Actor { def receive = { @@ -182,25 +182,6 @@ class SerializeSpec extends AkkaSpec(SerializationTests.serializeConf) { system.stop(a) } - "serialize DeadLetterActorRef" in { - val outbuf = new ByteArrayOutputStream() - val out = new ObjectOutputStream(outbuf) - val a = ActorSystem("SerializeDeadLeterActorRef", AkkaSpec.testConf) - try { - out.writeObject(a.deadLetters) - out.flush() - out.close() - - val in = new ObjectInputStream(new ByteArrayInputStream(outbuf.toByteArray)) - JavaSerializer.currentSystem.withValue(a.asInstanceOf[ActorSystemImpl]) { - val deadLetters = in.readObject().asInstanceOf[DeadLetterActorRef] - (deadLetters eq a.deadLetters) should ===(true) - } - } finally { - shutdown(a) - } - } - "resolve serializer by direct interface" in { ser.serializerFor(classOf[SimpleMessage]).getClass should ===(classOf[NoopSerializer]) } @@ -237,14 +218,14 @@ class SerializeSpec extends AkkaSpec(SerializationTests.serializeConf) { } "resolve serializer in the order of the bindings" in { - ser.serializerFor(classOf[A]).getClass should ===(classOf[JavaSerializer]) + ser.serializerFor(classOf[A]).getClass should ===(classOf[DisabledJavaSerializer]) ser.serializerFor(classOf[B]).getClass should ===(classOf[NoopSerializer]) // JavaSerializer lower prio when multiple found ser.serializerFor(classOf[C]).getClass should ===(classOf[NoopSerializer]) } "resolve serializer in the order of most specific binding first" in { - ser.serializerFor(classOf[A]).getClass should ===(classOf[JavaSerializer]) + ser.serializerFor(classOf[A]).getClass should ===(classOf[DisabledJavaSerializer]) ser.serializerFor(classOf[D]).getClass should ===(classOf[NoopSerializer]) ser.serializerFor(classOf[E]).getClass should ===(classOf[NoopSerializer]) } @@ -337,15 +318,67 @@ class ReferenceSerializationSpec extends AkkaSpec(SerializationTests.mostlyRefer "Serialization settings from reference.conf" must { - "declare Serializable classes to be use JavaSerializer" in { - serializerMustBe(classOf[Serializable], classOf[JavaSerializer]) - serializerMustBe(classOf[String], classOf[JavaSerializer]) + "declare Serializable classes to be use DisabledJavaSerializer" in { + serializerMustBe(classOf[Serializable], classOf[DisabledJavaSerializer]) } "declare Array[Byte] to use ByteArraySerializer" in { serializerMustBe(classOf[Array[Byte]], classOf[ByteArraySerializer]) } + "declare Long, Int, String, ByteString to use primitive serializers" in { + serializerMustBe(classOf[java.lang.Long], classOf[LongSerializer]) + serializerMustBe(classOf[java.lang.Integer], classOf[IntSerializer]) + serializerMustBe(classOf[String], classOf[StringSerializer]) + serializerMustBe(classOf[ByteString.ByteString1], classOf[ByteStringSerializer]) + serializerMustBe(classOf[ByteString.ByteString1C], classOf[ByteStringSerializer]) + serializerMustBe(classOf[ByteString.ByteStrings], classOf[ByteStringSerializer]) + + } + + "not support serialization for other classes" in { + intercept[NotSerializableException] { ser.serializerFor(classOf[Object]) } + } + + "not allow serialize function" in { + val f = (i: Int) => i + 1 + serializerMustBe(f.getClass, classOf[DisabledJavaSerializer]) + } + + } +} + +class AllowJavaSerializationSpec extends AkkaSpec(SerializationTests.allowJavaSerializationSystem) { + + val ser = SerializationExtension(system) + def serializerMustBe(toSerialize: Class[_], expectedSerializer: Class[_]) = + ser.serializerFor(toSerialize).getClass should ===(expectedSerializer) + + val address = SerializationTests.Address("120", "Monroe Street", "Santa Clara", "95050") + val person = SerializationTests.Person( + "debasish ghosh", + 25, + SerializationTests.Address("120", "Monroe Street", "Santa Clara", "95050")) + + val messagePrefix = "Using the Java serializer for class" + + "Serialization settings with allow-java-serialization = on" must { + + "declare Serializable classes to be use JavaSerializer" in { + serializerMustBe(classOf[Serializable], classOf[JavaSerializer]) + } + + "declare Array[Byte] to use ByteArraySerializer" in { + serializerMustBe(classOf[Array[Byte]], classOf[ByteArraySerializer]) + } + + "declare Long, Int, String, ByteString to use primitive serializers" in { + serializerMustBe(classOf[java.lang.Long], classOf[LongSerializer]) + serializerMustBe(classOf[java.lang.Integer], classOf[IntSerializer]) + serializerMustBe(classOf[String], classOf[StringSerializer]) + serializerMustBe(classOf[ByteString.ByteString1], classOf[ByteStringSerializer]) + } + "not support serialization for other classes" in { intercept[NotSerializableException] { ser.serializerFor(classOf[Object]) } } @@ -359,17 +392,6 @@ class ReferenceSerializationSpec extends AkkaSpec(SerializationTests.mostlyRefer f2(3) should ===(4) } - } -} - -class DefaultSerializationWarningSpec - extends AkkaSpec(ConfigFactory.parseString("akka.actor.warn-about-java-serializer-usage = on")) { - - val ser = SerializationExtension(system) - val messagePrefix = "Using the default Java serializer for class" - - "Using the default Java serializer" must { - "log a warning when serializing classes outside of java.lang package" in { EventFilter.warning(start = messagePrefix, occurrences = 1).intercept { ser.serializerFor(classOf[java.math.BigDecimal]) @@ -382,20 +404,72 @@ class DefaultSerializationWarningSpec } } - } + "have correct bindings" in { + ser.bindings.collectFirst { case (c, s) if c == address.getClass => s.getClass } should ===( + Some(classOf[JavaSerializer])) + ser.bindings.collectFirst { case (c, s) if c == classOf[PlainMessage] => s.getClass } should ===( + Some(classOf[NoopSerializer])) + } + "serialize Address" in { + assert(ser.deserialize(ser.serialize(address).get, classOf[SerializationTests.Address]).get === address) + } + + "serialize Person" in { + assert(ser.deserialize(ser.serialize(person).get, classOf[Person]).get === person) + } + + "serialize record with Java serializer" in { + val r = Record(100, person) + assert(ser.deserialize(ser.serialize(r).get, classOf[Record]).get === r) + } + + "not serialize ActorCell" in { + val a = system.actorOf(Props(new Actor { + def receive = { + case o: ObjectOutputStream => + try o.writeObject(this) + catch { case _: NotSerializableException => testActor ! "pass" } + } + })) + a ! new ObjectOutputStream(new ByteArrayOutputStream()) + expectMsg("pass") + system.stop(a) + } + + "serialize DeadLetterActorRef" in { + val outbuf = new ByteArrayOutputStream() + val out = new ObjectOutputStream(outbuf) + val a = ActorSystem("SerializeDeadLeterActorRef", AkkaSpec.testConf) + try { + out.writeObject(a.deadLetters) + out.flush() + out.close() + + val in = new ObjectInputStream(new ByteArrayInputStream(outbuf.toByteArray)) + JavaSerializer.currentSystem.withValue(a.asInstanceOf[ActorSystemImpl]) { + val deadLetters = in.readObject().asInstanceOf[DeadLetterActorRef] + (deadLetters eq a.deadLetters) should ===(true) + } + } finally { + shutdown(a) + } + } + + } } class NoVerificationWarningSpec - extends AkkaSpec( - ConfigFactory.parseString( - "akka.actor.warn-about-java-serializer-usage = on\n" + - "akka.actor.warn-on-no-serialization-verification = on")) { + extends AkkaSpec(ConfigFactory.parseString(""" + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = on + akka.actor.warn-on-no-serialization-verification = on + """)) { val ser = SerializationExtension(system) - val messagePrefix = "Using the default Java serializer for class" + val messagePrefix = "Using the Java serializer for class" - "When warn-on-no-serialization-verification = on, using the default Java serializer" must { + "When warn-on-no-serialization-verification = on, using the Java serializer" must { "log a warning on classes without extending NoSerializationVerificationNeeded" in { EventFilter.warning(start = messagePrefix, occurrences = 1).intercept { @@ -412,15 +486,16 @@ class NoVerificationWarningSpec } class NoVerificationWarningOffSpec - extends AkkaSpec( - ConfigFactory.parseString( - "akka.actor.warn-about-java-serializer-usage = on\n" + - "akka.actor.warn-on-no-serialization-verification = off")) { + extends AkkaSpec(ConfigFactory.parseString(""" + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = on + akka.actor.warn-on-no-serialization-verification = off + """)) { val ser = SerializationExtension(system) - val messagePrefix = "Using the default Java serializer for class" + val messagePrefix = "Using the Java serializer for class" - "When warn-on-no-serialization-verification = off, using the default Java serializer" must { + "When warn-on-no-serialization-verification = off, using the Java serializer" must { "log a warning on classes without extending NoSerializationVerificationNeeded" in { EventFilter.warning(start = messagePrefix, occurrences = 1).intercept { @@ -436,9 +511,6 @@ class NoVerificationWarningOffSpec } } -protected[akka] trait TestSerializable -protected[akka] trait TestSerializable2 - protected[akka] class NoopSerializer extends Serializer { def includeManifest: Boolean = false diff --git a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/internal/ActorRefSerializationSpec.scala b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/internal/ActorRefSerializationSpec.scala index 856a90835d..2d35a6a427 100644 --- a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/internal/ActorRefSerializationSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/internal/ActorRefSerializationSpec.scala @@ -16,7 +16,9 @@ object ActorRefSerializationSpec { def config = ConfigFactory.parseString(""" akka.actor { serialize-messages = off - allow-java-serialization = true + # test is verifying Java serialization of ActorRef + allow-java-serialization = on + warn-about-java-serializer-usage = off } akka.remote.classic.netty.tcp.port = 0 akka.remote.artery.canonical.port = 0 diff --git a/akka-actor/src/main/resources/reference.conf b/akka-actor/src/main/resources/reference.conf index 1400ff1d5f..3903d052a4 100644 --- a/akka-actor/src/main/resources/reference.conf +++ b/akka-actor/src/main/resources/reference.conf @@ -705,13 +705,29 @@ akka { # # Please note that this option does not stop you from manually invoking java serialization # - # The default value for this might be changed to off in future versions of Akka. - allow-java-serialization = on + allow-java-serialization = off + + # Log warnings when the Java serialization is used to serialize messages. + # Java serialization is not very performant and should not be used in production + # environments unless you don't care about performance and security. In that case + # you can turn this off. + warn-about-java-serializer-usage = on + + # To be used with the above warn-about-java-serializer-usage + # When warn-about-java-serializer-usage = on, and this warn-on-no-serialization-verification = off, + # warnings are suppressed for classes extending NoSerializationVerificationNeeded + # to reduce noise. + warn-on-no-serialization-verification = on # Entries for pluggable serializers and their bindings. serializers { java = "akka.serialization.JavaSerializer" bytes = "akka.serialization.ByteArraySerializer" + primitive-long = "akka.serialization.LongSerializer" + primitive-int = "akka.serialization.IntSerializer" + primitive-string = "akka.serialization.StringSerializer" + primitive-bytestring = "akka.serialization.ByteStringSerializer" + primitive-boolean = "akka.serialization.BooleanSerializer" } # Class to Serializer binding. You only need to specify the name of an @@ -724,20 +740,19 @@ akka { serialization-bindings { "[B" = bytes "java.io.Serializable" = java + + "java.lang.String" = primitive-string + "akka.util.ByteString$ByteString1C" = primitive-bytestring + "akka.util.ByteString$ByteString1" = primitive-bytestring + "akka.util.ByteString$ByteStrings" = primitive-bytestring + "java.lang.Long" = primitive-long + "scala.Long" = primitive-long + "java.lang.Integer" = primitive-int + "scala.Int" = primitive-int + "java.lang.Boolean" = primitive-boolean + "scala.Boolean" = primitive-boolean } - # Log warnings when the default Java serialization is used to serialize messages. - # The default serializer uses Java serialization which is not very performant and should not - # be used in production environments unless you don't care about performance. In that case - # you can turn this off. - warn-about-java-serializer-usage = on - - # To be used with the above warn-about-java-serializer-usage - # When warn-about-java-serializer-usage = on, and this warn-on-no-serialization-verification = off, - # warnings are suppressed for classes extending NoSerializationVerificationNeeded - # to reduce noize. - warn-on-no-serialization-verification = on - # Configuration namespace of serialization identifiers. # Each serializer implementation must have an entry in the following format: # `akka.actor.serialization-identifiers."FQCN" = ID` @@ -747,6 +762,12 @@ akka { serialization-identifiers { "akka.serialization.JavaSerializer" = 1 "akka.serialization.ByteArraySerializer" = 4 + + primitive-long = 18 + primitive-int = 19 + primitive-string = 20 + primitive-bytestring = 21 + primitive-boolean = 35 } } diff --git a/akka-actor/src/main/scala/akka/serialization/PrimitiveSerializers.scala b/akka-actor/src/main/scala/akka/serialization/PrimitiveSerializers.scala new file mode 100644 index 0000000000..0920ec7144 --- /dev/null +++ b/akka-actor/src/main/scala/akka/serialization/PrimitiveSerializers.scala @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2018-2019 Lightbend Inc. + */ + +package akka.serialization + +import java.nio.{ BufferOverflowException, ByteBuffer } + +import akka.actor.ExtendedActorSystem +import akka.annotation.InternalApi +import akka.util.ByteString + +/** + * INTERNAL API: only public by configuration + */ +@InternalApi private[akka] final class LongSerializer(val system: ExtendedActorSystem) + extends Serializer + with ByteBufferSerializer { + override def includeManifest: Boolean = false + + override val identifier: Int = BaseSerializer.identifierFromConfig("primitive-long", system) + + override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = { + buf.putLong(Long.unbox(o)) + } + + override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = { + Long.box(buf.getLong) + } + + override def toBinary(o: AnyRef): Array[Byte] = { + val result = new Array[Byte](8) + var long = Long.unbox(o) + var i = 0 + while (long != 0) { + result(i) = (long & 0xFF).toByte + i += 1 + long >>>= 8 + } + result + } + + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = { + var result = 0L + var i = 7 + while (i >= 0) { + result <<= 8 + result |= (bytes(i).toLong & 0xFF) + i -= 1 + } + Long.box(result) + } +} + +/** + * INTERNAL API: only public by configuration + */ +@InternalApi private[akka] final class IntSerializer(val system: ExtendedActorSystem) + extends Serializer + with ByteBufferSerializer { + override def includeManifest: Boolean = false + + override val identifier: Int = BaseSerializer.identifierFromConfig("primitive-int", system) + + override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = buf.putInt(Int.unbox(o)) + + override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = Int.box(buf.getInt) + + override def toBinary(o: AnyRef): Array[Byte] = { + val result = new Array[Byte](4) + var int = Int.unbox(o) + var i = 0 + while (int != 0) { + result(i) = (int & 0xFF).toByte + i += 1 + int >>>= 8 + } + result + } + + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = { + var result = 0 + var i = 3 + while (i >= 0) { + result <<= 8 + result |= (bytes(i).toInt & 0xFF) + i -= 1 + } + Int.box(result) + } +} + +/** + * INTERNAL API: only public by configuration + */ +@InternalApi private[akka] final class StringSerializer(val system: ExtendedActorSystem) + extends Serializer + with ByteBufferSerializer { + override def includeManifest: Boolean = false + + override val identifier: Int = BaseSerializer.identifierFromConfig("primitive-string", system) + + override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = buf.put(toBinary(o)) + + override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = { + val bytes = new Array[Byte](buf.remaining()) + buf.get(bytes) + new String(bytes, "UTF-8") + } + + override def toBinary(o: AnyRef): Array[Byte] = o.asInstanceOf[String].getBytes("UTF-8") + + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = new String(bytes, "UTF-8") + +} + +/** + * INTERNAL API: only public by configuration + */ +@InternalApi private[akka] final class ByteStringSerializer(val system: ExtendedActorSystem) + extends Serializer + with ByteBufferSerializer { + override def includeManifest: Boolean = false + + override val identifier: Int = BaseSerializer.identifierFromConfig("primitive-bytestring", system) + + override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = { + val bs = o.asInstanceOf[ByteString] + + // ByteString.copyToBuffer does not throw BufferOverflowException + if (bs.copyToBuffer(buf) < bs.length) + throw new BufferOverflowException() + } + + override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = + ByteString.fromByteBuffer(buf) + + override def toBinary(o: AnyRef): Array[Byte] = { + val bs = o.asInstanceOf[ByteString] + val result = new Array[Byte](bs.length) + bs.copyToArray(result, 0, bs.length) + result + } + + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = { + ByteString(bytes) + } + +} + +/** + * INTERNAL API: only public by configuration + */ +@InternalApi private[akka] final class BooleanSerializer(val system: ExtendedActorSystem) + extends Serializer + with ByteBufferSerializer { + + import java.lang.Boolean.{ FALSE, TRUE } + + private val FalseB = 0.toByte + private val TrueB = 1.toByte + + override def includeManifest: Boolean = false + + override val identifier: Int = BaseSerializer.identifierFromConfig("primitive-boolean", system) + + override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = { + val flag = o match { + case TRUE => TrueB + case FALSE => FalseB + } + buf.put(flag) + } + + override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = { + buf.get() match { + case TrueB => TRUE + case FalseB => FALSE + } + } + + override def toBinary(o: AnyRef): Array[Byte] = { + val flag = o match { + case TRUE => TrueB + case FALSE => FalseB + } + val result = new Array[Byte](1) + result(0) = flag + result + } + + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = { + bytes(0) match { + case TrueB => TRUE + case FalseB => FALSE + } + } +} diff --git a/akka-actor/src/main/scala/akka/serialization/Serialization.scala b/akka-actor/src/main/scala/akka/serialization/Serialization.scala index e635b69c50..a06118c917 100644 --- a/akka-actor/src/main/scala/akka/serialization/Serialization.scala +++ b/akka-actor/src/main/scala/akka/serialization/Serialization.scala @@ -350,7 +350,7 @@ class Serialization(val system: ExtendedActorSystem) extends Extension { if (shouldWarnAboutJavaSerializer(clazz, ser)) { _log.warning( LogMarker.Security, - "Using the default Java serializer for class [{}] which is not recommended because of " + + "Using the Java serializer for class [{}] which is not recommended because of " + "performance implications. Use another serializer or disable this warning using the setting " + "'akka.actor.warn-about-java-serializer-usage'", clazz.getName) @@ -550,4 +550,5 @@ class Serialization(val system: ExtendedActorSystem) extends Extension { !serializedClass.getName.startsWith("java.lang.") && !suppressWarningOnNonSerializationVerification(serializedClass) } + } diff --git a/akka-actor/src/main/scala/akka/serialization/Serializer.scala b/akka-actor/src/main/scala/akka/serialization/Serializer.scala index ab03eebd9f..d360f402d5 100644 --- a/akka-actor/src/main/scala/akka/serialization/Serializer.scala +++ b/akka-actor/src/main/scala/akka/serialization/Serializer.scala @@ -4,18 +4,22 @@ package akka.serialization -import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, NotSerializableException, ObjectOutputStream } +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.NotSerializableException +import java.io.ObjectOutputStream import java.nio.ByteBuffer import java.util.concurrent.Callable -import akka.util.ClassLoaderObjectInputStream -import akka.actor.ExtendedActorSystem -import akka.annotation.InternalApi -import akka.event.{ LogMarker, Logging } - import scala.util.DynamicVariable import scala.util.control.NoStackTrace +import akka.actor.ExtendedActorSystem +import akka.annotation.InternalApi +import akka.event.LogMarker +import akka.event.Logging +import akka.util.ClassLoaderObjectInputStream + /** * A Serializer represents a bimap between an object and an array of bytes representing that object. * diff --git a/akka-bench-jmh/src/main/scala/akka/cluster/ddata/ORSetSerializationBenchmark.scala b/akka-bench-jmh/src/main/scala/akka/cluster/ddata/ORSetSerializationBenchmark.scala index 37fa2d2f06..b273bbba88 100644 --- a/akka-bench-jmh/src/main/scala/akka/cluster/ddata/ORSetSerializationBenchmark.scala +++ b/akka-bench-jmh/src/main/scala/akka/cluster/ddata/ORSetSerializationBenchmark.scala @@ -41,7 +41,6 @@ class ORSetSerializationBenchmark { akka.remote.artery.canonical.port = 0 akka.actor { serialize-messages = off - allow-java-serialization = off } """) diff --git a/akka-cluster-metrics/src/multi-jvm/scala/akka/cluster/metrics/ClusterMetricsRoutingSpec.scala b/akka-cluster-metrics/src/multi-jvm/scala/akka/cluster/metrics/ClusterMetricsRoutingSpec.scala index c1524cca4c..ab938f5dbb 100644 --- a/akka-cluster-metrics/src/multi-jvm/scala/akka/cluster/metrics/ClusterMetricsRoutingSpec.scala +++ b/akka-cluster-metrics/src/multi-jvm/scala/akka/cluster/metrics/ClusterMetricsRoutingSpec.scala @@ -9,6 +9,7 @@ import java.lang.management.ManagementFactory import scala.concurrent.Await import scala.concurrent.duration._ + import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import akka.actor._ @@ -23,6 +24,7 @@ import akka.routing.ActorRefRoutee import akka.routing.Routees import akka.cluster.routing.ClusterRouterPool import akka.cluster.routing.ClusterRouterPoolSettings +import akka.serialization.jackson.CborSerializable import akka.util.unused object AdaptiveLoadBalancingRouterConfig extends MultiNodeConfig { @@ -52,7 +54,7 @@ object AdaptiveLoadBalancingRouterConfig extends MultiNodeConfig { } case object AllocateMemory - final case class Reply(address: Address) + final case class Reply(address: Address) extends CborSerializable val node1 = role("node-1") val node2 = role("node-2") diff --git a/akka-cluster-metrics/src/multi-jvm/scala/akka/cluster/metrics/sample/StatsMessages.scala b/akka-cluster-metrics/src/multi-jvm/scala/akka/cluster/metrics/sample/StatsMessages.scala index 538c9c66a9..af9e3546cb 100644 --- a/akka-cluster-metrics/src/multi-jvm/scala/akka/cluster/metrics/sample/StatsMessages.scala +++ b/akka-cluster-metrics/src/multi-jvm/scala/akka/cluster/metrics/sample/StatsMessages.scala @@ -4,8 +4,10 @@ package akka.cluster.metrics.sample +import akka.serialization.jackson.CborSerializable + //#messages -final case class StatsJob(text: String) -final case class StatsResult(meanWordLength: Double) -final case class JobFailed(reason: String) +final case class StatsJob(text: String) extends CborSerializable +final case class StatsResult(meanWordLength: Double) extends CborSerializable +final case class JobFailed(reason: String) extends CborSerializable //#messages diff --git a/akka-cluster-metrics/src/test/resources/reference.conf b/akka-cluster-metrics/src/test/resources/reference.conf index c55b6c276f..8d53d6c3ea 100644 --- a/akka-cluster-metrics/src/test/resources/reference.conf +++ b/akka-cluster-metrics/src/test/resources/reference.conf @@ -1,7 +1,6 @@ akka { actor { - serialize-messages = on - warn-about-java-serializer-usage = off + serialize-messages = off } } diff --git a/akka-cluster-metrics/src/test/scala/akka/cluster/metrics/protobuf/MessageSerializerSpec.scala b/akka-cluster-metrics/src/test/scala/akka/cluster/metrics/protobuf/MessageSerializerSpec.scala index e6ddd70ffe..714de31b4d 100644 --- a/akka-cluster-metrics/src/test/scala/akka/cluster/metrics/protobuf/MessageSerializerSpec.scala +++ b/akka-cluster-metrics/src/test/scala/akka/cluster/metrics/protobuf/MessageSerializerSpec.scala @@ -13,7 +13,6 @@ import akka.cluster.TestMember class MessageSerializerSpec extends AkkaSpec(""" akka.actor.provider = cluster akka.actor.serialize-messages = off - akka.actor.allow-java-serialization = off """) { val serializer = new MessageSerializer(system.asInstanceOf[ExtendedActorSystem]) diff --git a/akka-cluster-sharding-typed/src/test/java/akka/cluster/sharding/typed/javadsl/ClusterShardingPersistenceTest.java b/akka-cluster-sharding-typed/src/test/java/akka/cluster/sharding/typed/javadsl/ClusterShardingPersistenceTest.java index 0264c198ba..6af13e7d8f 100644 --- a/akka-cluster-sharding-typed/src/test/java/akka/cluster/sharding/typed/javadsl/ClusterShardingPersistenceTest.java +++ b/akka-cluster-sharding-typed/src/test/java/akka/cluster/sharding/typed/javadsl/ClusterShardingPersistenceTest.java @@ -31,7 +31,8 @@ public class ClusterShardingPersistenceTest extends JUnitSuite { + "akka.remote.classic.netty.tcp.port = 0 \n" + "akka.remote.artery.canonical.port = 0 \n" + "akka.remote.artery.canonical.hostname = 127.0.0.1 \n" - + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n"); + + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n" + + "akka.persistence.journal.inmem.test-serialization = on \n"); @ClassRule public static final TestKitJunitResource testKit = new TestKitJunitResource(config); diff --git a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleTest.java b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleTest.java index ef3bf68bc1..b9694e69f5 100644 --- a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleTest.java +++ b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleTest.java @@ -35,7 +35,8 @@ public class AccountExampleTest extends JUnitSuite { + "akka.remote.classic.netty.tcp.port = 0 \n" + "akka.remote.artery.canonical.port = 0 \n" + "akka.remote.artery.canonical.hostname = 127.0.0.1 \n" - + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n"); + + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n" + + "akka.persistence.journal.inmem.test-serialization = on \n"); @ClassRule public static final TestKitJunitResource testKit = new TestKitJunitResource(config); @@ -142,4 +143,47 @@ public class AccountExampleTest extends JUnitSuite { .get(3, TimeUnit.SECONDS); assertEquals(BigDecimal.valueOf(90), balance); } + + @Test + public void verifySerialization() { + TestProbe opProbe = testKit.createTestProbe(); + testKit.serializationTestKit().verifySerialization(new CreateAccount(opProbe.getRef()), false); + Deposit deposit2 = + testKit + .serializationTestKit() + .verifySerialization(new Deposit(BigDecimal.valueOf(100), opProbe.getRef()), false); + assertEquals(BigDecimal.valueOf(100), deposit2.amount); + assertEquals(opProbe.getRef(), deposit2.replyTo()); + testKit + .serializationTestKit() + .verifySerialization(new Withdraw(BigDecimal.valueOf(90), opProbe.getRef()), false); + testKit.serializationTestKit().verifySerialization(new CloseAccount(opProbe.getRef()), false); + + testKit.serializationTestKit().verifySerialization(Confirmed.INSTANCE, false); + testKit.serializationTestKit().verifySerialization(new Rejected("overdraft"), false); + + TestProbe getProbe = testKit.createTestProbe(); + testKit.serializationTestKit().verifySerialization(new GetBalance(getProbe.getRef()), false); + + testKit + .serializationTestKit() + .verifySerialization(new CurrentBalance(BigDecimal.valueOf(100)), false); + + testKit.serializationTestKit().verifySerialization(new AccountCreated(), false); + testKit + .serializationTestKit() + .verifySerialization(new Deposited(BigDecimal.valueOf(100)), false); + testKit + .serializationTestKit() + .verifySerialization(new Withdrawn(BigDecimal.valueOf(90)), false); + testKit.serializationTestKit().verifySerialization(new AccountClosed(), false); + + testKit.serializationTestKit().verifySerialization(new EmptyAccount(), false); + OpenedAccount openedAccount2 = + testKit + .serializationTestKit() + .verifySerialization(new OpenedAccount(BigDecimal.valueOf(100)), false); + assertEquals(BigDecimal.valueOf(100), openedAccount2.balance); + testKit.serializationTestKit().verifySerialization(new ClosedAccount(), false); + } } diff --git a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithCommandHandlersInState.java b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithCommandHandlersInState.java deleted file mode 100644 index 06b8ca0686..0000000000 --- a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithCommandHandlersInState.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (C) 2018-2019 Lightbend Inc. - */ - -package jdocs.akka.cluster.sharding.typed; - -import akka.actor.typed.ActorRef; -import akka.actor.typed.Behavior; -import akka.actor.typed.javadsl.Behaviors; -import akka.cluster.sharding.typed.javadsl.EntityTypeKey; -import akka.cluster.sharding.typed.javadsl.EventSourcedEntityWithEnforcedReplies; -import akka.persistence.typed.ExpectingReply; -import akka.persistence.typed.PersistenceId; -import akka.persistence.typed.javadsl.CommandHandlerWithReply; -import akka.persistence.typed.javadsl.CommandHandlerWithReplyBuilder; -import akka.persistence.typed.javadsl.EventHandler; -import akka.persistence.typed.javadsl.EventHandlerBuilder; -import akka.persistence.typed.javadsl.ReplyEffect; - -import java.math.BigDecimal; - -/** - * Bank account example illustrating: - different state classes representing the lifecycle of the - * account - event handlers that delegate to methods in the state classes - command handlers that - * delegate to methods in the state classes - replies of various types, using ExpectingReply and - * EventSourcedBehaviorWithEnforcedReplies - */ -public interface AccountExampleWithCommandHandlersInState { - - // #account-entity - public class AccountEntity - extends EventSourcedEntityWithEnforcedReplies< - AccountEntity.AccountCommand, AccountEntity.AccountEvent, AccountEntity.Account> { - - public static final EntityTypeKey ENTITY_TYPE_KEY = - EntityTypeKey.create(AccountCommand.class, "Account"); - - // Command - interface AccountCommand extends ExpectingReply {} - - public static class CreateAccount implements AccountCommand { - private final ActorRef replyTo; - - public CreateAccount(ActorRef replyTo) { - this.replyTo = replyTo; - } - - @Override - public ActorRef replyTo() { - return replyTo; - } - } - - public static class Deposit implements AccountCommand { - public final BigDecimal amount; - private final ActorRef replyTo; - - public Deposit(BigDecimal amount, ActorRef replyTo) { - this.replyTo = replyTo; - this.amount = amount; - } - - @Override - public ActorRef replyTo() { - return replyTo; - } - } - - public static class Withdraw implements AccountCommand { - public final BigDecimal amount; - private final ActorRef replyTo; - - public Withdraw(BigDecimal amount, ActorRef replyTo) { - this.amount = amount; - this.replyTo = replyTo; - } - - @Override - public ActorRef replyTo() { - return replyTo; - } - } - - public static class GetBalance implements AccountCommand { - private final ActorRef replyTo; - - public GetBalance(ActorRef replyTo) { - this.replyTo = replyTo; - } - - @Override - public ActorRef replyTo() { - return replyTo; - } - } - - public static class CloseAccount implements AccountCommand { - private final ActorRef replyTo; - - public CloseAccount(ActorRef replyTo) { - this.replyTo = replyTo; - } - - @Override - public ActorRef replyTo() { - return replyTo; - } - } - - // Reply - interface AccountCommandReply {} - - interface OperationResult extends AccountCommandReply {} - - enum Confirmed implements OperationResult { - INSTANCE - } - - public static class Rejected implements OperationResult { - public final String reason; - - public Rejected(String reason) { - this.reason = reason; - } - } - - public static class CurrentBalance implements AccountCommandReply { - public final BigDecimal balance; - - public CurrentBalance(BigDecimal balance) { - this.balance = balance; - } - } - - // Event - interface AccountEvent {} - - public static class AccountCreated implements AccountEvent {} - - public static class Deposited implements AccountEvent { - public final BigDecimal amount; - - Deposited(BigDecimal amount) { - this.amount = amount; - } - } - - public static class Withdrawn implements AccountEvent { - public final BigDecimal amount; - - Withdrawn(BigDecimal amount) { - this.amount = amount; - } - } - - public static class AccountClosed implements AccountEvent {} - - // State - interface Account {} - - public class EmptyAccount implements Account { - ReplyEffect createAccount(CreateAccount command) { - return Effect() - .persist(new AccountCreated()) - .thenReply(command, account2 -> Confirmed.INSTANCE); - } - - OpenedAccount openedAccount() { - return new OpenedAccount(BigDecimal.ZERO); - } - } - - public class OpenedAccount implements Account { - public final BigDecimal balance; - - public OpenedAccount(BigDecimal balance) { - this.balance = balance; - } - - ReplyEffect deposit(Deposit command) { - return Effect() - .persist(new Deposited(command.amount)) - .thenReply(command, account2 -> Confirmed.INSTANCE); - } - - ReplyEffect withdraw(Withdraw command) { - if (!canWithdraw(command.amount)) { - return Effect() - .reply(command, new Rejected("not enough funds to withdraw " + command.amount)); - } else { - return Effect() - .persist(new Withdrawn(command.amount)) - .thenReply(command, account2 -> Confirmed.INSTANCE); - } - } - - ReplyEffect getBalance(GetBalance command) { - return Effect().reply(command, new CurrentBalance(balance)); - } - - ReplyEffect closeAccount(CloseAccount command) { - if (balance.equals(BigDecimal.ZERO)) { - return Effect() - .persist(new AccountClosed()) - .thenReply(command, account2 -> Confirmed.INSTANCE); - } else { - return Effect().reply(command, new Rejected("balance must be zero for closing account")); - } - } - - OpenedAccount makeDeposit(BigDecimal amount) { - return new OpenedAccount(balance.add(amount)); - } - - boolean canWithdraw(BigDecimal amount) { - return (balance.subtract(amount).compareTo(BigDecimal.ZERO) >= 0); - } - - OpenedAccount makeWithdraw(BigDecimal amount) { - if (!canWithdraw(amount)) - throw new IllegalStateException("Account balance can't be negative"); - return new OpenedAccount(balance.subtract(amount)); - } - - ClosedAccount closedAccount() { - return new ClosedAccount(); - } - } - - public static class ClosedAccount implements Account {} - - public static AccountEntity create(String accountNumber) { - return new AccountEntity(accountNumber); - } - - public AccountEntity(String accountNumber) { - super(ENTITY_TYPE_KEY, accountNumber); - } - - @Override - public Account emptyState() { - return new EmptyAccount(); - } - - @Override - public CommandHandlerWithReply commandHandler() { - CommandHandlerWithReplyBuilder builder = - newCommandHandlerWithReplyBuilder(); - - builder - .forStateType(EmptyAccount.class) - .onCommand(CreateAccount.class, EmptyAccount::createAccount); - - builder - .forStateType(OpenedAccount.class) - .onCommand(Deposit.class, OpenedAccount::deposit) - .onCommand(Withdraw.class, OpenedAccount::withdraw) - .onCommand(GetBalance.class, OpenedAccount::getBalance) - .onCommand(CloseAccount.class, OpenedAccount::closeAccount); - - builder - .forStateType(ClosedAccount.class) - .onAnyCommand(() -> Effect().unhandled().thenNoReply()); - - return builder.build(); - } - - @Override - public EventHandler eventHandler() { - EventHandlerBuilder builder = newEventHandlerBuilder(); - - builder - .forStateType(EmptyAccount.class) - .onEvent(AccountCreated.class, (account, event) -> account.openedAccount()); - - builder - .forStateType(OpenedAccount.class) - .onEvent( - Deposited.class, - (account, deposited) -> { - account.makeDeposit(deposited.amount); - return account; - }) - .onEvent( - Withdrawn.class, - (account, withdrawn) -> { - account.makeWithdraw(withdrawn.amount); - return account; - }) - .onEvent(AccountClosed.class, (account, closed) -> account.closedAccount()); - - return builder.build(); - } - } - - // #account-entity -} diff --git a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithEventHandlersInState.java b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithEventHandlersInState.java index 75a219db91..87756d81b0 100644 --- a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithEventHandlersInState.java +++ b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithEventHandlersInState.java @@ -13,6 +13,8 @@ import akka.persistence.typed.javadsl.CommandHandlerWithReplyBuilder; import akka.persistence.typed.javadsl.EventHandler; import akka.persistence.typed.javadsl.EventHandlerBuilder; import akka.persistence.typed.javadsl.ReplyEffect; +import akka.serialization.jackson.CborSerializable; +import com.fasterxml.jackson.annotation.JsonCreator; import java.math.BigDecimal; @@ -36,12 +38,13 @@ public interface AccountExampleWithEventHandlersInState { // Command // #reply-command - interface AccountCommand extends ExpectingReply {} + interface AccountCommand extends ExpectingReply, CborSerializable {} // #reply-command public static class CreateAccount implements AccountCommand { private final ActorRef replyTo; + @JsonCreator public CreateAccount(ActorRef replyTo) { this.replyTo = replyTo; } @@ -85,6 +88,7 @@ public interface AccountExampleWithEventHandlersInState { public static class GetBalance implements AccountCommand { private final ActorRef replyTo; + @JsonCreator public GetBalance(ActorRef replyTo) { this.replyTo = replyTo; } @@ -98,6 +102,7 @@ public interface AccountExampleWithEventHandlersInState { public static class CloseAccount implements AccountCommand { private final ActorRef replyTo; + @JsonCreator public CloseAccount(ActorRef replyTo) { this.replyTo = replyTo; } @@ -110,7 +115,7 @@ public interface AccountExampleWithEventHandlersInState { // Reply // #reply-command - interface AccountCommandReply {} + interface AccountCommandReply extends CborSerializable {} interface OperationResult extends AccountCommandReply {} @@ -121,6 +126,7 @@ public interface AccountExampleWithEventHandlersInState { public static class Rejected implements OperationResult { public final String reason; + @JsonCreator public Rejected(String reason) { this.reason = reason; } @@ -130,19 +136,21 @@ public interface AccountExampleWithEventHandlersInState { public static class CurrentBalance implements AccountCommandReply { public final BigDecimal balance; + @JsonCreator public CurrentBalance(BigDecimal balance) { this.balance = balance; } } // Event - interface AccountEvent {} + interface AccountEvent extends CborSerializable {} public static class AccountCreated implements AccountEvent {} public static class Deposited implements AccountEvent { public final BigDecimal amount; + @JsonCreator Deposited(BigDecimal amount) { this.amount = amount; } @@ -151,6 +159,7 @@ public interface AccountExampleWithEventHandlersInState { public static class Withdrawn implements AccountEvent { public final BigDecimal amount; + @JsonCreator Withdrawn(BigDecimal amount) { this.amount = amount; } @@ -159,7 +168,7 @@ public interface AccountExampleWithEventHandlersInState { public static class AccountClosed implements AccountEvent {} // State - interface Account {} + interface Account extends CborSerializable {} public static class EmptyAccount implements Account { OpenedAccount openedAccount() { @@ -168,8 +177,9 @@ public interface AccountExampleWithEventHandlersInState { } public static class OpenedAccount implements Account { - private final BigDecimal balance; + final BigDecimal balance; + @JsonCreator public OpenedAccount(BigDecimal balance) { this.balance = balance; } diff --git a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithMutableState.java b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithMutableState.java index c0cd2f5d22..db6d90bd9b 100644 --- a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithMutableState.java +++ b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithMutableState.java @@ -16,6 +16,8 @@ import akka.persistence.typed.javadsl.CommandHandlerWithReplyBuilder; import akka.persistence.typed.javadsl.EventHandler; import akka.persistence.typed.javadsl.EventHandlerBuilder; import akka.persistence.typed.javadsl.ReplyEffect; +import akka.serialization.jackson.CborSerializable; +import com.fasterxml.jackson.annotation.JsonCreator; import java.math.BigDecimal; @@ -36,11 +38,12 @@ public interface AccountExampleWithMutableState { EntityTypeKey.create(AccountCommand.class, "Account"); // Command - interface AccountCommand extends ExpectingReply {} + interface AccountCommand extends ExpectingReply, CborSerializable {} public static class CreateAccount implements AccountCommand { private final ActorRef replyTo; + @JsonCreator public CreateAccount(ActorRef replyTo) { this.replyTo = replyTo; } @@ -84,6 +87,7 @@ public interface AccountExampleWithMutableState { public static class GetBalance implements AccountCommand { private final ActorRef replyTo; + @JsonCreator public GetBalance(ActorRef replyTo) { this.replyTo = replyTo; } @@ -97,6 +101,7 @@ public interface AccountExampleWithMutableState { public static class CloseAccount implements AccountCommand { private final ActorRef replyTo; + @JsonCreator public CloseAccount(ActorRef replyTo) { this.replyTo = replyTo; } @@ -108,7 +113,7 @@ public interface AccountExampleWithMutableState { } // Reply - interface AccountCommandReply {} + interface AccountCommandReply extends CborSerializable {} interface OperationResult extends AccountCommandReply {} @@ -119,6 +124,7 @@ public interface AccountExampleWithMutableState { public static class Rejected implements OperationResult { public final String reason; + @JsonCreator public Rejected(String reason) { this.reason = reason; } @@ -127,19 +133,21 @@ public interface AccountExampleWithMutableState { public static class CurrentBalance implements AccountCommandReply { public final BigDecimal balance; + @JsonCreator public CurrentBalance(BigDecimal balance) { this.balance = balance; } } // Event - interface AccountEvent {} + interface AccountEvent extends CborSerializable {} public static class AccountCreated implements AccountEvent {} public static class Deposited implements AccountEvent { public final BigDecimal amount; + @JsonCreator Deposited(BigDecimal amount) { this.amount = amount; } @@ -148,6 +156,7 @@ public interface AccountExampleWithMutableState { public static class Withdrawn implements AccountEvent { public final BigDecimal amount; + @JsonCreator Withdrawn(BigDecimal amount) { this.amount = amount; } @@ -156,7 +165,7 @@ public interface AccountExampleWithMutableState { public static class AccountClosed implements AccountEvent {} // State - interface Account {} + interface Account extends CborSerializable {} public static class EmptyAccount implements Account { OpenedAccount openedAccount() { diff --git a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithNullState.java b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithNullState.java index 45253f4d8f..955c3bb64b 100644 --- a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithNullState.java +++ b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithNullState.java @@ -18,6 +18,8 @@ import akka.persistence.typed.javadsl.EventHandler; import akka.persistence.typed.javadsl.EventHandlerBuilder; import akka.persistence.typed.javadsl.EventSourcedBehaviorWithEnforcedReplies; import akka.persistence.typed.javadsl.ReplyEffect; +import akka.serialization.jackson.CborSerializable; +import com.fasterxml.jackson.annotation.JsonCreator; import java.math.BigDecimal; @@ -38,11 +40,12 @@ public interface AccountExampleWithNullState { EntityTypeKey.create(AccountCommand.class, "Account"); // Command - interface AccountCommand extends ExpectingReply {} + interface AccountCommand extends ExpectingReply, CborSerializable {} public static class CreateAccount implements AccountCommand { private final ActorRef replyTo; + @JsonCreator public CreateAccount(ActorRef replyTo) { this.replyTo = replyTo; } @@ -86,6 +89,7 @@ public interface AccountExampleWithNullState { public static class GetBalance implements AccountCommand { private final ActorRef replyTo; + @JsonCreator public GetBalance(ActorRef replyTo) { this.replyTo = replyTo; } @@ -99,6 +103,7 @@ public interface AccountExampleWithNullState { public static class CloseAccount implements AccountCommand { private final ActorRef replyTo; + @JsonCreator public CloseAccount(ActorRef replyTo) { this.replyTo = replyTo; } @@ -110,7 +115,7 @@ public interface AccountExampleWithNullState { } // Reply - interface AccountCommandReply {} + interface AccountCommandReply extends CborSerializable {} interface OperationResult extends AccountCommandReply {} @@ -121,6 +126,7 @@ public interface AccountExampleWithNullState { public static class Rejected implements OperationResult { public final String reason; + @JsonCreator public Rejected(String reason) { this.reason = reason; } @@ -129,19 +135,21 @@ public interface AccountExampleWithNullState { public static class CurrentBalance implements AccountCommandReply { public final BigDecimal balance; + @JsonCreator public CurrentBalance(BigDecimal balance) { this.balance = balance; } } // Event - interface AccountEvent {} + interface AccountEvent extends CborSerializable {} public static class AccountCreated implements AccountEvent {} public static class Deposited implements AccountEvent { public final BigDecimal amount; + @JsonCreator Deposited(BigDecimal amount) { this.amount = amount; } @@ -150,6 +158,7 @@ public interface AccountExampleWithNullState { public static class Withdrawn implements AccountEvent { public final BigDecimal amount; + @JsonCreator Withdrawn(BigDecimal amount) { this.amount = amount; } @@ -158,7 +167,7 @@ public interface AccountExampleWithNullState { public static class AccountClosed implements AccountEvent {} // State - interface Account {} + interface Account extends CborSerializable {} public static class OpenedAccount implements Account { public final BigDecimal balance; @@ -167,6 +176,7 @@ public interface AccountExampleWithNullState { this.balance = BigDecimal.ZERO; } + @JsonCreator public OpenedAccount(BigDecimal balance) { this.balance = balance; } @@ -273,18 +283,8 @@ public interface AccountExampleWithNullState { builder .forStateType(OpenedAccount.class) - .onEvent( - Deposited.class, - (account, deposited) -> { - account.makeDeposit(deposited.amount); - return account; - }) - .onEvent( - Withdrawn.class, - (account, withdrawn) -> { - account.makeWithdraw(withdrawn.amount); - return account; - }) + .onEvent(Deposited.class, (account, deposited) -> account.makeDeposit(deposited.amount)) + .onEvent(Withdrawn.class, (account, withdrawn) -> account.makeWithdraw(withdrawn.amount)) .onEvent(AccountClosed.class, (account, closed) -> account.closedAccount()); return builder.build(); diff --git a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/HelloWorldEventSourcedEntityExampleTest.java b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/HelloWorldEventSourcedEntityExampleTest.java index 132749ba5b..c2023d0b43 100644 --- a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/HelloWorldEventSourcedEntityExampleTest.java +++ b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/HelloWorldEventSourcedEntityExampleTest.java @@ -28,7 +28,8 @@ public class HelloWorldEventSourcedEntityExampleTest extends JUnitSuite { + "akka.remote.classic.netty.tcp.port = 0 \n" + "akka.remote.artery.canonical.port = 0 \n" + "akka.remote.artery.canonical.hostname = 127.0.0.1 \n" - + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n"); + + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n" + + "akka.persistence.journal.inmem.test-serialization = on \n"); @ClassRule public static final TestKitJunitResource testKit = new TestKitJunitResource(config); @@ -64,4 +65,20 @@ public class HelloWorldEventSourcedEntityExampleTest extends JUnitSuite { assertEquals("Bob", greeting2.whom); assertEquals(2, greeting2.numberOfPeople); } + + @Test + public void testSerialization() { + TestProbe probe = testKit.createTestProbe(HelloWorld.Greeting.class); + testKit + .serializationTestKit() + .verifySerialization(new HelloWorld.Greet("Alice", probe.getRef()), false); + + testKit.serializationTestKit().verifySerialization(new HelloWorld.Greeted("Alice"), false); + testKit.serializationTestKit().verifySerialization(new HelloWorld.Greeted("Alice"), false); + HelloWorld.KnownPeople state = new HelloWorld.KnownPeople(); + state = state.add("Alice").add("Bob"); + HelloWorld.KnownPeople state2 = + testKit.serializationTestKit().verifySerialization(state, false); + assertEquals(state.numberOfPeople(), state2.numberOfPeople()); + } } diff --git a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/HelloWorldPersistentEntityExample.java b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/HelloWorldPersistentEntityExample.java index c6217ce1ef..c75e9cc3b4 100644 --- a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/HelloWorldPersistentEntityExample.java +++ b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/HelloWorldPersistentEntityExample.java @@ -25,7 +25,9 @@ import akka.persistence.typed.javadsl.EventHandler; import akka.cluster.sharding.typed.javadsl.ClusterSharding; import akka.cluster.sharding.typed.javadsl.EntityRef; import akka.cluster.sharding.typed.javadsl.Entity; +import akka.serialization.jackson.CborSerializable; import akka.util.Timeout; +import com.fasterxml.jackson.annotation.JsonCreator; // #persistent-entity-usage-import public class HelloWorldPersistentEntityExample { @@ -65,7 +67,7 @@ public class HelloWorldPersistentEntityExample { extends EventSourcedEntity { // Command - interface Command {} + interface Command extends CborSerializable {} public static final class Greet implements Command { public final String whom; @@ -78,7 +80,7 @@ public class HelloWorldPersistentEntityExample { } // Response - public static final class Greeting { + public static final class Greeting implements CborSerializable { public final String whom; public final int numberOfPeople; @@ -89,16 +91,17 @@ public class HelloWorldPersistentEntityExample { } // Event - public static final class Greeted { + public static final class Greeted implements CborSerializable { public final String whom; + @JsonCreator public Greeted(String whom) { this.whom = whom; } } // State - static final class KnownPeople { + static final class KnownPeople implements CborSerializable { private Set names = Collections.emptySet(); KnownPeople() {} diff --git a/akka-cluster-sharding-typed/src/test/scala/akka/cluster/sharding/typed/scaladsl/ClusterShardingPersistenceSpec.scala b/akka-cluster-sharding-typed/src/test/scala/akka/cluster/sharding/typed/scaladsl/ClusterShardingPersistenceSpec.scala index 02e3b837a7..7b01a12943 100644 --- a/akka-cluster-sharding-typed/src/test/scala/akka/cluster/sharding/typed/scaladsl/ClusterShardingPersistenceSpec.scala +++ b/akka-cluster-sharding-typed/src/test/scala/akka/cluster/sharding/typed/scaladsl/ClusterShardingPersistenceSpec.scala @@ -45,6 +45,7 @@ object ClusterShardingPersistenceSpec { akka.remote.artery.canonical.hostname = 127.0.0.1 akka.persistence.journal.plugin = "akka.persistence.journal.inmem" + akka.persistence.journal.inmem.test-serialization = on """) sealed trait Command diff --git a/akka-cluster-sharding-typed/src/test/scala/akka/cluster/sharding/typed/scaladsl/ClusterShardingSpec.scala b/akka-cluster-sharding-typed/src/test/scala/akka/cluster/sharding/typed/scaladsl/ClusterShardingSpec.scala index 1e1be8cae3..63225b725c 100644 --- a/akka-cluster-sharding-typed/src/test/scala/akka/cluster/sharding/typed/scaladsl/ClusterShardingSpec.scala +++ b/akka-cluster-sharding-typed/src/test/scala/akka/cluster/sharding/typed/scaladsl/ClusterShardingSpec.scala @@ -51,8 +51,6 @@ object ClusterShardingSpec { akka.actor { serialize-messages = off - # issue #24465 missing serializer for GetShardRegionStats - #allow-java-serialization = off serializers { test = "akka.cluster.sharding.typed.scaladsl.ClusterShardingSpec$$Serializer" diff --git a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleSpec.scala b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleSpec.scala index b3108ca6d5..94da0a0fad 100644 --- a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleSpec.scala +++ b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleSpec.scala @@ -22,9 +22,10 @@ object AccountExampleSpec { akka.remote.classic.netty.tcp.port = 0 akka.remote.artery.canonical.port = 0 akka.remote.artery.canonical.hostname = 127.0.0.1 - + akka.persistence.journal.plugin = "akka.persistence.journal.inmem" - """) + akka.persistence.journal.inmem.test-serialization = on + """) } @@ -115,5 +116,30 @@ class AccountExampleSpec extends ScalaTestWithActorTestKit(AccountExampleSpec.co ref.ask(GetBalance(_)).map(_.balance).futureValue should ===(90) } + "verifySerialization" in { + val opProbe = createTestProbe[OperationResult]() + serializationTestKit.verifySerialization(CreateAccount(opProbe.ref)) + serializationTestKit.verifySerialization(Deposit(100, opProbe.ref)) + serializationTestKit.verifySerialization(Withdraw(90, opProbe.ref)) + serializationTestKit.verifySerialization(CloseAccount(opProbe.ref)) + + serializationTestKit.verifySerialization(Confirmed) + serializationTestKit.verifySerialization(Rejected("overdraft")) + + val getProbe = createTestProbe[CurrentBalance]() + serializationTestKit.verifySerialization(GetBalance(getProbe.ref)) + + serializationTestKit.verifySerialization(CurrentBalance(100)) + + serializationTestKit.verifySerialization(AccountCreated) + serializationTestKit.verifySerialization(Deposited(100)) + serializationTestKit.verifySerialization(Withdrawn(90)) + serializationTestKit.verifySerialization(AccountClosed) + + serializationTestKit.verifySerialization(EmptyAccount) + serializationTestKit.verifySerialization(OpenedAccount(100)) + serializationTestKit.verifySerialization(ClosedAccount) + } + } } diff --git a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithCommandHandlersInState.scala b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithCommandHandlersInState.scala index a22742a15b..57a232a6af 100644 --- a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithCommandHandlersInState.scala +++ b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithCommandHandlersInState.scala @@ -10,6 +10,7 @@ import akka.cluster.sharding.typed.scaladsl.EntityTypeKey import akka.cluster.sharding.typed.scaladsl.EventSourcedEntity import akka.persistence.typed.ExpectingReply import akka.persistence.typed.scaladsl.Effect +import akka.serialization.jackson.CborSerializable /** * Bank account example illustrating: @@ -23,7 +24,7 @@ object AccountExampleWithCommandHandlersInState { //#account-entity object AccountEntity { // Command - sealed trait AccountCommand[Reply] extends ExpectingReply[Reply] + sealed trait AccountCommand[Reply] extends ExpectingReply[Reply] with CborSerializable final case class CreateAccount(override val replyTo: ActorRef[OperationResult]) extends AccountCommand[OperationResult] final case class Deposit(amount: BigDecimal, override val replyTo: ActorRef[OperationResult]) @@ -35,14 +36,14 @@ object AccountExampleWithCommandHandlersInState { extends AccountCommand[OperationResult] // Reply - sealed trait AccountCommandReply + sealed trait AccountCommandReply extends CborSerializable sealed trait OperationResult extends AccountCommandReply case object Confirmed extends OperationResult final case class Rejected(reason: String) extends OperationResult final case class CurrentBalance(balance: BigDecimal) extends AccountCommandReply // Event - sealed trait AccountEvent + sealed trait AccountEvent extends CborSerializable case object AccountCreated extends AccountEvent case class Deposited(amount: BigDecimal) extends AccountEvent case class Withdrawn(amount: BigDecimal) extends AccountEvent @@ -54,7 +55,7 @@ object AccountExampleWithCommandHandlersInState { type ReplyEffect = akka.persistence.typed.scaladsl.ReplyEffect[AccountEvent, Account] // State - sealed trait Account { + sealed trait Account extends CborSerializable { def applyCommand(cmd: AccountCommand[_]): ReplyEffect def applyEvent(event: AccountEvent): Account } diff --git a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithEventHandlersInState.scala b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithEventHandlersInState.scala index f902bd67b9..5b49491c88 100644 --- a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithEventHandlersInState.scala +++ b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithEventHandlersInState.scala @@ -11,6 +11,7 @@ import akka.cluster.sharding.typed.scaladsl.EventSourcedEntity import akka.persistence.typed.ExpectingReply import akka.persistence.typed.scaladsl.Effect import akka.persistence.typed.scaladsl.ReplyEffect +import akka.serialization.jackson.CborSerializable /** * Bank account example illustrating: @@ -26,7 +27,7 @@ object AccountExampleWithEventHandlersInState { object AccountEntity { // Command //#reply-command - sealed trait AccountCommand[Reply <: AccountCommandReply] extends ExpectingReply[Reply] + sealed trait AccountCommand[Reply <: AccountCommandReply] extends ExpectingReply[Reply] with CborSerializable //#reply-command final case class CreateAccount(override val replyTo: ActorRef[OperationResult]) extends AccountCommand[OperationResult] @@ -42,7 +43,7 @@ object AccountExampleWithEventHandlersInState { // Reply //#reply-command - sealed trait AccountCommandReply + sealed trait AccountCommandReply extends CborSerializable sealed trait OperationResult extends AccountCommandReply case object Confirmed extends OperationResult final case class Rejected(reason: String) extends OperationResult @@ -50,7 +51,7 @@ object AccountExampleWithEventHandlersInState { final case class CurrentBalance(balance: BigDecimal) extends AccountCommandReply // Event - sealed trait AccountEvent + sealed trait AccountEvent extends CborSerializable case object AccountCreated extends AccountEvent case class Deposited(amount: BigDecimal) extends AccountEvent case class Withdrawn(amount: BigDecimal) extends AccountEvent @@ -59,7 +60,7 @@ object AccountExampleWithEventHandlersInState { val Zero = BigDecimal(0) // State - sealed trait Account { + sealed trait Account extends CborSerializable { def applyEvent(event: AccountEvent): Account } case object EmptyAccount extends Account { diff --git a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithOptionState.scala b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithOptionState.scala index e3cea3b68b..bba524eed1 100644 --- a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithOptionState.scala +++ b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithOptionState.scala @@ -10,6 +10,8 @@ import akka.cluster.sharding.typed.scaladsl.EntityTypeKey import akka.cluster.sharding.typed.scaladsl.EventSourcedEntity import akka.persistence.typed.ExpectingReply import akka.persistence.typed.scaladsl.Effect +import akka.serialization.jackson.CborSerializable +import akka.serialization.jackson.CborSerializable /** * Bank account example illustrating: @@ -23,7 +25,7 @@ object AccountExampleWithOptionState { //#account-entity object AccountEntity { // Command - sealed trait AccountCommand[Reply] extends ExpectingReply[Reply] + sealed trait AccountCommand[Reply] extends ExpectingReply[Reply] with CborSerializable final case class CreateAccount(override val replyTo: ActorRef[OperationResult]) extends AccountCommand[OperationResult] final case class Deposit(amount: BigDecimal, override val replyTo: ActorRef[OperationResult]) @@ -35,14 +37,14 @@ object AccountExampleWithOptionState { extends AccountCommand[OperationResult] // Reply - sealed trait AccountCommandReply + sealed trait AccountCommandReply extends CborSerializable sealed trait OperationResult extends AccountCommandReply case object Confirmed extends OperationResult final case class Rejected(reason: String) extends OperationResult final case class CurrentBalance(balance: BigDecimal) extends AccountCommandReply // Event - sealed trait AccountEvent + sealed trait AccountEvent extends CborSerializable case object AccountCreated extends AccountEvent case class Deposited(amount: BigDecimal) extends AccountEvent case class Withdrawn(amount: BigDecimal) extends AccountEvent @@ -54,7 +56,7 @@ object AccountExampleWithOptionState { type ReplyEffect = akka.persistence.typed.scaladsl.ReplyEffect[AccountEvent, Option[Account]] // State - sealed trait Account { + sealed trait Account extends CborSerializable { def applyCommand(cmd: AccountCommand[_]): ReplyEffect def applyEvent(event: AccountEvent): Account } diff --git a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/HelloWorldEventSourcedEntityExampleSpec.scala b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/HelloWorldEventSourcedEntityExampleSpec.scala index bf74a7aa5b..bac1eadbd3 100644 --- a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/HelloWorldEventSourcedEntityExampleSpec.scala +++ b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/HelloWorldEventSourcedEntityExampleSpec.scala @@ -21,6 +21,7 @@ object HelloWorldEventSourcedEntityExampleSpec { akka.remote.artery.canonical.hostname = 127.0.0.1 akka.persistence.journal.plugin = "akka.persistence.journal.inmem" + akka.persistence.journal.inmem.test-serialization = on """) } @@ -50,5 +51,12 @@ class HelloWorldEventSourcedEntityExampleSpec probe.expectMessage(Greeting("Bob", 2)) } + "verifySerialization" in { + val probe = createTestProbe[Greeting]() + serializationTestKit.verifySerialization(Greet("Alice")(probe.ref)) + serializationTestKit.verifySerialization(Greeting("Alice", 1)) + serializationTestKit.verifySerialization(KnownPeople(Set.empty).add("Alice").add("Bob")) + } + } } diff --git a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/HelloWorldPersistentEntityExample.scala b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/HelloWorldPersistentEntityExample.scala index 79da1c6e48..34ff0901c9 100644 --- a/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/HelloWorldPersistentEntityExample.scala +++ b/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/HelloWorldPersistentEntityExample.scala @@ -9,6 +9,7 @@ import scala.concurrent.duration._ import akka.actor.typed.ActorRef import akka.actor.typed.ActorSystem +import akka.serialization.jackson.CborSerializable object HelloWorldPersistentEntityExample { @@ -48,16 +49,16 @@ object HelloWorldPersistentEntityExample { object HelloWorld { // Command - trait Command + trait Command extends CborSerializable final case class Greet(whom: String)(val replyTo: ActorRef[Greeting]) extends Command // Response - final case class Greeting(whom: String, numberOfPeople: Int) + final case class Greeting(whom: String, numberOfPeople: Int) extends CborSerializable // Event - final case class Greeted(whom: String) + final case class Greeted(whom: String) extends CborSerializable // State - private final case class KnownPeople(names: Set[String]) { + final case class KnownPeople(names: Set[String]) extends CborSerializable { def add(name: String): KnownPeople = copy(names = names + name) def numberOfPeople: Int = names.size diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingCustomShardAllocationSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingCustomShardAllocationSpec.scala index 0f98befacf..b37a4ef402 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingCustomShardAllocationSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingCustomShardAllocationSpec.scala @@ -85,7 +85,9 @@ abstract class ClusterShardingCustomShardAllocationSpecConfig(val mode: String) val first = role("first") val second = role("second") - commonConfig(ConfigFactory.parseString(s""" + commonConfig( + ConfigFactory + .parseString(s""" akka.actor.provider = "cluster" akka.remote.log-remote-lifecycle-events = off akka.persistence.journal.plugin = "akka.persistence.journal.leveldb-shared" @@ -101,7 +103,9 @@ abstract class ClusterShardingCustomShardAllocationSpecConfig(val mode: String) akka.cluster.sharding.state-store-mode = "$mode" akka.cluster.sharding.rebalance-interval = 1 s #akka.cluster.sharding.retry-interval = 5 s - """).withFallback(MultiNodeClusterSpec.clusterConfig)) + """) + .withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) + .withFallback(MultiNodeClusterSpec.clusterConfig)) } object PersistentClusterShardingCustomShardAllocationSpecConfig diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingFailureSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingFailureSpec.scala index 8d6e98989f..f092fefc59 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingFailureSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingFailureSpec.scala @@ -7,8 +7,8 @@ package akka.cluster.sharding import java.io.File import akka.cluster.sharding.ShardRegion.Passivate - import scala.concurrent.duration._ + import org.apache.commons.io.FileUtils import com.typesafe.config.ConfigFactory import akka.actor._ @@ -21,14 +21,15 @@ import akka.remote.testkit.MultiNodeConfig import akka.remote.testkit.MultiNodeSpec import akka.remote.testkit.STMultiNodeSpec import akka.remote.transport.ThrottlerTransportAdapter.Direction +import akka.serialization.jackson.CborSerializable import akka.testkit._ import akka.util.ccompat._ @ccompatUsedUntil213 object ClusterShardingFailureSpec { - case class Get(id: String) - case class Add(id: String, i: Int) - case class Value(id: String, n: Int) + case class Get(id: String) extends CborSerializable + case class Add(id: String, i: Int) extends CborSerializable + case class Value(id: String, n: Int) extends CborSerializable class Entity extends Actor { var n = 0 @@ -56,7 +57,9 @@ abstract class ClusterShardingFailureSpecConfig(val mode: String) extends MultiN val first = role("first") val second = role("second") - commonConfig(ConfigFactory.parseString(s""" + commonConfig( + ConfigFactory + .parseString(s""" akka.loglevel = INFO akka.actor.provider = "cluster" akka.remote.classic.log-remote-lifecycle-events = off @@ -81,7 +84,14 @@ abstract class ClusterShardingFailureSpecConfig(val mode: String) extends MultiN dir = target/ClusterShardingFailureSpec/sharding-ddata map-size = 10 MiB } - """).withFallback(MultiNodeClusterSpec.clusterConfig)) + # using Java serialization for these messages because test is sending them + # to other nodes, which isn't normal usage. + akka.actor.serialization-bindings { + "${classOf[ShardRegion.Passivate].getName}" = java-test + } + """) + .withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) + .withFallback(MultiNodeClusterSpec.clusterConfig)) testTransport(on = true) } diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGetStateSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGetStateSpec.scala index 1cead11bfe..db06e71672 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGetStateSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGetStateSpec.scala @@ -11,13 +11,14 @@ import akka.remote.testconductor.RoleName import akka.remote.testkit.{ MultiNodeConfig, MultiNodeSpec, STMultiNodeSpec } import akka.testkit.TestProbe import com.typesafe.config.ConfigFactory - import scala.concurrent.duration._ +import akka.serialization.jackson.CborSerializable + object ClusterShardingGetStateSpec { - case object Stop - case class Ping(id: Long) - case object Pong + case object Stop extends CborSerializable + case class Ping(id: Long) extends CborSerializable + case object Pong extends CborSerializable class ShardedActor extends Actor with ActorLogging { log.info(self.path.toString) @@ -45,7 +46,7 @@ object ClusterShardingGetStateSpecConfig extends MultiNodeConfig { val first = role("first") val second = role("second") - commonConfig(ConfigFactory.parseString(""" + commonConfig(ConfigFactory.parseString(s""" akka.loglevel = INFO akka.actor.provider = "cluster" akka.remote.log-remote-lifecycle-events = off @@ -59,6 +60,12 @@ object ClusterShardingGetStateSpecConfig extends MultiNodeConfig { dir = target/ClusterShardingGetStateSpec/sharding-ddata map-size = 10 MiB } + # using Java serialization for these messages because test is sending them + # to other nodes, which isn't normal usage. + akka.actor.serialization-bindings { + "${ShardRegion.GetShardRegionState.getClass.getName}" = java-test + "${classOf[ShardRegion.CurrentShardRegionState].getName}" = java-test + } """).withFallback(MultiNodeClusterSpec.clusterConfig)) nodeConfig(first, second)(ConfigFactory.parseString("""akka.cluster.roles=["shard"]""")) diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGetStatsSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGetStatsSpec.scala index 9f50a7860c..e2dafbba1a 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGetStatsSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGetStatsSpec.scala @@ -10,13 +10,14 @@ import akka.remote.testconductor.RoleName import akka.remote.testkit.{ MultiNodeConfig, MultiNodeSpec, STMultiNodeSpec } import akka.testkit.{ TestDuration, TestProbe } import com.typesafe.config.ConfigFactory - import scala.concurrent.duration._ +import akka.serialization.jackson.CborSerializable + object ClusterShardingGetStatsSpec { - case object Stop - case class Ping(id: Long) - case object Pong + case object Stop extends CborSerializable + case class Ping(id: Long) extends CborSerializable + case object Pong extends CborSerializable class ShardedActor extends Actor with ActorLogging { log.info(s"entity started {}", self.path) @@ -60,7 +61,6 @@ object ClusterShardingGetStatsSpecConfig extends MultiNodeConfig { dir = target/ClusterShardingGetStatsSpec/sharding-ddata map-size = 10 MiB } - akka.actor.warn-about-java-serializer-usage=false """).withFallback(MultiNodeClusterSpec.clusterConfig)) nodeConfig(first, second, third)(ConfigFactory.parseString("""akka.cluster.roles=["shard"]""")) diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGracefulShutdownSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGracefulShutdownSpec.scala index 46eea5f152..80aabb4efa 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGracefulShutdownSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingGracefulShutdownSpec.scala @@ -46,7 +46,9 @@ abstract class ClusterShardingGracefulShutdownSpecConfig(val mode: String) exten val first = role("first") val second = role("second") - commonConfig(ConfigFactory.parseString(s""" + commonConfig( + ConfigFactory + .parseString(s""" akka.loglevel = INFO akka.actor.provider = "cluster" akka.remote.log-remote-lifecycle-events = off @@ -65,7 +67,9 @@ abstract class ClusterShardingGracefulShutdownSpecConfig(val mode: String) exten dir = target/ClusterShardingGracefulShutdownSpec/sharding-ddata map-size = 10 MiB } - """).withFallback(MultiNodeClusterSpec.clusterConfig)) + """) + .withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) + .withFallback(MultiNodeClusterSpec.clusterConfig)) } object PersistentClusterShardingGracefulShutdownSpecConfig diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingLeavingSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingLeavingSpec.scala index 13ee09f6c6..5552574e3b 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingLeavingSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingLeavingSpec.scala @@ -7,6 +7,7 @@ package akka.cluster.sharding import java.io.File import scala.concurrent.duration._ + import akka.actor.Actor import akka.actor.ActorIdentity import akka.actor.ActorRef @@ -20,12 +21,13 @@ import akka.remote.testconductor.RoleName import akka.remote.testkit.MultiNodeConfig import akka.remote.testkit.MultiNodeSpec import akka.remote.testkit.STMultiNodeSpec +import akka.serialization.jackson.CborSerializable import akka.testkit._ import com.typesafe.config.ConfigFactory import org.apache.commons.io.FileUtils object ClusterShardingLeavingSpec { - case class Ping(id: String) + case class Ping(id: String) extends CborSerializable class Entity extends Actor { def receive = { @@ -33,8 +35,8 @@ object ClusterShardingLeavingSpec { } } - case object GetLocations - case class Locations(locations: Map[String, ActorRef]) + case object GetLocations extends CborSerializable + case class Locations(locations: Map[String, ActorRef]) extends CborSerializable class ShardLocations extends Actor { var locations: Locations = _ @@ -59,7 +61,9 @@ abstract class ClusterShardingLeavingSpecConfig(val mode: String) extends MultiN val third = role("third") val fourth = role("fourth") - commonConfig(ConfigFactory.parseString(s""" + commonConfig( + ConfigFactory + .parseString(s""" akka.loglevel = INFO akka.actor.provider = "cluster" akka.remote.classic.log-remote-lifecycle-events = off @@ -79,7 +83,9 @@ abstract class ClusterShardingLeavingSpecConfig(val mode: String) extends MultiN dir = target/ClusterShardingLeavingSpec/sharding-ddata map-size = 10 MiB } - """).withFallback(MultiNodeClusterSpec.clusterConfig)) + """) + .withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) + .withFallback(MultiNodeClusterSpec.clusterConfig)) } object PersistentClusterShardingLeavingSpecConfig extends ClusterShardingLeavingSpecConfig("persistence") diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingMinMembersSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingMinMembersSpec.scala index c8f5ba9022..c19e44bf4f 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingMinMembersSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingMinMembersSpec.scala @@ -41,7 +41,9 @@ abstract class ClusterShardingMinMembersSpecConfig(val mode: String) extends Mul val second = role("second") val third = role("third") - commonConfig(ConfigFactory.parseString(s""" + commonConfig( + ConfigFactory + .parseString(s""" akka.loglevel = INFO akka.actor.provider = "cluster" akka.remote.log-remote-lifecycle-events = off @@ -62,7 +64,9 @@ abstract class ClusterShardingMinMembersSpecConfig(val mode: String) extends Mul map-size = 10 MiB } akka.cluster.min-nr-of-members = 3 - """).withFallback(MultiNodeClusterSpec.clusterConfig)) + """) + .withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) + .withFallback(MultiNodeClusterSpec.clusterConfig)) } object PersistentClusterShardingMinMembersSpecConfig extends ClusterShardingMinMembersSpecConfig("persistence") diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingRememberEntitiesNewExtractorSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingRememberEntitiesNewExtractorSpec.scala index a20ae526ed..2c8863c9e6 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingRememberEntitiesNewExtractorSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingRememberEntitiesNewExtractorSpec.scala @@ -57,7 +57,9 @@ abstract class ClusterShardingRememberEntitiesNewExtractorSpecConfig(val mode: S val second = role("second") val third = role("third") - commonConfig(ConfigFactory.parseString(s""" + commonConfig( + ConfigFactory + .parseString(s""" akka.actor.provider = "cluster" akka.cluster.auto-down-unreachable-after = 0s akka.remote.classic.log-remote-lifecycle-events = off @@ -76,7 +78,9 @@ abstract class ClusterShardingRememberEntitiesNewExtractorSpecConfig(val mode: S dir = target/ShardingRememberEntitiesNewExtractorSpec/sharding-ddata map-size = 10 MiB } - """).withFallback(MultiNodeClusterSpec.clusterConfig)) + """) + .withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) + .withFallback(MultiNodeClusterSpec.clusterConfig)) val roleConfig = ConfigFactory.parseString(""" akka.cluster.roles = [sharding] diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingRememberEntitiesSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingRememberEntitiesSpec.scala index aaace0a90e..1c0558597a 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingRememberEntitiesSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingRememberEntitiesSpec.scala @@ -51,7 +51,9 @@ abstract class ClusterShardingRememberEntitiesSpecConfig(val mode: String) exten val second = role("second") val third = role("third") - commonConfig(ConfigFactory.parseString(s""" + commonConfig( + ConfigFactory + .parseString(s""" akka.loglevel = INFO akka.actor.provider = "cluster" akka.cluster.auto-down-unreachable-after = 0s @@ -71,7 +73,9 @@ abstract class ClusterShardingRememberEntitiesSpecConfig(val mode: String) exten dir = target/ShardingRememberEntitiesSpec/sharding-ddata map-size = 10 MiB } - """).withFallback(MultiNodeClusterSpec.clusterConfig)) + """) + .withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) + .withFallback(MultiNodeClusterSpec.clusterConfig)) nodeConfig(third)(ConfigFactory.parseString(s""" akka.cluster.sharding.distributed-data.durable.lmdb { diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingSpec.scala index f7c243580d..15d8f0d55c 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingSpec.scala @@ -9,9 +9,9 @@ import akka.cluster.sharding.ShardCoordinator.Internal.{ HandOff, ShardStopped } import akka.cluster.sharding.ShardRegion.Passivate import akka.cluster.sharding.ShardRegion.GetCurrentRegions import akka.cluster.sharding.ShardRegion.CurrentRegions - import language.postfixOps import scala.concurrent.duration._ + import com.typesafe.config.ConfigFactory import akka.actor._ import akka.cluster.{ Cluster, MultiNodeClusterSpec } @@ -129,7 +129,9 @@ abstract class ClusterShardingSpecConfig(val mode: String, val entityRecoveryStr val fifth = role("fifth") val sixth = role("sixth") - commonConfig(ConfigFactory.parseString(s""" + commonConfig( + ConfigFactory + .parseString(s""" akka.loglevel = INFO akka.actor.provider = "cluster" akka.remote.log-remote-lifecycle-events = off @@ -165,7 +167,21 @@ abstract class ClusterShardingSpecConfig(val mode: String, val entityRecoveryStr } } akka.testconductor.barrier-timeout = 70s - """).withFallback(MultiNodeClusterSpec.clusterConfig)) + + # using Java serialization for the messages here because would be to much (unrelated) + # to show full Jackson serialization in docs (requires annotations because of envelope and such) + akka.actor.serialization-bindings { + "${ClusterShardingSpec.Increment.getClass.getName}" = java-test + "${ClusterShardingSpec.Decrement.getClass.getName}" = java-test + "${classOf[ClusterShardingSpec.Get].getName}" = java-test + "${classOf[ClusterShardingSpec.EntityEnvelope].getName}" = java-test + "${ClusterShardingSpec.Stop.getClass.getName}" = java-test + "${classOf[ClusterShardingSpec.CounterChanged].getName}" = java-test + } + + """) + .withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) + .withFallback(MultiNodeClusterSpec.clusterConfig)) nodeConfig(sixth) { ConfigFactory.parseString("""akka.cluster.roles = ["frontend"]""") } diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/MultiDcClusterShardingSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/MultiDcClusterShardingSpec.scala index 4b29f2b301..f0debccf94 100644 --- a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/MultiDcClusterShardingSpec.scala +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/MultiDcClusterShardingSpec.scala @@ -5,6 +5,7 @@ package akka.cluster.sharding import scala.concurrent.duration._ + import akka.actor.Actor import akka.actor.ActorRef import akka.actor.Address @@ -16,13 +17,14 @@ import akka.remote.testconductor.RoleName import akka.remote.testkit.MultiNodeConfig import akka.remote.testkit.MultiNodeSpec import akka.remote.testkit.STMultiNodeSpec +import akka.serialization.jackson.CborSerializable import akka.testkit._ import com.typesafe.config.ConfigFactory import akka.util.ccompat._ @ccompatUsedUntil213 object MultiDcClusterShardingSpec { - sealed trait EntityMsg { + sealed trait EntityMsg extends CborSerializable { def id: String } final case class Ping(id: String) extends EntityMsg diff --git a/akka-cluster-sharding/src/test/resources/reference.conf b/akka-cluster-sharding/src/test/resources/reference.conf index c55b6c276f..8d53d6c3ea 100644 --- a/akka-cluster-sharding/src/test/resources/reference.conf +++ b/akka-cluster-sharding/src/test/resources/reference.conf @@ -1,7 +1,6 @@ akka { actor { - serialize-messages = on - warn-about-java-serializer-usage = off + serialize-messages = off } } diff --git a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/TestLeaseActor.scala b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/TestLeaseActor.scala index fac0362be0..c5e63c49d7 100644 --- a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/TestLeaseActor.scala +++ b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/TestLeaseActor.scala @@ -8,6 +8,7 @@ import java.util.concurrent.atomic.AtomicReference import scala.concurrent.Future import scala.concurrent.duration._ + import akka.actor.Actor import akka.actor.ActorLogging import akka.actor.ActorRef @@ -22,20 +23,21 @@ import akka.event.Logging import akka.coordination.lease.LeaseSettings import akka.coordination.lease.scaladsl.Lease import akka.pattern.ask +import akka.testkit.JavaSerializable import akka.util.Timeout object TestLeaseActor { def props(): Props = Props(new TestLeaseActor) - sealed trait LeaseRequest + sealed trait LeaseRequest extends JavaSerializable final case class Acquire(owner: String) extends LeaseRequest final case class Release(owner: String) extends LeaseRequest - final case class Create(leaseName: String, ownerName: String) + final case class Create(leaseName: String, ownerName: String) extends JavaSerializable - final case object GetRequests - final case class LeaseRequests(requests: List[LeaseRequest]) - final case class ActionRequest(request: LeaseRequest, result: Any) // boolean of Failure + final case object GetRequests extends JavaSerializable + final case class LeaseRequests(requests: List[LeaseRequest]) extends JavaSerializable + final case class ActionRequest(request: LeaseRequest, result: Any) extends JavaSerializable // boolean of Failure } class TestLeaseActor extends Actor with ActorLogging { diff --git a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/client/ClusterClientSpec.scala b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/client/ClusterClientSpec.scala index 453af0a75d..bdf601a867 100644 --- a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/client/ClusterClientSpec.scala +++ b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/client/ClusterClientSpec.scala @@ -57,7 +57,7 @@ object ClusterClientSpec extends MultiNodeConfig { testTransport(on = true) - case class Reply(msg: Any, node: Address) + case class Reply(msg: Any, node: Address) extends JavaSerializable class TestService(testActor: ActorRef) extends Actor { def receive = { diff --git a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerLeaseSpec.scala b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerLeaseSpec.scala index 4e1bd2311d..8862921e94 100644 --- a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerLeaseSpec.scala +++ b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerLeaseSpec.scala @@ -43,7 +43,7 @@ object ClusterSingletonManagerLeaseSpec extends MultiNodeConfig { nodeConfig(first, second, third)(ConfigFactory.parseString("akka.cluster.roles = [worker]")) object ImportantSingleton { - case class Response(msg: Any, address: Address) + case class Response(msg: Any, address: Address) extends JavaSerializable def props(): Props = Props(new ImportantSingleton()) } diff --git a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerSpec.scala b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerSpec.scala index 947006d5fb..8c7b371aa7 100644 --- a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerSpec.scala +++ b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerSpec.scala @@ -6,6 +6,7 @@ package akka.cluster.singleton import language.postfixOps import scala.concurrent.duration._ + import com.typesafe.config.ConfigFactory import akka.actor.Actor import akka.actor.ActorLogging @@ -23,6 +24,7 @@ import akka.testkit.TestEvent._ import akka.actor.Identify import akka.actor.ActorIdentity import akka.actor.ActorSelection +import akka.serialization.jackson.CborSerializable object ClusterSingletonManagerSpec extends MultiNodeConfig { val controller = role("controller") @@ -45,15 +47,15 @@ object ClusterSingletonManagerSpec extends MultiNodeConfig { //#singleton-message-classes object PointToPointChannel { - case object UnregistrationOk + case object UnregistrationOk extends CborSerializable //#singleton-message-classes - case object RegisterConsumer - case object UnregisterConsumer - case object RegistrationOk - case object UnexpectedRegistration - case object UnexpectedUnregistration - case object Reset - case object ResetOk + case object RegisterConsumer extends CborSerializable + case object UnregisterConsumer extends CborSerializable + case object RegistrationOk extends CborSerializable + case object UnexpectedRegistration extends CborSerializable + case object UnexpectedUnregistration extends CborSerializable + case object Reset extends CborSerializable + case object ResetOk extends CborSerializable //#singleton-message-classes } //#singleton-message-classes @@ -105,10 +107,10 @@ object ClusterSingletonManagerSpec extends MultiNodeConfig { //#singleton-message-classes object Consumer { - case object End - case object GetCurrent - case object Ping - case object Pong + case object End extends CborSerializable + case object GetCurrent extends CborSerializable + case object Ping extends CborSerializable + case object Pong extends CborSerializable } //#singleton-message-classes diff --git a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/MultiDcSingletonManagerSpec.scala b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/MultiDcSingletonManagerSpec.scala index 968d7ee44c..561b685ca2 100644 --- a/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/MultiDcSingletonManagerSpec.scala +++ b/akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/MultiDcSingletonManagerSpec.scala @@ -7,13 +7,12 @@ package akka.cluster.singleton import scala.concurrent.duration._ import com.typesafe.config.ConfigFactory - import akka.actor.{ Actor, ActorLogging, Address, PoisonPill, Props } import akka.cluster.Cluster - import akka.testkit.ImplicitSender import akka.remote.testkit.{ MultiNodeConfig, MultiNodeSpec, STMultiNodeSpec } import akka.cluster.ClusterSettings +import akka.serialization.jackson.CborSerializable object MultiDcSingletonManagerSpec extends MultiNodeConfig { val controller = role("controller") @@ -60,8 +59,8 @@ class MultiDcSingleton extends Actor with ActorLogging { } } object MultiDcSingleton { - case object Ping - case class Pong(fromDc: String, fromAddress: Address, roles: Set[String]) + case object Ping extends CborSerializable + case class Pong(fromDc: String, fromAddress: Address, roles: Set[String]) extends CborSerializable } abstract class MultiDcSingletonManagerSpec diff --git a/akka-cluster-tools/src/test/resources/reference.conf b/akka-cluster-tools/src/test/resources/reference.conf index c55b6c276f..8d53d6c3ea 100644 --- a/akka-cluster-tools/src/test/resources/reference.conf +++ b/akka-cluster-tools/src/test/resources/reference.conf @@ -1,7 +1,6 @@ akka { actor { - serialize-messages = on - warn-about-java-serializer-usage = off + serialize-messages = off } } diff --git a/akka-cluster-tools/src/test/scala/akka/cluster/singleton/ClusterSingletonLeaseSpec.scala b/akka-cluster-tools/src/test/scala/akka/cluster/singleton/ClusterSingletonLeaseSpec.scala index 4fe5e5975f..9aa677f66d 100644 --- a/akka-cluster-tools/src/test/scala/akka/cluster/singleton/ClusterSingletonLeaseSpec.scala +++ b/akka-cluster-tools/src/test/scala/akka/cluster/singleton/ClusterSingletonLeaseSpec.scala @@ -6,16 +6,27 @@ package akka.cluster.singleton import java.util.concurrent.atomic.AtomicInteger -import akka.actor.{ Actor, ActorLogging, ActorRef, ExtendedActorSystem, PoisonPill, Props } -import akka.cluster.TestLease.{ AcquireReq, ReleaseReq } -import akka.cluster.{ Cluster, MemberStatus, TestLease, TestLeaseExt } -import akka.testkit.{ AkkaSpec, TestProbe } -import com.typesafe.config.ConfigFactory - import scala.concurrent.Promise import scala.concurrent.duration._ import scala.util.Success +import akka.actor.Actor +import akka.actor.ActorLogging +import akka.actor.ActorRef +import akka.actor.ExtendedActorSystem +import akka.actor.PoisonPill +import akka.actor.Props +import akka.cluster.Cluster +import akka.cluster.MemberStatus +import akka.cluster.TestLease +import akka.cluster.TestLease.AcquireReq +import akka.cluster.TestLease.ReleaseReq +import akka.cluster.TestLeaseExt +import akka.testkit.AkkaSpec +import akka.testkit.TestException +import akka.testkit.TestProbe +import com.typesafe.config.ConfigFactory + class ImportantSingleton(lifeCycleProbe: ActorRef) extends Actor with ActorLogging { override def preStart(): Unit = { @@ -129,7 +140,7 @@ class ClusterSingletonLeaseSpec extends AkkaSpec(ConfigFactory.parseString(""" testLeaseExt.getTestLease(leaseNameFor(settings)) } // allow singleton manager to create the lease probe.expectNoMessage(shortDuration) - testLease.initialPromise.failure(new RuntimeException("no lease for you")) + testLease.initialPromise.failure(TestException("no lease for you")) probe.expectNoMessage(shortDuration) } @@ -146,7 +157,7 @@ class ClusterSingletonLeaseSpec extends AkkaSpec(ConfigFactory.parseString(""" singletonProbe.expectNoMessage(shortDuration) val nextResponse = Promise[Boolean] testLease.setNextAcquireResult(nextResponse.future) - testLease.initialPromise.failure(new RuntimeException("no lease for you")) + testLease.initialPromise.failure(TestException("no lease for you")) testLease.probe.expectMsg(AcquireReq(leaseOwner)) singletonProbe.expectNoMessage(shortDuration) nextResponse.complete(Success(true)) diff --git a/akka-cluster-tools/src/test/scala/akka/cluster/singleton/ClusterSingletonRestart2Spec.scala b/akka-cluster-tools/src/test/scala/akka/cluster/singleton/ClusterSingletonRestart2Spec.scala index 5a23c02d72..fc3e8fa2d9 100644 --- a/akka-cluster-tools/src/test/scala/akka/cluster/singleton/ClusterSingletonRestart2Spec.scala +++ b/akka-cluster-tools/src/test/scala/akka/cluster/singleton/ClusterSingletonRestart2Spec.scala @@ -26,7 +26,8 @@ object ClusterSingletonRestart2Spec { } } -class ClusterSingletonRestart2Spec extends AkkaSpec(""" +class ClusterSingletonRestart2Spec + extends AkkaSpec(""" akka.loglevel = INFO akka.cluster.roles = [singleton] akka.actor.provider = akka.cluster.ClusterActorRefProvider @@ -42,6 +43,10 @@ class ClusterSingletonRestart2Spec extends AkkaSpec(""" port = 0 } } + akka.actor.serialization-bindings { + # there is no serializer for UniqueAddress, not intended to be sent as a standalone message + "akka.cluster.UniqueAddress" = jackson-cbor + } """) { val sys1 = ActorSystem(system.name, system.settings.config) diff --git a/akka-cluster-typed/src/multi-jvm/scala/akka/cluster/typed/MultiDcClusterActors.scala b/akka-cluster-typed/src/multi-jvm/scala/akka/cluster/typed/MultiDcClusterActors.scala index 77041aa12b..ab0c2eaeac 100644 --- a/akka-cluster-typed/src/multi-jvm/scala/akka/cluster/typed/MultiDcClusterActors.scala +++ b/akka-cluster-typed/src/multi-jvm/scala/akka/cluster/typed/MultiDcClusterActors.scala @@ -6,10 +6,11 @@ package akka.cluster.typed import akka.actor.typed.ActorRef import akka.actor.typed.scaladsl.Behaviors +import akka.serialization.jackson.CborSerializable object MultiDcClusterActors { - case class Pong(dc: String) - sealed trait PingProtocol + case class Pong(dc: String) extends CborSerializable + sealed trait PingProtocol extends CborSerializable case class Ping(ref: ActorRef[Pong]) extends PingProtocol case object NoMore extends PingProtocol diff --git a/akka-cluster-typed/src/test/java/akka/cluster/typed/ClusterApiTest.java b/akka-cluster-typed/src/test/java/akka/cluster/typed/ClusterApiTest.java index c8f18a3d07..b561582902 100644 --- a/akka-cluster-typed/src/test/java/akka/cluster/typed/ClusterApiTest.java +++ b/akka-cluster-typed/src/test/java/akka/cluster/typed/ClusterApiTest.java @@ -29,7 +29,6 @@ public class ClusterApiTest extends JUnitSuite { + "akka.coordinated-shutdown.run-by-actor-system-terminate = off \n" + "akka.actor { \n" + " serialize-messages = off \n" - + " allow-java-serialization = off \n" + "}"); ActorSystem system1 = diff --git a/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterApiSpec.scala b/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterApiSpec.scala index eaae8a6dd3..b8f28d5a75 100644 --- a/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterApiSpec.scala +++ b/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterApiSpec.scala @@ -27,7 +27,6 @@ object ClusterApiSpec { akka.coordinated-shutdown.run-by-actor-system-terminate = off akka.actor { serialize-messages = off - allow-java-serialization = off } # generous timeout for cluster forming probes akka.actor.testkit.typed.default-timeout = 10s diff --git a/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterSingletonApiSpec.scala b/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterSingletonApiSpec.scala index 997ee2a779..52899537c5 100644 --- a/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterSingletonApiSpec.scala +++ b/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterSingletonApiSpec.scala @@ -26,7 +26,6 @@ object ClusterSingletonApiSpec { akka.actor { provider = cluster serialize-messages = off - allow-java-serialization = off serializers { test = "akka.cluster.typed.ClusterSingletonApiSpec$$PingSerializer" diff --git a/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterSingletonPersistenceSpec.scala b/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterSingletonPersistenceSpec.scala index f35bfab4c3..254ce0feac 100644 --- a/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterSingletonPersistenceSpec.scala +++ b/akka-cluster-typed/src/test/scala/akka/cluster/typed/ClusterSingletonPersistenceSpec.scala @@ -24,7 +24,6 @@ object ClusterSingletonPersistenceSpec { akka.actor { serialize-messages = off - allow-java-serialization = off } akka.persistence.journal.plugin = "akka.persistence.journal.inmem" diff --git a/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteContextAskSpec.scala b/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteContextAskSpec.scala index 937732b0ef..a3a6bda710 100644 --- a/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteContextAskSpec.scala +++ b/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteContextAskSpec.scala @@ -48,7 +48,6 @@ object RemoteContextAskSpec { loglevel = debug actor { provider = cluster - warn-about-java-serializer-usage = off serialize-creators = off serializers { test = "akka.cluster.typed.RemoteContextAskSpecSerializer" diff --git a/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteDeployNotAllowedSpec.scala b/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteDeployNotAllowedSpec.scala index 0a9b7327fe..df5f7bfaea 100644 --- a/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteDeployNotAllowedSpec.scala +++ b/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteDeployNotAllowedSpec.scala @@ -20,7 +20,6 @@ object RemoteDeployNotAllowedSpec { loglevel = warning actor { provider = cluster - warn-about-java-serializer-usage = off serialize-creators = off } remote.classic.netty.tcp.port = 0 diff --git a/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteMessageSpec.scala b/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteMessageSpec.scala index baabb38425..10759425b1 100644 --- a/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteMessageSpec.scala +++ b/akka-cluster-typed/src/test/scala/akka/cluster/typed/RemoteMessageSpec.scala @@ -13,8 +13,8 @@ import akka.actor.typed.scaladsl.Behaviors import akka.actor.{ ExtendedActorSystem, ActorSystem => UntypedActorSystem } import akka.serialization.SerializerWithStringManifest import com.typesafe.config.ConfigFactory - import scala.concurrent.Promise + import akka.actor.typed.scaladsl.adapter._ class PingSerializer(system: ExtendedActorSystem) extends SerializerWithStringManifest { @@ -37,7 +37,6 @@ object RemoteMessageSpec { loglevel = debug actor { provider = cluster - warn-about-java-serializer-usage = off serialize-creators = off serializers { test = "akka.cluster.typed.PingSerializer" diff --git a/akka-cluster-typed/src/test/scala/akka/cluster/typed/internal/receptionist/ClusterReceptionistSpec.scala b/akka-cluster-typed/src/test/scala/akka/cluster/typed/internal/receptionist/ClusterReceptionistSpec.scala index f5ad771930..bb7c685e72 100644 --- a/akka-cluster-typed/src/test/scala/akka/cluster/typed/internal/receptionist/ClusterReceptionistSpec.scala +++ b/akka-cluster-typed/src/test/scala/akka/cluster/typed/internal/receptionist/ClusterReceptionistSpec.scala @@ -31,7 +31,6 @@ object ClusterReceptionistSpec { akka.actor { provider = cluster serialize-messages = off - allow-java-serialization = true serializers { test = "akka.cluster.typed.internal.receptionist.ClusterReceptionistSpec$$PingSerializer" } diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/ClusterDeathWatchSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/ClusterDeathWatchSpec.scala index 3546ce2d9b..8ae7ceda05 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/ClusterDeathWatchSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/ClusterDeathWatchSpec.scala @@ -18,6 +18,7 @@ import akka.remote.testkit.MultiNodeConfig import akka.remote.testkit.MultiNodeSpec import akka.testkit.TestEvent._ import akka.testkit._ +import com.typesafe.config.ConfigFactory import org.scalatest.concurrent.ScalaFutures object ClusterDeathWatchMultiJvmSpec extends MultiNodeConfig { @@ -27,7 +28,14 @@ object ClusterDeathWatchMultiJvmSpec extends MultiNodeConfig { val fourth = role("fourth") val fifth = role("fifth") - commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfigWithFailureDetectorPuppet)) + commonConfig( + debugConfig(on = false) + .withFallback(ConfigFactory.parseString(""" + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """)) + .withFallback(MultiNodeClusterSpec.clusterConfigWithFailureDetectorPuppet)) deployOn(fourth, """/hello.remote = "@first@" """) diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/MultiNodeClusterSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/MultiNodeClusterSpec.scala index ce38a0bf71..a93c2b2af9 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/MultiNodeClusterSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/MultiNodeClusterSpec.scala @@ -7,6 +7,7 @@ package akka.cluster import java.util.UUID import language.implicitConversions + import org.scalatest.{ Canceled, Outcome, Suite } import org.scalatest.exceptions.TestCanceledException import com.typesafe.config.Config @@ -18,7 +19,6 @@ import akka.testkit.TestEvent._ import akka.actor.{ Actor, ActorRef, ActorSystem, Address, Deploy, PoisonPill, Props, RootActorPath } import akka.event.Logging.ErrorLevel import akka.util.ccompat._ - import scala.concurrent.duration._ import scala.collection.immutable import java.util.concurrent.ConcurrentHashMap @@ -26,9 +26,10 @@ import java.util.concurrent.ConcurrentHashMap import akka.remote.DefaultFailureDetectorRegistry import akka.cluster.ClusterEvent.{ MemberEvent, MemberRemoved } import akka.util.ccompat._ - import scala.concurrent.Await +import akka.serialization.jackson.CborSerializable + @ccompatUsedUntil213 object MultiNodeClusterSpec { @@ -77,9 +78,9 @@ object MultiNodeClusterSpec { // sometimes we need to coordinate test shutdown with messages instead of barriers object EndActor { - case object SendEnd - case object End - case object EndAck + case object SendEnd extends CborSerializable + case object End extends CborSerializable + case object EndAck extends CborSerializable } class EndActor(testActor: ActorRef, target: Option[Address]) extends Actor { diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNode2Spec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNode2Spec.scala index a63dba624c..c56b926660 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNode2Spec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNode2Spec.scala @@ -26,13 +26,18 @@ object RestartNode2SpecMultiJvmSpec extends MultiNodeConfig { val seed2 = role("seed2") commonConfig( - debugConfig(on = false).withFallback(ConfigFactory.parseString(""" + debugConfig(on = false) + .withFallback(ConfigFactory.parseString(""" akka.cluster.auto-down-unreachable-after = 2s akka.cluster.retry-unsuccessful-join-after = 3s akka.cluster.allow-weakly-up-members = off akka.remote.retry-gate-closed-for = 45s akka.remote.log-remote-lifecycle-events = INFO - """)).withFallback(MultiNodeClusterSpec.clusterConfig)) + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """)) + .withFallback(MultiNodeClusterSpec.clusterConfig)) } diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNode3Spec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNode3Spec.scala index 45ff1bcf5e..f0ba61733a 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNode3Spec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNode3Spec.scala @@ -27,10 +27,15 @@ object RestartNode3MultiJvmSpec extends MultiNodeConfig { val third = role("third") commonConfig( - debugConfig(on = false).withFallback(ConfigFactory.parseString(""" + debugConfig(on = false) + .withFallback(ConfigFactory.parseString(""" akka.cluster.auto-down-unreachable-after = off akka.cluster.allow-weakly-up-members = off - """)).withFallback(MultiNodeClusterSpec.clusterConfig)) + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """)) + .withFallback(MultiNodeClusterSpec.clusterConfig)) testTransport(on = true) } diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNodeSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNodeSpec.scala index 432ab9b095..fbd236e66d 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNodeSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/RestartNodeSpec.scala @@ -32,11 +32,16 @@ object RestartNodeMultiJvmSpec extends MultiNodeConfig { val third = role("third") commonConfig( - debugConfig(on = false).withFallback(ConfigFactory.parseString(""" + debugConfig(on = false) + .withFallback(ConfigFactory.parseString(""" akka.cluster.auto-down-unreachable-after = 5s akka.cluster.allow-weakly-up-members = off #akka.remote.use-passive-connections = off - """)).withFallback(MultiNodeClusterSpec.clusterConfig)) + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """)) + .withFallback(MultiNodeClusterSpec.clusterConfig)) /** * This was used together with sleep in EndpointReader before deliverAndAck diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/StreamRefSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/StreamRefSpec.scala index 7adfaeb297..7e6c3e1958 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/StreamRefSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/StreamRefSpec.scala @@ -18,6 +18,7 @@ import akka.actor.Props import akka.remote.testkit.MultiNodeConfig import akka.remote.testkit.MultiNodeSpec import akka.remote.transport.ThrottlerTransportAdapter.Direction +import akka.serialization.jackson.CborSerializable import akka.stream.ActorMaterializer import akka.stream.RemoteStreamRefActorTerminatedException import akka.stream.SinkRef @@ -43,8 +44,9 @@ object StreamRefSpec extends MultiNodeConfig { testTransport(on = true) - case class RequestLogs(streamId: Int) - case class LogsOffer(streamId: Int, sourceRef: SourceRef[String]) + case class RequestLogs(streamId: Int) extends CborSerializable + // Using Java serialization until issue #27304 is fixed + case class LogsOffer(streamId: Int, sourceRef: SourceRef[String]) extends JavaSerializable object DataSource { def props(streamLifecycleProbe: ActorRef): Props = @@ -84,8 +86,9 @@ object StreamRefSpec extends MultiNodeConfig { } - case class PrepareUpload(id: String) - case class MeasurementsSinkReady(id: String, sinkRef: SinkRef[String]) + case class PrepareUpload(id: String) extends CborSerializable + // Using Java serialization until issue #27304 is fixed + case class MeasurementsSinkReady(id: String, sinkRef: SinkRef[String]) extends JavaSerializable object DataReceiver { def props(streamLifecycleProbe: ActorRef): Props = diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/StressSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/StressSpec.scala index 2bf7699ab3..5930ad0cb7 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/StressSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/StressSpec.scala @@ -165,6 +165,9 @@ private[cluster] object StressMultiJvmSpec extends MultiNodeConfig { } } } + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """)) class Settings(conf: Config) { diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/SurviveNetworkInstabilitySpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/SurviveNetworkInstabilitySpec.scala index c6ef1c5e1f..07b3c73d04 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/SurviveNetworkInstabilitySpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/SurviveNetworkInstabilitySpec.scala @@ -13,12 +13,13 @@ import akka.actor.Address import akka.actor.PoisonPill import akka.actor.Props import akka.actor.Terminated -import akka.remote.artery.QuarantinedEvent import akka.remote.RARP +import akka.remote.artery.QuarantinedEvent import akka.remote.testconductor.RoleName import akka.remote.testkit.MultiNodeConfig import akka.remote.testkit.MultiNodeSpec import akka.remote.transport.ThrottlerTransportAdapter.Direction +import akka.serialization.jackson.CborSerializable import akka.testkit._ import com.github.ghik.silencer.silent import com.typesafe.config.ConfigFactory @@ -50,8 +51,8 @@ object SurviveNetworkInstabilityMultiJvmSpec extends MultiNodeConfig { } } - case class Targets(refs: Set[ActorRef]) - case object TargetsRegistered + case class Targets(refs: Set[ActorRef]) extends CborSerializable + case object TargetsRegistered extends CborSerializable class Watcher extends Actor { var targets = Set.empty[ActorRef] diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/ClusterConsistentHashingGroupSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/ClusterConsistentHashingGroupSpec.scala index dc416ed0ef..9bb5562410 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/ClusterConsistentHashingGroupSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/ClusterConsistentHashingGroupSpec.scala @@ -16,8 +16,9 @@ import scala.concurrent.Await object ClusterConsistentHashingGroupMultiJvmSpec extends MultiNodeConfig { - case object Get - final case class Collected(messages: Set[Any]) + // using Java serialization because of `Any` in `Collected` (don't want to spend time on rewriting test) + case object Get extends JavaSerializable + final case class Collected(messages: Set[Any]) extends JavaSerializable class Destination extends Actor { var receivedMessages = Set.empty[Any] diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/ClusterRoundRobinSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/ClusterRoundRobinSpec.scala index ebfab91299..a23a87eb1f 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/ClusterRoundRobinSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/ClusterRoundRobinSpec.scala @@ -50,11 +50,10 @@ object ClusterRoundRobinMultiJvmSpec extends MultiNodeConfig { commonConfig(debugConfig(on = false).withFallback(ConfigFactory.parseString(s""" akka.actor { - allow-java-serialization = off serialize-creators = off serialize-messages = off serialization-bindings { - "akka.cluster.routing.ClusterRoundRobinMultiJvmSpec$$Reply" = test-message-serializer + "akka.cluster.routing.ClusterRoundRobinMultiJvmSpec$$Reply" = java-test } deployment { diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/UseRoleIgnoredSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/UseRoleIgnoredSpec.scala index 06a6eadb3c..050617d293 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/UseRoleIgnoredSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/UseRoleIgnoredSpec.scala @@ -36,7 +36,7 @@ object UseRoleIgnoredMultiJvmSpec extends MultiNodeConfig { } } - final case class Reply(routeeType: RouteeType, ref: ActorRef) + final case class Reply(routeeType: RouteeType, ref: ActorRef) extends JavaSerializable sealed trait RouteeType extends Serializable object PoolRoutee extends RouteeType diff --git a/akka-cluster/src/test/resources/reference.conf b/akka-cluster/src/test/resources/reference.conf index b7b9343137..c4862737dc 100644 --- a/akka-cluster/src/test/resources/reference.conf +++ b/akka-cluster/src/test/resources/reference.conf @@ -1,7 +1,6 @@ akka { actor { serialize-messages = off - warn-about-java-serializer-usage = off } } diff --git a/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorDeltaSpec.scala b/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorDeltaSpec.scala index 28fab6eb32..d2063c184f 100644 --- a/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorDeltaSpec.scala +++ b/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorDeltaSpec.scala @@ -13,6 +13,7 @@ import akka.cluster.ddata.Replicator._ import akka.remote.testconductor.RoleName import akka.remote.testkit.MultiNodeConfig import akka.remote.testkit.MultiNodeSpec +import akka.serialization.jackson.CborSerializable import akka.testkit._ import com.typesafe.config.ConfigFactory @@ -33,7 +34,8 @@ object ReplicatorDeltaSpec extends MultiNodeConfig { case class Highest(n: Int, delta: Option[Highest] = None) extends DeltaReplicatedData with RequiresCausalDeliveryOfDeltas - with ReplicatedDelta { + with ReplicatedDelta + with CborSerializable { type T = Highest type D = Highest diff --git a/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorMapDeltaSpec.scala b/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorMapDeltaSpec.scala index 09c956e377..9720e4a53b 100644 --- a/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorMapDeltaSpec.scala +++ b/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorMapDeltaSpec.scala @@ -28,9 +28,7 @@ object ReplicatorMapDeltaSpec extends MultiNodeConfig { akka.log-dead-letters-during-shutdown = off akka.actor { serialize-messages = off - allow-java-serialization = off } - #akka.remote.artery.enabled = on """)) testTransport(on = true) diff --git a/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorORSetDeltaSpec.scala b/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorORSetDeltaSpec.scala index fd2bae18c2..5ecb56867d 100644 --- a/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorORSetDeltaSpec.scala +++ b/akka-distributed-data/src/multi-jvm/scala/akka/cluster/ddata/ReplicatorORSetDeltaSpec.scala @@ -25,7 +25,6 @@ object ReplicatorORSetDeltaSpec extends MultiNodeConfig { akka.log-dead-letters-during-shutdown = off akka.actor { serialize-messages = off - allow-java-serialization = off } """)) diff --git a/akka-distributed-data/src/test/resources/reference.conf b/akka-distributed-data/src/test/resources/reference.conf index cd91912673..34b65628db 100644 --- a/akka-distributed-data/src/test/resources/reference.conf +++ b/akka-distributed-data/src/test/resources/reference.conf @@ -1,5 +1,4 @@ akka.actor { - serialize-messages = on - warn-about-java-serializer-usage = off + serialize-messages = off } diff --git a/akka-distributed-data/src/test/scala/akka/cluster/ddata/protobuf/ReplicatedDataSerializerSpec.scala b/akka-distributed-data/src/test/scala/akka/cluster/ddata/protobuf/ReplicatedDataSerializerSpec.scala index 2562e8245d..20934ed258 100644 --- a/akka-distributed-data/src/test/scala/akka/cluster/ddata/protobuf/ReplicatedDataSerializerSpec.scala +++ b/akka-distributed-data/src/test/scala/akka/cluster/ddata/protobuf/ReplicatedDataSerializerSpec.scala @@ -37,7 +37,6 @@ class ReplicatedDataSerializerSpec akka.remote.artery.canonical.port = 0 akka.actor { serialize-messages = off - allow-java-serialization = off } """))) with WordSpecLike diff --git a/akka-distributed-data/src/test/scala/akka/cluster/ddata/protobuf/ReplicatorMessageSerializerSpec.scala b/akka-distributed-data/src/test/scala/akka/cluster/ddata/protobuf/ReplicatorMessageSerializerSpec.scala index 5af818e622..d5cbe2667b 100644 --- a/akka-distributed-data/src/test/scala/akka/cluster/ddata/protobuf/ReplicatorMessageSerializerSpec.scala +++ b/akka-distributed-data/src/test/scala/akka/cluster/ddata/protobuf/ReplicatorMessageSerializerSpec.scala @@ -41,7 +41,6 @@ class ReplicatorMessageSerializerSpec akka.remote.artery.canonical.port = 0 akka.actor { serialize-messages = off - allow-java-serialization = off } """))) with WordSpecLike diff --git a/akka-docs/src/main/paradox/cluster-routing.md b/akka-docs/src/main/paradox/cluster-routing.md index 86a0911c26..2c294cdac1 100644 --- a/akka-docs/src/main/paradox/cluster-routing.md +++ b/akka-docs/src/main/paradox/cluster-routing.md @@ -195,6 +195,9 @@ Java See @ref:[reference configuration](general/configuration.md#config-akka-cluster) for further descriptions of the settings. +When using a pool of remote deployed routees you must ensure that all parameters of the `Props` can +be @ref:[serialized](serialization.md). + ### Router Example with Pool of Remote Deployed Routees Let's take a look at how to use a cluster aware router on single master node that creates @@ -253,4 +256,4 @@ akka.actor.deployment { ``` The easiest way to run **Router Example with Pool of Routees** example yourself is to try the @scala[@extref[Akka Cluster Sample with Scala](samples:akka-samples-cluster-scala)]@java[@extref[Akka Cluster Sample with Java](samples:akka-samples-cluster-java)]. -It contains instructions on how to run the **Router Example with Pool of Routees** sample. \ No newline at end of file +It contains instructions on how to run the **Router Example with Pool of Routees** sample. diff --git a/akka-docs/src/main/paradox/cluster-usage.md b/akka-docs/src/main/paradox/cluster-usage.md index f7e01bb4fb..c4ef730ddd 100644 --- a/akka-docs/src/main/paradox/cluster-usage.md +++ b/akka-docs/src/main/paradox/cluster-usage.md @@ -6,6 +6,10 @@ The core of Akka Cluster is the cluster membership, to keep track of what nodes their health. There are several @ref:[Higher level Cluster tools](cluster-usage.md#higher-level-cluster-tools) that are built on top of the cluster membership. +You need to enable @ref:[serialization](serialization.md) for your actor messages. +@ref:[Serialization with Jackson](serialization-jackson.md) is a good choice in many cases and our +recommendation if you don't have other preference. + ## Dependency To use Akka Cluster, you must add the following dependency in your project: diff --git a/akka-docs/src/main/paradox/persistence.md b/akka-docs/src/main/paradox/persistence.md index 16bb062cc8..34ab18e792 100644 --- a/akka-docs/src/main/paradox/persistence.md +++ b/akka-docs/src/main/paradox/persistence.md @@ -1091,7 +1091,7 @@ it must add @@snip [PersistenceSerializerDocSpec.scala](/akka-docs/src/test/scala/docs/persistence/PersistenceSerializerDocSpec.scala) { #custom-serializer-config } -to the application configuration. If not specified, a default serializer is used. +to the application configuration. If not specified, an exception will be throw when trying to persist events or snapshots. For more advanced schema evolution techniques refer to the @ref:[Persistence - Schema Evolution](persistence-schema-evolution.md) documentation. diff --git a/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md b/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md index 2896d6e105..e50304ff4d 100644 --- a/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md +++ b/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md @@ -193,6 +193,64 @@ Classic remoting is deprecated but can be used in `2.6.` Explicitly disable Arte specific to classic remoting needs to be moved to `akka.remote.classic`. To see which configuration options are specific to classic search for them in: [`akka-remote/reference.conf`](/akka-remote/src/main/resources/reference.conf) +## Java Serialization + +Java serialization is known to be slow and [prone to attacks](https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995) +of various kinds - it never was designed for high throughput messaging after all. +One may think that network bandwidth and latency limit the performance of remote messaging, but serialization is a more typical bottleneck. + +From Akka 2.6.0 the Akka serialization with Java serialization is disabled by default and Akka +itself doesn't use Java serialization for any of its internal messages. + +For compatibility with older systems that rely on Java serialization it can be enabled with the following configuration: + +```ruby +akka.actor.allow-java-serialization = on +``` + +Akka will still log warning when Java serialization is used and to silent that you may add: + +```ruby +akka.actor.warn-about-java-serializer-usage = off +``` + +### Rolling update + +You can replace Java serialization, if you use that, with for example the new +@ref:[Serialization with Jackson](../serialization-jackson.md) and still be able to perform a rolling updates +without bringing down the entire cluster. + +The procedure for changing from Java serialization to Jackson would look like: + +1. Rolling update from 2.5.24 (or later) to 2.6.0 + * Use config `allow-java-serialization=on`. + * Roll out the change. + * Java serialization will be used as before. + * This step is optional and you could combine it with next step if you like, but could be good to + make one change at a time. +1. Rolling update to support deserialization but not enable serialization + * Change message classes by adding the marker interface and possibly needed annotations as + described in @ref:[Serialization with Jackson](../serialization-jackson.md). + * Test the system with the new serialization in a new test cluster (no rolling update). + * Remove the binding for the marker interface, so that Jackson is not used for serialization yet. + * Roll out the change. + * Java serialization is still used, but this version is prepared for next roll out. +1. Rolling update to enable serialization with Jackson. + * Add the binding to the marker interface to the Jackson serializer. + * Roll out the change. + * Old nodes will still send messages with Java serialization, and that can still be deserialized by new nodes. + * New nodes will send messages with Jackson serialization, and old node can deserialize those because they were + prepared in previous roll out. +1. Rolling update to disable Java serialization + * Remove `allow-java-serialization` config, to use the default `allow-java-serialization=off`. + * Remove `.warn-about-java-serializer-usage` config if you had changed that, to use the default `.warn-about-java-serializer-usage=on`. + * Roll out the change. + +### Java serialization in consistent hashing + +When using a consistent hashing router keys that were not bytes or a String are serialized. +You might have to add a serializer for you hash keys, unless one of the default serializer are not +handling that type and it was previously "accidentally" serialized with Java serialization. ## Configuration and behavior changes diff --git a/akka-docs/src/main/paradox/remoting-artery.md b/akka-docs/src/main/paradox/remoting-artery.md index 588e498a7d..fed9e88778 100644 --- a/akka-docs/src/main/paradox/remoting-artery.md +++ b/akka-docs/src/main/paradox/remoting-artery.md @@ -86,10 +86,8 @@ underlying module that allows for Cluster, it is still useful to understand deta @@@ note -This page describes the remoting subsystem, codenamed *Artery* that will eventually replace the -@ref:[classic remoting implementation](remoting.md). Artery is ready to use in production, but the -module is still marked @ref:[may change](common/may-change.md) because some configuration will be -changed when the API becomes stable in Akka 2.6.0. +This page describes the remoting subsystem, codenamed *Artery* that has replaced the +@ref:[classic remoting implementation](remoting.md). @@@ @@ -101,6 +99,10 @@ sent messages to, watched, etc. Every `ActorRef` contains hostname and port information and can be passed around even on the network. This means that on a network every `ActorRef` is a unique identifier of an actor on that network. +You need to enable @ref:[serialization](serialization.md) for your actor messages. +@ref:[Serialization with Jackson](serialization-jackson.md) is a good choice in many cases and our +recommendation if you don't have other preference. + Remoting is not a server-client technology. All systems using remoting can contact any other system on the network if they possess an `ActorRef` pointing to those system. This means that every system that is remoting enabled acts as a "server" to which arbitrary systems on the same network can connect to. @@ -254,8 +256,9 @@ Best practice is that Akka remoting nodes should only be accessible from the adj enabled with mutual authentication there is still a risk that an attacker can gain access to a valid certificate by compromising any node with certificates issued by the same internal PKI tree. -It is also security best-practice to @ref[disable the Java serializer](serialization.md#disable-java-serializer) because of -its multiple [known attack surfaces](https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995). +By default, @ref[Java serialization](serialization.md#java-serialization) is disabled in Akka. +That is also security best-practice because of its multiple +[known attack surfaces](https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995). ### Configuring SSL/TLS for Akka Remoting @@ -388,9 +391,10 @@ as a marker trait to user-defined messages. Untrusted mode does not give full protection against attacks by itself. It makes it slightly harder to perform malicious or unintended actions but -it should be complemented with @ref:[disabled Java serializer](#disabling-the-java-serializer) +it should be noted that @ref:[Java serialization](serialization.md#java-serialization) +should still not be enabled. Additional protection can be achieved when running in an untrusted network by -network security (e.g. firewalls). +network security (e.g. firewalls) and/or enabling @ref:[TLS with mutual authentication](#remote-tls). @@@ @@ -546,10 +550,9 @@ This is how the curve looks like for `acceptable-heartbeat-pause` configured to ## Serialization -When using remoting for actors you must ensure that the `props` and `messages` used for -those actors are serializable. Failing to do so will cause the system to behave in an unintended way. - -For more information please see @ref:[Serialization](serialization.md). +You need to enable @ref:[serialization](serialization.md) for your actor messages. +@ref:[Serialization with Jackson](serialization-jackson.md) is a good choice in many cases and our +recommendation if you don't have other preference. ### ByteBuffer based serialization @@ -588,11 +591,6 @@ Scala Java : @@snip [ByteBufferSerializerDocTest.java](/akka-docs/src/test/java/jdocs/actor/ByteBufferSerializerDocTest.java) { #bytebufserializer-with-manifest } - -### Disabling the Java Serializer - -It is highly recommended that you @ref[disable Java serialization](serialization.md#disable-java-serializer). - ## Routers with Remote Destinations It is absolutely feasible to combine remoting with @ref:[Routing](routing.md). @@ -604,6 +602,9 @@ A pool of remote deployed routees can be configured as: This configuration setting will clone the actor defined in the `Props` of the `remotePool` 10 times and deploy it evenly distributed across the two given target nodes. +When using a pool of remote deployed routees you must ensure that all parameters of the `Props` can +be @ref:[serialized](serialization.md). + A group of remote actors can be configured as: @@snip [RouterDocSpec.scala](/akka-docs/src/test/scala/docs/routing/RouterDocSpec.scala) { #config-remote-round-robin-group-artery } diff --git a/akka-docs/src/main/paradox/remoting.md b/akka-docs/src/main/paradox/remoting.md index 63db432d01..5a39119bbf 100644 --- a/akka-docs/src/main/paradox/remoting.md +++ b/akka-docs/src/main/paradox/remoting.md @@ -100,6 +100,10 @@ network and/or Akka configuration will have to be changed as described in @@@ +You need to enable @ref:[serialization](serialization.md) for your actor messages. +@ref:[Serialization with Jackson](serialization-jackson.md) is a good choice in many cases and our +recommendation if you don't have other preference. + ## Types of Remote Interaction Akka has two ways of using remoting: @@ -203,6 +207,9 @@ Java The actor class `SampleActor` has to be available to the runtimes using it, i.e. the classloader of the actor systems has to have a JAR containing the class. +When using remote deployment of actors you must ensure that all parameters of the `Props` can +be @ref:[serialized](serialization.md). + @@@ note In order to ensure serializability of `Props` when passing constructor @@ -359,15 +366,9 @@ This is how the curve looks like for `acceptable-heartbeat-pause` configured to ## Serialization -When using remoting for actors you must ensure that the `props` and `messages` used for -those actors are serializable. Failing to do so will cause the system to behave in an unintended way. - -For more information please see @ref:[Serialization](serialization.md). - - -### Disabling the Java Serializer - -It is highly recommended that you @ref[disable Java serialization](serialization.md#disable-java-serializer). +You need to enable @ref:[serialization](serialization.md) for your actor messages. +@ref:[Serialization with Jackson](serialization-jackson.md) is a good choice in many cases and our +recommendation if you don't have other preference. ## Routers with Remote Destinations @@ -380,6 +381,9 @@ A pool of remote deployed routees can be configured as: This configuration setting will clone the actor defined in the `Props` of the `remotePool` 10 times and deploy it evenly distributed across the two given target nodes. +When using a pool of remote deployed routees you must ensure that all parameters of the `Props` can +be @ref:[serialized](serialization.md). + A group of remote actors can be configured as: @@snip [RouterDocSpec.scala](/akka-docs/src/test/scala/docs/routing/RouterDocSpec.scala) { #config-remote-round-robin-group } @@ -454,8 +458,9 @@ Best practice is that Akka remoting nodes should only be accessible from the adj enabled with mutual authentication there is still a risk that an attacker can gain access to a valid certificate by compromising any node with certificates issued by the same internal PKI tree. -It is also security best-practice to [disable the Java serializer](#disable-java-serializer) because of -its multiple [known attack surfaces](https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995). +By default, @ref[Java serialization](serialization.md#java-serialization) is disabled in Akka. +That is also security best-practice because of its multiple +[known attack surfaces](https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995). ### Configuring SSL/TLS for Akka Remoting @@ -564,9 +569,10 @@ as a marker trait to user-defined messages. Untrusted mode does not give full protection against attacks by itself. It makes it slightly harder to perform malicious or unintended actions but -it should be complemented with [disabled Java serializer](#disable-java-serializer). +it should be noted that @ref:[Java serialization](serialization.md#java-serialization) +should still not be enabled. Additional protection can be achieved when running in an untrusted network by -network security (e.g. firewalls) and/or enabling [TLS with mutual authentication](#remote-tls). +network security (e.g. firewalls) and/or enabling @ref:[TLS with mutual authentication](#remote-tls). @@@ diff --git a/akka-docs/src/main/paradox/security/2017-02-10-java-serialization.md b/akka-docs/src/main/paradox/security/2017-02-10-java-serialization.md index 3e75090627..4fa590288f 100644 --- a/akka-docs/src/main/paradox/security/2017-02-10-java-serialization.md +++ b/akka-docs/src/main/paradox/security/2017-02-10-java-serialization.md @@ -20,7 +20,7 @@ Java deserialization is [known to be vulnerable](https://community.hpe.com/t5/Se Akka Remoting uses Java serialiser as default configuration which makes it vulnerable in its default form. The documentation of how to disable Java serializer was not complete. The documentation of how to enable mutual authentication was missing (only described in reference.conf). To protect against such attacks the system should be updated to Akka *2.4.17* or later and be configured with -@ref:[disabled Java serializer](../remoting.md#disable-java-serializer). Additional protection can be achieved when running in an +[disabled Java serializer](https://doc.akka.io/docs/akka/2.5/remoting.html#disable-java-serializer). Additional protection can be achieved when running in an untrusted network by enabling @ref:[TLS with mutual authentication](../remoting.md#remote-tls). Please subscribe to the [akka-security](https://groups.google.com/forum/#!forum/akka-security) mailing list to be notified promptly about future security issues. diff --git a/akka-docs/src/main/paradox/security/index.md b/akka-docs/src/main/paradox/security/index.md index ba7e8dcd14..2ab53762ae 100644 --- a/akka-docs/src/main/paradox/security/index.md +++ b/akka-docs/src/main/paradox/security/index.md @@ -18,7 +18,7 @@ to ensure that a fix can be provided without delay. ## Security Related Documentation - * @ref:[Disabling the Java Serializer](../remoting-artery.md#disable-java-serializer) + * @ref:[Java Serialization](../serialization.md#java-serialization) * @ref:[Remote deployment whitelist](../remoting.md#remote-deployment-whitelist) * @ref:[Remote Security](../remoting-artery.md#remote-security) diff --git a/akka-docs/src/main/paradox/serialization.md b/akka-docs/src/main/paradox/serialization.md index ec91fe2c12..c36be39256 100644 --- a/akka-docs/src/main/paradox/serialization.md +++ b/akka-docs/src/main/paradox/serialization.md @@ -12,15 +12,24 @@ To use Serialization, you must add the following dependency in your project: ## Introduction -The messages that Akka actors send to each other are JVM objects (e.g. instances of Scala case classes). Message passing between actors that live on the same JVM is straightforward. It is done via reference passing. However, messages that have to escape the JVM to reach an actor running on a different host have to undergo some form of serialization (i.e. the objects have to be converted to and from byte arrays). +The messages that Akka actors send to each other are JVM objects @scala[(e.g. instances of Scala case classes)]. Message passing between actors that live on the same JVM is straightforward. It is done via reference passing. However, messages that have to escape the JVM to reach an actor running on a different host have to undergo some form of serialization (i.e. the objects have to be converted to and from byte arrays). -Akka itself uses Protocol Buffers to serialize internal messages (i.e. cluster gossip messages). However, the serialization mechanism in Akka allows you to write custom serializers and to define which serializer to use for what. +The serialization mechanism in Akka allows you to write custom serializers and to define which serializer to use for what. + +@ref:[Serialization with Jackson](serialization-jackson.md) is a good choice in many cases and our +recommendation if you don't have other preference. + +[Google Protocol Buffers](https://developers.google.com/protocol-buffers/) is good if you want +more control over the schema evolution of your messages, but it requires more work to develop and +maintain the mapping between serialized representation and domain representation. + +Akka itself uses Protocol Buffers to serialize internal messages (for example cluster gossip messages). ## Usage ### Configuration -For Akka to know which `Serializer` to use for what, you need edit your [Configuration](), +For Akka to know which `Serializer` to use for what, you need edit your configuration, in the "akka.actor.serializers"-section you bind names to implementations of the `akka.serialization.Serializer` you wish to use, like this: @@ -35,8 +44,8 @@ You only need to specify the name of an interface or abstract base class of the messages. In case of ambiguity, i.e. the message implements several of the configured classes, the most specific configured class will be used, i.e. the one of which all other candidates are superclasses. If this condition cannot be -met, because e.g. `java.io.Serializable` and `MyOwnSerializable` both apply -and neither is a subtype of the other, a warning will be issued. +met, because e.g. two marker interfaces that have been configured for serialization +both apply and neither is a subtype of the other, a warning will be issued. @@@ note @@ -47,13 +56,10 @@ you would need to reference it as `Wrapper$Message` instead of `Wrapper.Message` @@@ -Akka provides serializers for `java.io.Serializable` and [protobuf](http://code.google.com/p/protobuf/) +Akka provides serializers for several primitive types and [protobuf](http://code.google.com/p/protobuf/) `com.google.protobuf.GeneratedMessage` by default (the latter only if depending on the akka-remote module), so normally you don't need to add -configuration for that; since `com.google.protobuf.GeneratedMessage` -implements `java.io.Serializable`, protobuf messages will always be -serialized using the protobuf protocol unless specifically overridden. In order -to disable a default serializer, see @ref:[Disabling the Java Serializer](remoting-artery.md#disable-java-serializer) +configuration for that if you send raw protobuf messages as actor messages. ### Verification @@ -89,7 +95,13 @@ Scala Java : @@snip [SerializationDocTest.java](/akka-docs/src/test/java/jdocs/serialization/SerializationDocTest.java) { #programmatic } -For more information, have a look at the `ScalaDoc` for `akka.serialization._` +The manifest is a type hint so that the same serializer can be used for different classes. + +Note that when deserializing from bytes the manifest and the identifier of the serializer are needed. +It is important to use the serializer identifier in this way to support rolling updates, where the +`serialization-bindings` for a class may have changed from one serializer to another. Therefore the three parts +consisting of the bytes, the serializer id, and the manifest should always be transferred or stored together so that +they can be deserialized with different `serialization-bindings` configuration. ## Customization @@ -117,7 +129,7 @@ classes. The manifest parameter in @scala[`fromBinary`]@java[`fromBinaryJava`] i was serialized. In `fromBinary` you can match on the class and deserialize the bytes to different objects. -Then you only need to fill in the blanks, bind it to a name in your [Configuration]() and then +Then you only need to fill in the blanks, bind it to a name in your configuration and then list which classes that should be serialized using it. @@ -145,17 +157,17 @@ Scala Java : @@snip [SerializationDocTest.java](/akka-docs/src/test/java/jdocs/serialization/SerializationDocTest.java) { #my-own-serializer2 } -You must also bind it to a name in your [Configuration]() and then list which classes +You must also bind it to a name in your configuration and then list which classes that should be serialized using it. -It's recommended to throw `java.io.NotSerializableException` in `fromBinary` -if the manifest is unknown. This makes it possible to introduce new message types and +It's recommended to throw `IllegalArgumentException` or ``java.io.NotSerializableException` in +`fromBinary` if the manifest is unknown. This makes it possible to introduce new message types and send them to nodes that don't know about them. This is typically needed when performing rolling upgrades, i.e. running a cluster with mixed versions for while. -`NotSerializableException` is treated as a transient problem in the TCP based remoting +Those exceptions are treated as a transient problem in the classic remoting layer. The problem will be logged and message is dropped. Other exceptions will tear down the TCP connection because it can be an indication of corrupt bytes from the underlying -transport. +transport. Artery TCP handles all deserialization exceptions as transient problems. ### Serializing ActorRefs @@ -186,16 +198,13 @@ address part of an actor’s path determines how that actor is communicated with Storing a local actor path might be the right choice if the retrieval happens in the same logical context, but it is not enough when deserializing it on a different network host: for that it would need to include the system’s remote -transport address. An actor system is not limited to having just one remote -transport per se, which makes this question a bit more interesting. To find out -the appropriate address to use when sending to `remoteAddr` you can use -`ActorRefProvider.getExternalAddressFor(remoteAddr)` like this: +transport address. Scala -: @@snip [SerializationDocSpec.scala](/akka-docs/src/test/scala/docs/serialization/SerializationDocSpec.scala) { #external-address } +: @@snip [SerializationDocSpec.scala](/akka-docs/src/test/scala/docs/serialization/SerializationDocSpec.scala) { #external-address-default } Java -: @@snip [SerializationDocTest.java](/akka-docs/src/test/java/jdocs/serialization/SerializationDocTest.java) { #external-address } +: @@snip [SerializationDocTest.java](/akka-docs/src/test/java/jdocs/serialization/SerializationDocTest.java) { #external-address-default } @@@ note @@ -212,12 +221,6 @@ include the unique id. @@@ -This requires that you know at least which type of address will be supported by -the system which will deserialize the resulting actor reference; if you have no -concrete address handy you can create a dummy one for the right protocol using -@scala[`Address(protocol, "", "", 0)`]@java[`new Address(protocol, "", "", 0)`] (assuming that the actual transport used is as -lenient as Akka’s RemoteActorRefProvider). - There is also a default remote address which is the one used by cluster support (and typical systems have just this one); you can get it like this: @@ -227,56 +230,42 @@ Scala Java : @@snip [SerializationDocTest.java](/akka-docs/src/test/java/jdocs/serialization/SerializationDocTest.java) { #external-address-default } -Another solution is to encapsulate your serialization code in `Serialization.withTransportInformation`. -It ensures the actorRefs are serialized using systems default address when -no other address is available. - ### Deep serialization of Actors The recommended approach to do deep serialization of internal actor state is to use Akka @ref:[Persistence](persistence.md). - -## Disabling the Java Serializer +## Java serialization Java serialization is known to be slow and [prone to attacks](https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995) -of various kinds - it never was designed for high throughput messaging after all. However, it is very -convenient to use, thus it remained the default serialization mechanism that Akka used to -serialize user messages as well as some of its internal messages in previous versions. +of various kinds - it never was designed for high throughput messaging after all. +One may think that network bandwidth and latency limit the performance of remote messaging, but serialization is a more typical bottleneck. @@@ note -Akka does not use Java Serialization for any of its internal messages. -It is highly encouraged to disable java serialization, so please plan to do so at the earliest possibility you have in your project. +Akka serialization with Java serialization is disabled by default and Akka itself doesn't use Java serialization +for any of its internal messages. It is highly discouraged to enable Java serialization in production. -One may think that network bandwidth and latency limit the performance of remote messaging, but serialization is a more typical bottleneck. - -@@@ - -For user messages, the default serializer, implemented using Java serialization, remains available and enabled. -We do however recommend to disable it entirely and utilise a proper serialization library instead in order effectively utilise -the improved performance and ability for rolling deployments using Artery. Libraries that we recommend to use include, -but are not limited to, [Kryo](https://github.com/EsotericSoftware/kryo) by using the [akka-kryo-serialization](https://github.com/romix/akka-kryo-serialization) library or [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) if you want -more control over the schema evolution of your messages. - -In order to completely disable Java Serialization in your Actor system you need to add the following configuration to -your `application.conf`: - -```ruby -akka.actor.allow-java-serialization = off -``` - -This will completely disable the use of `akka.serialization.JavaSerialization` by the -Akka Serialization extension, instead `DisabledJavaSerializer` will -be inserted which will fail explicitly if attempts to use java serialization are made. - -The log messages emitted by such serializer SHOULD be treated as potential +The log messages emitted by the disabled Java serializer in production SHOULD be treated as potential attacks which the serializer prevented, as they MAY indicate an external operator attempting to send malicious messages intending to use java serialization as attack vector. The attempts are logged with the SECURITY marker. -Please note that this option does not stop you from manually invoking java serialization. +@@@ -## Serialization compatibility +However, for early prototyping it is very convenient to use. For that reason and for compatibility with +older systems that rely on Java serialization it can be enabled with the following configuration: + +```ruby +akka.actor.allow-java-serialization = on +``` + +Akka will still log warning when Java serialization is used and to silent that you may add: + +```ruby +akka.actor.warn-about-java-serializer-usage = off +``` + +### Java serialization compatibility It is not safe to mix major Scala versions when using the Java serialization as Scala does not guarantee compatibility and this could lead to very surprising errors. @@ -308,8 +297,8 @@ It must still be possible to deserialize the events that were stored with the ol ## External Akka Serializers -[Akka-quickser by Roman Levenstein](https://github.com/romix/akka-quickser-serialization) +* [Akka-quickser by Roman Levenstein](https://github.com/romix/akka-quickser-serialization) -[Akka-kryo by Roman Levenstein](https://github.com/romix/akka-kryo-serialization) +* [Akka-kryo by Roman Levenstein](https://github.com/romix/akka-kryo-serialization) -[Twitter Chill Scala extensions for Kryo (based on Akka Version 2.3.x but due to backwards compatibility of the Serializer Interface this extension also works with 2.4.x)](https://github.com/twitter/chill) +* [Twitter Chill Scala extensions for Kryo (based on Akka Version 2.3.x but due to backwards compatibility of the Serializer Interface this extension also works with 2.4.x)](https://github.com/twitter/chill) diff --git a/akka-docs/src/main/paradox/typed/cluster.md b/akka-docs/src/main/paradox/typed/cluster.md index ab65946aa7..c9603ba464 100644 --- a/akka-docs/src/main/paradox/typed/cluster.md +++ b/akka-docs/src/main/paradox/typed/cluster.md @@ -15,6 +15,10 @@ To use Akka Cluster Typed, you must add the following dependency in your project For an introduction to Akka Cluster concepts see @ref:[Cluster Specification](../common/cluster.md). This documentation shows how to use the typed Cluster API. +You need to enable @ref:[serialization](../serialization.md) for your actor messages. +@ref:[Serialization with Jackson](../serialization-jackson.md) is a good choice in many cases and our +recommendation if you don't have other preference. + ## Examples All of the examples below assume the following imports: diff --git a/akka-docs/src/main/paradox/typed/persistence-style.md b/akka-docs/src/main/paradox/typed/persistence-style.md index 9440346a8b..c8a52c136a 100644 --- a/akka-docs/src/main/paradox/typed/persistence-style.md +++ b/akka-docs/src/main/paradox/typed/persistence-style.md @@ -4,8 +4,8 @@ The section about @ref:[Changing Behavior](persistence.md#changing-behavior) described how commands and events can be handled differently depending on the state. One can take that one step further and define the event -handler inside the state classes. In @ref:[next section the command handlers](#command-handlers-in-the-state) are -also defined in the state. +handler inside the state classes. @scala[In @ref:[next section the command handlers](#command-handlers-in-the-state) are +also defined in the state.] The state can be seen as your domain object and it should contain the core business logic. Then it's a matter of taste if event handlers and command handlers should be defined in the state or be kept outside it. @@ -24,6 +24,7 @@ in the concrete `EmptyAccount`, `OpenedAccount`, and `ClosedAccount`.] @java[Notice how the `eventHandler` delegates to methods in the concrete `Account` (state) classes; `EmptyAccount`, `OpenedAccount`, and `ClosedAccount`.] +@@@ div { .group-scala } ## Command handlers in the state We can take the previous bank account example one step further by handling the commands in the state too. @@ -31,13 +32,10 @@ We can take the previous bank account example one step further by handling the c Scala : @@snip [AccountExampleWithCommandHandlersInState.scala](/akka-cluster-sharding-typed/src/test/scala/docs/akka/cluster/sharding/typed/AccountExampleWithCommandHandlersInState.scala) { #account-entity } -Java -: @@snip [AccountExampleWithCommandHandlersInState.java](/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/AccountExampleWithCommandHandlersInState.java) { #account-entity } +Notice how the command handler is delegating to `applyCommand` in the `Account` (state), which is implemented +in the concrete `EmptyAccount`, `OpenedAccount`, and `ClosedAccount`. -@scala[Notice how the command handler is delegating to `applyCommand` in the `Account` (state), which is implemented -in the concrete `EmptyAccount`, `OpenedAccount`, and `ClosedAccount`.] -@java[Notice how the command handler delegates to methods in the concrete `Account` (state) classes; -`EmptyAccount`, `OpenedAccount`, and `ClosedAccount`.] +@@@ ## Optional initial state diff --git a/akka-docs/src/main/paradox/typed/persistence.md b/akka-docs/src/main/paradox/typed/persistence.md index eb0546be0f..2ae137e478 100644 --- a/akka-docs/src/main/paradox/typed/persistence.md +++ b/akka-docs/src/main/paradox/typed/persistence.md @@ -324,6 +324,10 @@ actors is also used in Akka Typed, also for persistent actors. When picking seri you should also consider that it must be possible read old events when the application has evolved. Strategies for that can be found in the @ref:[schema evolution](../persistence-schema-evolution.md). +You need to enable @ref:[serialization](../serialization.md) for your commands (messages), events, and state (snapshot). +@ref:[Serialization with Jackson](../serialization-jackson.md) is a good choice in many cases and our +recommendation if you don't have other preference. + ## Recovery It is strongly discouraged to perform side effects in `applyEvent`, diff --git a/akka-docs/src/test/java/jdocs/serialization/SerializationDocTest.java b/akka-docs/src/test/java/jdocs/serialization/SerializationDocTest.java index 633f8e89b1..638f8b10bf 100644 --- a/akka-docs/src/test/java/jdocs/serialization/SerializationDocTest.java +++ b/akka-docs/src/test/java/jdocs/serialization/SerializationDocTest.java @@ -6,6 +6,7 @@ package jdocs.serialization; import java.io.UnsupportedEncodingException; +import akka.cluster.Cluster; import akka.testkit.javadsl.TestKit; import org.junit.Test; import static org.junit.Assert.*; @@ -138,106 +139,26 @@ public class SerializationDocTest { // #actorref-serializer // Serialize // (beneath toBinary) - String identifier = Serialization.serializedActorPath(theActorRef); + String serializedRef = Serialization.serializedActorPath(theActorRef); // Then just serialize the identifier however you like // Deserialize // (beneath fromBinary) - final ActorRef deserializedActorRef = extendedSystem.provider().resolveActorRef(identifier); + final ActorRef deserializedRef = extendedSystem.provider().resolveActorRef(serializedRef); // Then just use the ActorRef // #actorref-serializer TestKit.shutdownActorSystem(extendedSystem); } - public - // #external-address - static class ExternalAddressExt implements Extension { - private final ExtendedActorSystem system; - - public ExternalAddressExt(ExtendedActorSystem system) { - this.system = system; - } - - public Address getAddressFor(Address remoteAddress) { - final scala.Option
optAddr = system.provider().getExternalAddressFor(remoteAddress); - if (optAddr.isDefined()) { - return optAddr.get(); - } else { - throw new UnsupportedOperationException("cannot send to remote address " + remoteAddress); - } - } - } - - // #external-address - public - // #external-address - static class ExternalAddress extends AbstractExtensionId - implements ExtensionIdProvider { - public static final ExternalAddress ID = new ExternalAddress(); - - public ExternalAddress lookup() { - return ID; - } - - public ExternalAddressExt createExtension(ExtendedActorSystem system) { - return new ExternalAddressExt(system); - } - } - - // #external-address - public - // #external-address - static class ExternalAddressExample { - // #external-address - final ActorSystem system = ActorSystem.create(); - // #external-address - public String serializeTo(ActorRef ref, Address remote) { - return ref.path() - .toSerializationFormatWithAddress(ExternalAddress.ID.get(system).getAddressFor(remote)); - } - } - - // #external-address - - public - // #external-address-default - static class DefaultAddressExt implements Extension { - private final ExtendedActorSystem system; - - public DefaultAddressExt(ExtendedActorSystem system) { - this.system = system; - } - - public Address getAddress() { - return system.provider().getDefaultAddress(); - } - } - - // #external-address-default - public - // #external-address-default - static class DefaultAddress extends AbstractExtensionId - implements ExtensionIdProvider { - public static final DefaultAddress ID = new DefaultAddress(); - - public DefaultAddress lookup() { - return ID; - } - - public DefaultAddressExt createExtension(ExtendedActorSystem system) { - return new DefaultAddressExt(system); - } - } - - // #external-address-default - public void demonstrateDefaultAddress() { // this is not meant to be run, only to be compiled final ActorSystem system = ActorSystem.create(); - final Address remoteAddr = new Address("", ""); + final ActorRef theActorRef = system.deadLetters(); // #external-address-default - final Address addr = DefaultAddress.ID.get(system).getAddress(); + Address selfAddress = Cluster.get(system).selfAddress(); + + String serializedRef = theActorRef.path().toSerializationFormatWithAddress(selfAddress); // #external-address-default } @@ -252,20 +173,19 @@ public class SerializationDocTest { // Have something to serialize String original = "woohoo"; - // Find the Serializer for it - Serializer serializer = serialization.findSerializerFor(original); + // Turn it into bytes, and retrieve the serializerId and manifest, which are needed for + // deserialization + byte[] bytes = serialization.serialize(original).get(); + int serializerId = serialization.findSerializerFor(original).identifier(); + String manifest = Serializers.manifestFor(serialization.findSerializerFor(original), original); - // Turn it into bytes - byte[] bytes = serializer.toBinary(original); - - // Turn it back into an object, - // the nulls are for the class manifest and for the classloader - String back = (String) serializer.fromBinary(bytes); + // Turn it back into an object + String back = (String) serialization.deserialize(bytes, serializerId, manifest).get(); + // #programmatic // Voilá! assertEquals(original, back); - // #programmatic TestKit.shutdownActorSystem(system); } } diff --git a/akka-docs/src/test/scala/docs/serialization/SerializationDocSpec.scala b/akka-docs/src/test/scala/docs/serialization/SerializationDocSpec.scala index b956d79b57..c8535ef542 100644 --- a/akka-docs/src/test/scala/docs/serialization/SerializationDocSpec.scala +++ b/akka-docs/src/test/scala/docs/serialization/SerializationDocSpec.scala @@ -4,17 +4,16 @@ package docs.serialization { - import akka.actor.{ ExtensionId, ExtensionIdProvider } - import akka.testkit._ //#imports - import akka.actor.{ ActorRef, ActorSystem } + import akka.actor._ + import akka.cluster.Cluster import akka.serialization._ - import com.typesafe.config.ConfigFactory //#imports + + import akka.testkit._ + import com.typesafe.config.ConfigFactory import akka.actor.ExtendedActorSystem - import akka.actor.Extension - import akka.actor.Address import java.nio.charset.StandardCharsets //#my-own-serializer @@ -99,6 +98,16 @@ package docs.serialization { final case class Customer(name: String) extends MyOwnSerializable final case class User(name: String) extends MyOwnSerializable + /** + * Marker trait for serialization with Jackson CBOR + */ + trait CborSerializable + + /** + * Marker trait for serialization with Jackson JSON + */ + trait JsonSerializable + class SerializationDocSpec extends AkkaSpec { "demonstrate configuration of serialize messages" in { val config = ConfigFactory.parseString(""" @@ -136,7 +145,8 @@ package docs.serialization { akka { actor { serializers { - java = "akka.serialization.JavaSerializer" + jackson-json = "akka.serialization.jackson.JacksonJsonSerializer" + jackson-cbor = "akka.serialization.jackson.JacksonCborSerializer" proto = "akka.remote.serialization.ProtobufSerializer" myown = "docs.serialization.MyOwnSerializer" } @@ -154,26 +164,24 @@ package docs.serialization { akka { actor { serializers { - java = "akka.serialization.JavaSerializer" + jackson-json = "akka.serialization.jackson.JacksonJsonSerializer" + jackson-cbor = "akka.serialization.jackson.JacksonCborSerializer" proto = "akka.remote.serialization.ProtobufSerializer" myown = "docs.serialization.MyOwnSerializer" } serialization-bindings { - "java.lang.String" = java - "docs.serialization.Customer" = java + "docs.serialization.JsonSerializable" = jackson-json + "docs.serialization.CborSerializable" = jackson-cbor "com.google.protobuf.Message" = proto "docs.serialization.MyOwnSerializable" = myown - "java.lang.Boolean" = myown } } } #//#serialization-bindings-config """) val a = ActorSystem("system", config) - SerializationExtension(a).serializerFor(classOf[String]).getClass should be(classOf[JavaSerializer]) - SerializationExtension(a).serializerFor(classOf[Customer]).getClass should be(classOf[JavaSerializer]) - SerializationExtension(a).serializerFor(classOf[java.lang.Boolean]).getClass should be(classOf[MyOwnSerializer]) + SerializationExtension(a).serializerFor(classOf[Customer]).getClass should be(classOf[MyOwnSerializer]) shutdown(a) } @@ -187,80 +195,47 @@ package docs.serialization { // Have something to serialize val original = "woohoo" - // Find the Serializer for it - val serializer = serialization.findSerializerFor(original) - - // Turn it into bytes - val bytes = serializer.toBinary(original) + // Turn it into bytes, and retrieve the serializerId and manifest, which are needed for deserialization + val bytes = serialization.serialize(original).get + val serializerId = serialization.findSerializerFor(original).identifier + val manifest = Serializers.manifestFor(serialization.findSerializerFor(original), original) // Turn it back into an object - val back = serializer.fromBinary(bytes, manifest = None) + val back = serialization.deserialize(bytes, serializerId, manifest).get + //#programmatic // Voilá! back should be(original) - //#programmatic shutdown(system) } - "demonstrate serialization of ActorRefs" in { + def demonstrateSerializationOfActorRefs(): Unit = { val theActorRef: ActorRef = system.deadLetters val extendedSystem: ExtendedActorSystem = system.asInstanceOf[ExtendedActorSystem] //#actorref-serializer // Serialize // (beneath toBinary) - val identifier: String = Serialization.serializedActorPath(theActorRef) + val serializedRef: String = Serialization.serializedActorPath(theActorRef) // Then serialize the identifier however you like // Deserialize // (beneath fromBinary) - val deserializedActorRef = extendedSystem.provider.resolveActorRef(identifier) + val deserializedRef = extendedSystem.provider.resolveActorRef(serializedRef) // Then use the ActorRef //#actorref-serializer - - //#external-address - object ExternalAddress extends ExtensionId[ExternalAddressExt] with ExtensionIdProvider { - override def lookup() = ExternalAddress - - override def createExtension(system: ExtendedActorSystem): ExternalAddressExt = - new ExternalAddressExt(system) - - override def get(system: ActorSystem): ExternalAddressExt = super.get(system) - } - - class ExternalAddressExt(system: ExtendedActorSystem) extends Extension { - def addressFor(remoteAddr: Address): Address = - system.provider - .getExternalAddressFor(remoteAddr) - .getOrElse(throw new UnsupportedOperationException("cannot send to " + remoteAddr)) - } - - def serializeTo(ref: ActorRef, remote: Address): String = - ref.path.toSerializationFormatWithAddress(ExternalAddress(extendedSystem).addressFor(remote)) - //#external-address } - "demonstrate how to do default Akka serialization of ActorRef" in { - val theActorSystem: ActorSystem = system + def demonstrateSerializationOfActorRefs2(): Unit = { + val theActorRef: ActorRef = system.deadLetters //#external-address-default - object ExternalAddress extends ExtensionId[ExternalAddressExt] with ExtensionIdProvider { - override def lookup() = ExternalAddress + val selfAddress = Cluster(system).selfAddress - override def createExtension(system: ExtendedActorSystem): ExternalAddressExt = - new ExternalAddressExt(system) - - override def get(system: ActorSystem): ExternalAddressExt = super.get(system) - } - - class ExternalAddressExt(system: ExtendedActorSystem) extends Extension { - def addressForAkka: Address = system.provider.getDefaultAddress - } - - def serializeAkkaDefault(ref: ActorRef): String = - ref.path.toSerializationFormatWithAddress(ExternalAddress(theActorSystem).addressForAkka) + val serializedRef: String = + theActorRef.path.toSerializationFormatWithAddress(selfAddress) //#external-address-default } } diff --git a/akka-persistence-query/src/test/scala/akka/persistence/query/journal/leveldb/AllPersistenceIdsSpec.scala b/akka-persistence-query/src/test/scala/akka/persistence/query/journal/leveldb/AllPersistenceIdsSpec.scala index 081b56100d..346202adf9 100644 --- a/akka-persistence-query/src/test/scala/akka/persistence/query/journal/leveldb/AllPersistenceIdsSpec.scala +++ b/akka-persistence-query/src/test/scala/akka/persistence/query/journal/leveldb/AllPersistenceIdsSpec.scala @@ -20,6 +20,9 @@ object AllPersistenceIdsSpec { akka.persistence.journal.plugin = "akka.persistence.journal.leveldb" akka.persistence.journal.leveldb.dir = "target/journal-AllPersistenceIdsSpec" akka.test.single-expect-default = 10s + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """ } diff --git a/akka-persistence-query/src/test/scala/akka/persistence/query/journal/leveldb/EventsByPersistenceIdSpec.scala b/akka-persistence-query/src/test/scala/akka/persistence/query/journal/leveldb/EventsByPersistenceIdSpec.scala index 45de75c2af..37d660fc57 100644 --- a/akka-persistence-query/src/test/scala/akka/persistence/query/journal/leveldb/EventsByPersistenceIdSpec.scala +++ b/akka-persistence-query/src/test/scala/akka/persistence/query/journal/leveldb/EventsByPersistenceIdSpec.scala @@ -22,6 +22,9 @@ object EventsByPersistenceIdSpec { akka.persistence.journal.leveldb.dir = "target/journal-EventsByPersistenceIdSpec" akka.test.single-expect-default = 10s akka.persistence.query.journal.leveldb.refresh-interval = 1s + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """ } diff --git a/akka-persistence-shared/src/test/scala/akka/persistence/journal/leveldb/PersistencePluginProxySpec.scala b/akka-persistence-shared/src/test/scala/akka/persistence/journal/leveldb/PersistencePluginProxySpec.scala index 66516c20ee..4d9f46c628 100644 --- a/akka-persistence-shared/src/test/scala/akka/persistence/journal/leveldb/PersistencePluginProxySpec.scala +++ b/akka-persistence-shared/src/test/scala/akka/persistence/journal/leveldb/PersistencePluginProxySpec.scala @@ -12,7 +12,7 @@ import com.typesafe.config.ConfigFactory object PersistencePluginProxySpec { lazy val config = - ConfigFactory.parseString(""" + ConfigFactory.parseString(s""" akka { actor { provider = remote @@ -44,7 +44,7 @@ object PersistencePluginProxySpec { log-dead-letters-during-shutdown = off test.single-expect-default = 10s } - """) + """).withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) lazy val startTargetConfig = ConfigFactory.parseString(""" diff --git a/akka-persistence-shared/src/test/scala/akka/persistence/journal/leveldb/SharedLeveldbJournalSpec.scala b/akka-persistence-shared/src/test/scala/akka/persistence/journal/leveldb/SharedLeveldbJournalSpec.scala index 7330e56fc1..ff5fefe72c 100644 --- a/akka-persistence-shared/src/test/scala/akka/persistence/journal/leveldb/SharedLeveldbJournalSpec.scala +++ b/akka-persistence-shared/src/test/scala/akka/persistence/journal/leveldb/SharedLeveldbJournalSpec.scala @@ -7,10 +7,10 @@ package akka.persistence.journal.leveldb import akka.actor._ import akka.persistence._ import akka.testkit.{ AkkaSpec, TestProbe } +import com.typesafe.config.ConfigFactory object SharedLeveldbJournalSpec { - val config = - """ + val config = ConfigFactory.parseString(s""" akka { actor { provider = remote @@ -41,7 +41,7 @@ object SharedLeveldbJournalSpec { log-dead-letters-during-shutdown = off test.single-expect-default = 10s } - """ + """).withFallback(SharedLeveldbJournal.configToEnableJavaSerializationForTest) class ExamplePersistentActor(probe: ActorRef, name: String) extends NamedPersistentActor(name) { override def receiveRecover = { diff --git a/akka-persistence-tck/src/main/scala/akka/persistence/journal/JournalSpec.scala b/akka-persistence-tck/src/main/scala/akka/persistence/journal/JournalSpec.scala index 396dad344b..a519a7daeb 100644 --- a/akka-persistence-tck/src/main/scala/akka/persistence/journal/JournalSpec.scala +++ b/akka-persistence-tck/src/main/scala/akka/persistence/journal/JournalSpec.scala @@ -18,6 +18,8 @@ object JournalSpec { val config: Config = ConfigFactory.parseString(s""" akka.persistence.publish-plugin-commands = on akka.actor { + serialize-messages = off + serialize-creators = off serializers { persistence-tck-test = "${classOf[TestSerializer].getName}" } diff --git a/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/LoggerSourceTest.java b/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/LoggerSourceTest.java index 167ef58b7b..8acd26487c 100644 --- a/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/LoggerSourceTest.java +++ b/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/LoggerSourceTest.java @@ -27,7 +27,8 @@ public class LoggerSourceTest extends JUnitSuite { private static final Config config = ConfigFactory.parseString( "akka.loggers = [akka.testkit.TestEventListener] \n" - + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n"); + + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n" + + "akka.persistence.journal.inmem.test-serialization = on \n"); @ClassRule public static final TestKitJunitResource testKit = new TestKitJunitResource(config); diff --git a/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/NullEmptyStateTest.java b/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/NullEmptyStateTest.java index 05b9db8015..a34dcc809d 100644 --- a/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/NullEmptyStateTest.java +++ b/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/NullEmptyStateTest.java @@ -21,7 +21,8 @@ public class NullEmptyStateTest extends JUnitSuite { private static final Config config = ConfigFactory.parseString( - "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n"); + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n" + + "akka.persistence.journal.inmem.test-serialization = on \n"); @ClassRule public static final TestKitJunitResource testKit = new TestKitJunitResource(config); diff --git a/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/PersistentActorJavaDslTest.java b/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/PersistentActorJavaDslTest.java index c0f7156aed..e21d032eb1 100644 --- a/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/PersistentActorJavaDslTest.java +++ b/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/PersistentActorJavaDslTest.java @@ -18,11 +18,15 @@ import akka.persistence.query.Sequence; import akka.persistence.query.journal.leveldb.javadsl.LeveldbReadJournal; import akka.persistence.typed.*; import akka.persistence.typed.scaladsl.EventSourcedBehaviorSpec; +import akka.serialization.jackson.CborSerializable; import akka.stream.ActorMaterializer; import akka.stream.javadsl.Sink; import akka.actor.testkit.typed.javadsl.TestKitJunitResource; import akka.actor.testkit.typed.javadsl.TestProbe; import akka.testkit.javadsl.EventFilter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.typesafe.config.Config; @@ -31,7 +35,6 @@ import org.junit.ClassRule; import org.junit.Test; import org.scalatest.junit.JUnitSuite; -import java.io.Serializable; import java.time.Duration; import java.util.*; @@ -54,7 +57,7 @@ public class PersistentActorJavaDslTest extends JUnitSuite { private ActorMaterializer materializer = ActorMaterializer.create(Adapter.toUntyped(testKit.system())); - interface Command extends Serializable {} + interface Command extends CborSerializable {} public enum Increment implements Command { INSTANCE @@ -83,6 +86,7 @@ public class PersistentActorJavaDslTest extends JUnitSuite { public static class IncrementWithConfirmation implements Command, ExpectingReply { private final ActorRef replyTo; + @JsonCreator public IncrementWithConfirmation(ActorRef replyTo) { this.replyTo = replyTo; } @@ -104,6 +108,7 @@ public class PersistentActorJavaDslTest extends JUnitSuite { public static class GetValue implements Command, ExpectingReply { private final ActorRef replyTo; + @JsonCreator public GetValue(ActorRef replyTo) { this.replyTo = replyTo; } @@ -114,9 +119,15 @@ public class PersistentActorJavaDslTest extends JUnitSuite { } } - public static class Incremented implements Serializable { + // need the JsonTypeInfo because of the Wrapper + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") + @JsonSubTypes({@JsonSubTypes.Type(value = Incremented.class, name = "incremented")}) + interface Event extends CborSerializable {} + + public static class Incremented implements Event { final int delta; + @JsonCreator public Incremented(int delta) { this.delta = delta; } @@ -141,7 +152,7 @@ public class PersistentActorJavaDslTest extends JUnitSuite { } } - public static class State implements Serializable { + public static class State implements CborSerializable { final int value; final List history; @@ -187,7 +198,7 @@ public class PersistentActorJavaDslTest extends JUnitSuite { } @SuppressWarnings("unused") - private static class CounterBehavior extends EventSourcedBehavior { + private static class CounterBehavior extends EventSourcedBehavior { private final ActorContext ctx; CounterBehavior(PersistenceId persistenceId, ActorContext ctx) { @@ -198,7 +209,7 @@ public class PersistentActorJavaDslTest extends JUnitSuite { } @Override - public CommandHandler commandHandler() { + public CommandHandler commandHandler() { return newCommandHandlerBuilder() .forAnyState() .onCommand(Increment.class, this::increment) @@ -214,20 +225,20 @@ public class PersistentActorJavaDslTest extends JUnitSuite { .build(); } - private Effect increment(State state, Increment command) { + private Effect increment(State state, Increment command) { return Effect().persist(new Incremented(1)); } - private ReplyEffect incrementWithConfirmation( + private ReplyEffect incrementWithConfirmation( State state, IncrementWithConfirmation command) { return Effect().persist(new Incremented(1)).thenReply(command, newState -> done()); } - private ReplyEffect getValue(State state, GetValue command) { + private ReplyEffect getValue(State state, GetValue command) { return Effect().reply(command, state); } - private Effect incrementLater(State state, IncrementLater command) { + private Effect incrementLater(State state, IncrementLater command) { ActorRef delay = ctx.spawnAnonymous( Behaviors.withTimers( @@ -239,38 +250,36 @@ public class PersistentActorJavaDslTest extends JUnitSuite { return Effect().none(); } - private Effect delayFinished(State state, DelayFinished command) { + private Effect delayFinished(State state, DelayFinished command) { return Effect().persist(new Incremented(10)); } - private Effect increment100OnTimeout( - State state, Increment100OnTimeout command) { + private Effect increment100OnTimeout(State state, Increment100OnTimeout command) { ctx.setReceiveTimeout(Duration.ofMillis(10), Timeout.INSTANCE); return Effect().none(); } - private Effect timeout(State state, Timeout command) { + private Effect timeout(State state, Timeout command) { return Effect().persist(new Incremented(100)); } - private Effect emptyEventsListAndThenLog( + private Effect emptyEventsListAndThenLog( State state, EmptyEventsListAndThenLog command) { return Effect().persist(Collections.emptyList()).thenRun(s -> log()); } - private Effect stopThenLog(State state, StopThenLog command) { + private Effect stopThenLog(State state, StopThenLog command) { return Effect().stop().thenRun(s -> log()); } - private Effect incrementTwiceAndLog( - State state, IncrementTwiceAndLog command) { + private Effect incrementTwiceAndLog(State state, IncrementTwiceAndLog command) { return Effect() .persist(Arrays.asList(new Incremented(1), new Incremented(1))) .thenRun(s -> log()); } @Override - public EventHandler eventHandler() { + public EventHandler eventHandler() { return newEventHandlerBuilder() .forAnyState() .onEvent(Incremented.class, this::applyIncremented) @@ -407,7 +416,7 @@ public class PersistentActorJavaDslTest extends JUnitSuite { ctx -> new CounterBehavior(new PersistenceId("snapshot"), ctx) { @Override - public boolean shouldSnapshot(State state, Incremented event, long sequenceNr) { + public boolean shouldSnapshot(State state, Event event, long sequenceNr) { return state.value % 2 == 0; } @@ -523,7 +532,7 @@ public class PersistentActorJavaDslTest extends JUnitSuite { ctx -> new CounterBehavior(new PersistenceId("tagging"), ctx) { @Override - public Set tagsFor(Incremented incremented) { + public Set tagsFor(Event incremented) { return Sets.newHashSet("tag1", "tag2"); } }); @@ -552,9 +561,9 @@ public class PersistentActorJavaDslTest extends JUnitSuite { Behaviors.setup( ctx -> new CounterBehavior(new PersistenceId("transform"), ctx) { - private final EventAdapter adapter = new WrapperEventAdapter(); + private final EventAdapter adapter = new WrapperEventAdapter(); - public EventAdapter eventAdapter() { + public EventAdapter eventAdapter() { return adapter; } }); @@ -574,7 +583,7 @@ public class PersistentActorJavaDslTest extends JUnitSuite { .get(); assertEquals( Lists.newArrayList( - new EventEnvelope(new Sequence(1), "transform", 1, new Wrapper<>(new Incremented(1)))), + new EventEnvelope(new Sequence(1), "transform", 1, new Wrapper(new Incremented(1)))), events); ActorRef c2 = testKit.spawn(transformer); @@ -583,15 +592,16 @@ public class PersistentActorJavaDslTest extends JUnitSuite { } // event-wrapper - public static class Wrapper implements Serializable { - private final T t; + public static class Wrapper implements CborSerializable { + private final Event event; - public Wrapper(T t) { - this.t = t; + @JsonCreator + public Wrapper(Event event) { + this.event = event; } - public T getT() { - return t; + public Event getEvent() { + return event; } @Override @@ -599,31 +609,36 @@ public class PersistentActorJavaDslTest extends JUnitSuite { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - Wrapper wrapper = (Wrapper) o; + Wrapper wrapper = (Wrapper) o; - return t.equals(wrapper.t); + return event.equals(wrapper.event); } @Override public int hashCode() { - return t.hashCode(); + return event.hashCode(); + } + + @Override + public String toString() { + return "Wrapper(" + event + ")"; } } - class WrapperEventAdapter extends EventAdapter> { + class WrapperEventAdapter extends EventAdapter { @Override - public Wrapper toJournal(Incremented incremented) { - return new Wrapper<>(incremented); + public Wrapper toJournal(Event event) { + return new Wrapper(event); } @Override - public String manifest(Incremented event) { + public String manifest(Event event) { return ""; } @Override - public EventSeq fromJournal(Wrapper wrapper, String manifest) { - return EventSeq.single(wrapper.getT()); + public EventSeq fromJournal(Wrapper wrapper, String manifest) { + return EventSeq.single(wrapper.getEvent()); } } // event-wrapper diff --git a/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/PrimitiveStateTest.java b/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/PrimitiveStateTest.java index 83cb9163e7..037b438bf3 100644 --- a/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/PrimitiveStateTest.java +++ b/akka-persistence-typed/src/test/java/akka/persistence/typed/javadsl/PrimitiveStateTest.java @@ -21,7 +21,8 @@ public class PrimitiveStateTest extends JUnitSuite { private static final Config config = ConfigFactory.parseString( - "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n"); + "akka.persistence.journal.plugin = \"akka.persistence.journal.inmem\" \n" + + "akka.persistence.journal.inmem.test-serialization = on \n"); @ClassRule public static final TestKitJunitResource testKit = new TestKitJunitResource(config); diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/ManyRecoveriesSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/ManyRecoveriesSpec.scala index 6de0650925..8802a0b21f 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/ManyRecoveriesSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/ManyRecoveriesSpec.scala @@ -60,7 +60,6 @@ class ManyRecoveriesSpec extends ScalaTestWithActorTestKit(s""" } akka.persistence.max-concurrent-recoveries = 3 akka.persistence.journal.plugin = "akka.persistence.journal.inmem" - akka.actor.warn-about-java-serializer-usage = off """) with WordSpecLike { import ManyRecoveriesSpec._ diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/internal/RecoveryPermitterSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/internal/RecoveryPermitterSpec.scala index ec232fad12..0997fb42d1 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/internal/RecoveryPermitterSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/internal/RecoveryPermitterSpec.scala @@ -71,7 +71,7 @@ class RecoveryPermitterSpec extends ScalaTestWithActorTestKit(s""" akka.loggers = [akka.testkit.TestEventListener] akka.persistence.max-concurrent-recoveries = 3 akka.persistence.journal.plugin = "akka.persistence.journal.inmem" - akka.actor.warn-about-java-serializer-usage = off + akka.persistence.journal.inmem.test-serialization = on akka.loggers = ["akka.testkit.TestEventListener"] """) with WordSpecLike { diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorInterceptorSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorInterceptorSpec.scala index 6a95ab9362..f7a95b4b14 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorInterceptorSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorInterceptorSpec.scala @@ -27,6 +27,7 @@ object EventSourcedBehaviorInterceptorSpec { akka.loglevel = INFO akka.loggers = [akka.testkit.TestEventListener] akka.persistence.journal.plugin = "akka.persistence.journal.inmem" + akka.persistence.journal.inmem.test-serialization = on """) def testBehavior(persistenceId: PersistenceId, probe: ActorRef[String]): Behavior[String] = diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorReplySpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorReplySpec.scala index 661610e439..86920fbf8d 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorReplySpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorReplySpec.scala @@ -15,6 +15,7 @@ import akka.actor.typed.scaladsl.ActorContext import akka.actor.typed.scaladsl.Behaviors import akka.persistence.typed.ExpectingReply import akka.persistence.typed.PersistenceId +import akka.serialization.jackson.CborSerializable import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import org.scalatest.WordSpecLike @@ -29,16 +30,16 @@ object EventSourcedBehaviorReplySpec { akka.persistence.snapshot-store.local.dir = "target/typed-persistence-${UUID.randomUUID().toString}" """) - sealed trait Command[ReplyMessage] extends ExpectingReply[ReplyMessage] + sealed trait Command[ReplyMessage] extends ExpectingReply[ReplyMessage] with CborSerializable final case class IncrementWithConfirmation(override val replyTo: ActorRef[Done]) extends Command[Done] final case class IncrementReplyLater(override val replyTo: ActorRef[Done]) extends Command[Done] final case class ReplyNow(override val replyTo: ActorRef[Done]) extends Command[Done] final case class GetValue(replyTo: ActorRef[State]) extends Command[State] - sealed trait Event + sealed trait Event extends CborSerializable final case class Incremented(delta: Int) extends Event - final case class State(value: Int, history: Vector[Int]) + final case class State(value: Int, history: Vector[Int]) extends CborSerializable def counter(persistenceId: PersistenceId): Behavior[Command[_]] = Behaviors.setup(ctx => counter(ctx, persistenceId)) diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorRetentionSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorRetentionSpec.scala index 9a2e0f6b73..902e08bede 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorRetentionSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorRetentionSpec.scala @@ -28,6 +28,7 @@ import akka.persistence.typed.SnapshotCompleted import akka.persistence.typed.SnapshotFailed import akka.persistence.typed.SnapshotMetadata import akka.persistence.typed.SnapshotSelectionCriteria +import akka.serialization.jackson.CborSerializable import akka.testkit.EventFilter import akka.testkit.TestEvent.Mute import akka.util.unused @@ -47,16 +48,16 @@ object EventSourcedBehaviorRetentionSpec { akka.persistence.snapshot-store.local.dir = "target/typed-persistence-${UUID.randomUUID().toString}" """) - sealed trait Command + sealed trait Command extends CborSerializable final case object Increment extends Command final case class IncrementWithPersistAll(nr: Int) extends Command final case class GetValue(replyTo: ActorRef[State]) extends Command final case object StopIt extends Command - sealed trait Event + sealed trait Event extends CborSerializable final case class Incremented(delta: Int) extends Event - final case class State(value: Int, history: Vector[Int]) + final case class State(value: Int, history: Vector[Int]) extends CborSerializable def counter(persistenceId: PersistenceId)(implicit system: ActorSystem[_]): Behavior[Command] = Behaviors.setup(ctx => counter(ctx, persistenceId)) diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorSpec.scala index 4abc10b28f..69ff82a49e 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedBehaviorSpec.scala @@ -40,6 +40,7 @@ import akka.persistence.typed.SnapshotFailed import akka.persistence.typed.SnapshotMetadata import akka.persistence.{ SnapshotMetadata => UntypedSnapshotMetadata } import akka.persistence.{ SnapshotSelectionCriteria => UntypedSnapshotSelectionCriteria } +import akka.serialization.jackson.CborSerializable import akka.stream.ActorMaterializer import akka.stream.scaladsl.Sink import akka.testkit.EventFilter @@ -94,7 +95,7 @@ object EventSourcedBehaviorSpec { } """) - sealed trait Command + sealed trait Command extends CborSerializable final case object Increment extends Command final case object IncrementThenLogThenStop extends Command final case object IncrementTwiceThenLogThenStop extends Command @@ -114,10 +115,10 @@ object EventSourcedBehaviorSpec { final case object Fail extends Command final case object StopIt extends Command - sealed trait Event + sealed trait Event extends CborSerializable final case class Incremented(delta: Int) extends Event - final case class State(value: Int, history: Vector[Int]) + final case class State(value: Int, history: Vector[Int]) extends CborSerializable case object Tick diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedEventAdapterSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedEventAdapterSpec.scala index 1669d1957d..474633e06a 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedEventAdapterSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedEventAdapterSpec.scala @@ -18,9 +18,11 @@ import akka.persistence.query.journal.leveldb.scaladsl.LeveldbReadJournal import akka.persistence.typed.EventAdapter import akka.persistence.typed.EventSeq import akka.persistence.typed.PersistenceId +import akka.serialization.jackson.CborSerializable import akka.stream.ActorMaterializer import akka.stream.scaladsl.Sink import akka.testkit.EventFilter +import akka.testkit.JavaSerializable import akka.testkit.TestEvent.Mute import com.typesafe.config.ConfigFactory import org.scalatest.WordSpecLike @@ -33,10 +35,10 @@ object EventSourcedEventAdapterSpec { akka.persistence.journal.plugin = "akka.persistence.journal.leveldb" """) - case class Wrapper(t: String) + case class Wrapper(event: String) extends CborSerializable class WrapperEventAdapter extends EventAdapter[String, Wrapper] { override def toJournal(e: String): Wrapper = Wrapper("<" + e) - override def fromJournal(p: Wrapper, manifest: String): EventSeq[String] = EventSeq.single(p.t + ">") + override def fromJournal(p: Wrapper, manifest: String): EventSeq[String] = EventSeq.single(p.event + ">") override def manifest(event: String): String = "" } @@ -71,10 +73,11 @@ object EventSourcedEventAdapterSpec { override def manifest(event: String): String = event.length.toString } - case class GenericWrapper[T](t: T) + // generics doesn't work with Jackson, so using Java serialization + case class GenericWrapper[T](event: T) extends JavaSerializable class GenericWrapperEventAdapter[T] extends EventAdapter[T, GenericWrapper[T]] { override def toJournal(e: T): GenericWrapper[T] = GenericWrapper(e) - override def fromJournal(p: GenericWrapper[T], manifest: String): EventSeq[T] = EventSeq.single(p.t) + override def fromJournal(p: GenericWrapper[T], manifest: String): EventSeq[T] = EventSeq.single(p.event) override def manifest(event: T): String = "" } diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedSequenceNumberSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedSequenceNumberSpec.scala index dd4d9639cc..3499dcec23 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedSequenceNumberSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/EventSourcedSequenceNumberSpec.scala @@ -19,6 +19,7 @@ object EventSourcedSequenceNumberSpec { private val conf = ConfigFactory.parseString(s""" akka.loggers = [akka.testkit.TestEventListener] akka.persistence.journal.plugin = "akka.persistence.journal.inmem" + akka.persistence.journal.inmem.test-serialization = on """) } diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/NullEmptyStateSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/NullEmptyStateSpec.scala index d955a365e3..7f5340c458 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/NullEmptyStateSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/NullEmptyStateSpec.scala @@ -20,6 +20,7 @@ object NullEmptyStateSpec { private val conf = ConfigFactory.parseString(s""" akka.loggers = [akka.testkit.TestEventListener] akka.persistence.journal.plugin = "akka.persistence.journal.inmem" + akka.persistence.journal.inmem.test-serialization = on """) } diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/OptionalSnapshotStoreSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/OptionalSnapshotStoreSpec.scala index ba9e9d5f49..ff6fbffc25 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/OptionalSnapshotStoreSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/OptionalSnapshotStoreSpec.scala @@ -11,18 +11,19 @@ import akka.actor.testkit.typed.scaladsl.TestProbe import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps import akka.persistence.typed.PersistenceId import akka.persistence.typed.scaladsl.EventSourcedBehavior.CommandHandler +import akka.serialization.jackson.CborSerializable import akka.testkit.EventFilter import org.scalatest.WordSpecLike object OptionalSnapshotStoreSpec { - sealed trait Command + sealed trait Command extends CborSerializable object AnyCommand extends Command - final case class State(internal: String = UUID.randomUUID().toString) + final case class State(internal: String = UUID.randomUUID().toString) extends CborSerializable - case class Event(id: Long = System.currentTimeMillis()) + case class Event(id: Long = System.currentTimeMillis()) extends CborSerializable def persistentBehavior(probe: TestProbe[State], name: String = UUID.randomUUID().toString) = EventSourcedBehavior[Command, Event, State]( @@ -44,9 +45,7 @@ class OptionalSnapshotStoreSpec extends ScalaTestWithActorTestKit(s""" akka.loggers = [akka.testkit.TestEventListener] akka.persistence.publish-plugin-commands = on akka.persistence.journal.plugin = "akka.persistence.journal.inmem" - akka.persistence.journal.leveldb.dir = "target/journal-${classOf[OptionalSnapshotStoreSpec].getName}" - - akka.actor.warn-about-java-serializer-usage = off + akka.persistence.journal.inmem.test-serialization = on # snapshot store plugin is NOT defined, things should still work akka.persistence.snapshot-store.local.dir = "target/snapshots-${classOf[OptionalSnapshotStoreSpec].getName}/" diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/PerformanceSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/PerformanceSpec.scala index 55ef7b906e..e54f56194f 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/PerformanceSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/PerformanceSpec.scala @@ -112,7 +112,6 @@ object PerformanceSpec { class PerformanceSpec extends ScalaTestWithActorTestKit(ConfigFactory.parseString(s""" akka.actor.serialize-creators = off akka.actor.serialize-messages = off - akka.actor.warn-about-java-serializer-usage = off akka.persistence.publish-plugin-commands = on akka.persistence.journal.plugin = "akka.persistence.journal.leveldb" akka.persistence.journal.leveldb.dir = "target/journal-PerformanceSpec" diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/PrimitiveStateSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/PrimitiveStateSpec.scala index 9e857ed85a..c6c0dc06cc 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/PrimitiveStateSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/PrimitiveStateSpec.scala @@ -19,6 +19,7 @@ object PrimitiveStateSpec { private val conf = ConfigFactory.parseString(s""" akka.loggers = [akka.testkit.TestEventListener] akka.persistence.journal.plugin = "akka.persistence.journal.inmem" + akka.persistence.journal.inmem.test-serialization = on """) } diff --git a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/SnapshotMutableStateSpec.scala b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/SnapshotMutableStateSpec.scala index f4c6e19aaa..c05c22fa98 100644 --- a/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/SnapshotMutableStateSpec.scala +++ b/akka-persistence-typed/src/test/scala/akka/persistence/typed/scaladsl/SnapshotMutableStateSpec.scala @@ -19,6 +19,7 @@ import akka.persistence.typed.SnapshotCompleted import akka.persistence.typed.SnapshotFailed import akka.persistence.{ SnapshotSelectionCriteria => UntypedSnapshotSelectionCriteria } import akka.persistence.{ SnapshotMetadata => UntypedSnapshotMetadata } +import akka.serialization.jackson.CborSerializable import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import org.scalatest.WordSpecLike @@ -76,14 +77,14 @@ object SnapshotMutableStateSpec { slow-snapshot-store.class = "${classOf[SlowInMemorySnapshotStore].getName}" """) - sealed trait Command + sealed trait Command extends CborSerializable case object Increment extends Command final case class GetValue(replyTo: ActorRef[Int]) extends Command - sealed trait Event + sealed trait Event extends CborSerializable case object Incremented extends Event - final class MutableState(var value: Int) + final class MutableState(var value: Int) extends CborSerializable def counter( persistenceId: PersistenceId, diff --git a/akka-persistence/src/main/resources/reference.conf b/akka-persistence/src/main/resources/reference.conf index 25e629903d..2e4c22d4de 100644 --- a/akka-persistence/src/main/resources/reference.conf +++ b/akka-persistence/src/main/resources/reference.conf @@ -207,6 +207,9 @@ akka.persistence.journal.inmem { class = "akka.persistence.journal.inmem.InmemJournal" # Dispatcher for the plugin actor. plugin-dispatcher = "akka.actor.default-dispatcher" + + # Turn this on to test serialization of the events + test-serialization = off } # Local file system snapshot store plugin. diff --git a/akka-persistence/src/main/scala/akka/persistence/journal/inmem/InmemJournal.scala b/akka-persistence/src/main/scala/akka/persistence/journal/inmem/InmemJournal.scala index 1da9c78ac3..83730430f3 100644 --- a/akka-persistence/src/main/scala/akka/persistence/journal/inmem/InmemJournal.scala +++ b/akka-persistence/src/main/scala/akka/persistence/journal/inmem/InmemJournal.scala @@ -7,20 +7,45 @@ package akka.persistence.journal.inmem import scala.collection.immutable import scala.concurrent.Future import scala.util.Try +import scala.util.control.NonFatal + import akka.persistence.journal.AsyncWriteJournal import akka.persistence.PersistentRepr import akka.persistence.AtomicWrite +import akka.serialization.SerializationExtension +import akka.serialization.Serializers +import com.typesafe.config.Config +import com.typesafe.config.ConfigFactory /** * INTERNAL API. * * In-memory journal for testing purposes only. */ -private[persistence] class InmemJournal extends AsyncWriteJournal with InmemMessages { +private[persistence] class InmemJournal(cfg: Config) extends AsyncWriteJournal with InmemMessages { + + def this() = this(ConfigFactory.empty()) + + private val testSerialization = { + val key = "test-serialization" + if (cfg.hasPath(key)) cfg.getBoolean("test-serialization") + else false + } + + private val serialization = SerializationExtension(context.system) + override def asyncWriteMessages(messages: immutable.Seq[AtomicWrite]): Future[immutable.Seq[Try[Unit]]] = { - for (w <- messages; p <- w.payload) - add(p) - Future.successful(Nil) // all good + try { + for (w <- messages; p <- w.payload) { + verifySerialization(p.payload) + add(p) + } + Future.successful(Nil) // all good + } catch { + case NonFatal(e) => + // serialization problem + Future.failed(e) + } } override def asyncReadHighestSequenceNr(persistenceId: String, fromSequenceNr: Long): Future[Long] = { @@ -44,6 +69,16 @@ private[persistence] class InmemJournal extends AsyncWriteJournal with InmemMess } Future.successful(()) } + + private def verifySerialization(event: Any): Unit = { + if (testSerialization) { + val eventAnyRef = event.asInstanceOf[AnyRef] + val bytes = serialization.serialize(eventAnyRef).get + val serializer = serialization.findSerializerFor(eventAnyRef) + val manifest = Serializers.manifestFor(serializer, eventAnyRef) + serialization.deserialize(bytes, serializer.identifier, manifest).get + } + } } /** diff --git a/akka-persistence/src/main/scala/akka/persistence/journal/leveldb/LeveldbJournal.scala b/akka-persistence/src/main/scala/akka/persistence/journal/leveldb/LeveldbJournal.scala index 29a242fb5e..9cd5f4127c 100644 --- a/akka-persistence/src/main/scala/akka/persistence/journal/leveldb/LeveldbJournal.scala +++ b/akka-persistence/src/main/scala/akka/persistence/journal/leveldb/LeveldbJournal.scala @@ -11,10 +11,12 @@ import akka.util.Timeout import akka.util.Helpers.ConfigOps import akka.persistence.PersistentRepr import scala.concurrent.Future + import akka.persistence.JournalProtocol.RecoverySuccess import akka.persistence.JournalProtocol.ReplayMessagesFailure import akka.pattern.pipe import com.typesafe.config.Config +import com.typesafe.config.ConfigFactory /** * INTERNAL API. @@ -144,6 +146,9 @@ private[persistence] class SharedLeveldbJournal extends AsyncWriteProxy { } } +/** + * For testing only. + */ object SharedLeveldbJournal { /** @@ -153,4 +158,25 @@ object SharedLeveldbJournal { */ def setStore(store: ActorRef, system: ActorSystem): Unit = Persistence(system).journalFor(null) ! AsyncWriteProxy.SetStore(store) + + /** + * Configuration to enable `TestJavaSerializer` in `akka-testkit` for + * for the messages used by `SharedLeveldbJournal`. + * + * For testing only. + */ + def configToEnableJavaSerializationForTest: Config = { + ConfigFactory.parseString(s""" + akka.actor.serialization-bindings { + "akka.persistence.journal.AsyncWriteTarget$$WriteMessages" = java-test + "akka.persistence.journal.AsyncWriteTarget$$DeleteMessagesTo" = java-test + "akka.persistence.journal.AsyncWriteTarget$$ReplayMessages" = java-test + "akka.persistence.journal.AsyncWriteTarget$$ReplaySuccess" = java-test + "akka.persistence.journal.AsyncWriteTarget$$ReplayFailure" = java-test + "akka.persistence.JournalProtocol$$Message" = java-test + "akka.persistence.SnapshotProtocol$$Message" = java-test + "scala.collection.immutable.Vector" = java-test + } + """) + } } diff --git a/akka-persistence/src/test/scala/akka/persistence/PersistenceSpec.scala b/akka-persistence/src/test/scala/akka/persistence/PersistenceSpec.scala index e8ed88b75e..30d37f6676 100644 --- a/akka-persistence/src/test/scala/akka/persistence/PersistenceSpec.scala +++ b/akka-persistence/src/test/scala/akka/persistence/PersistenceSpec.scala @@ -59,13 +59,15 @@ abstract class PersistenceSpec(config: Config) } object PersistenceSpec { - def config(plugin: String, test: String, serialization: String = "on", extraConfig: Option[String] = None) = + def config(plugin: String, test: String, serialization: String = "off", extraConfig: Option[String] = None) = extraConfig .map(ConfigFactory.parseString(_)) .getOrElse(ConfigFactory.empty()) .withFallback(ConfigFactory.parseString(s""" akka.actor.serialize-creators = ${serialization} akka.actor.serialize-messages = ${serialization} + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on akka.actor.warn-about-java-serializer-usage = off akka.persistence.publish-plugin-commands = on akka.persistence.journal.plugin = "akka.persistence.journal.${plugin}" diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/remote/RemoteDeliverySpec.scala b/akka-remote-tests/src/multi-jvm/scala/akka/remote/RemoteDeliverySpec.scala index 284df13168..b59292cc6c 100644 --- a/akka-remote-tests/src/multi-jvm/scala/akka/remote/RemoteDeliverySpec.scala +++ b/akka-remote-tests/src/multi-jvm/scala/akka/remote/RemoteDeliverySpec.scala @@ -5,8 +5,8 @@ package akka.remote import scala.language.postfixOps - import scala.concurrent.duration._ + import com.typesafe.config.ConfigFactory import akka.actor.Actor import akka.actor.ActorRef @@ -15,6 +15,7 @@ import akka.remote.testconductor.RoleName import akka.remote.testkit.MultiNodeConfig import akka.actor.ActorIdentity import akka.actor.Identify +import akka.serialization.jackson.CborSerializable class RemoteDeliveryConfig(artery: Boolean) extends MultiNodeConfig { val first = role("first") @@ -35,7 +36,7 @@ class ArteryRemoteDeliveryMultiJvmNode2 extends RemoteDeliverySpec(new RemoteDel class ArteryRemoteDeliveryMultiJvmNode3 extends RemoteDeliverySpec(new RemoteDeliveryConfig(artery = true)) object RemoteDeliverySpec { - final case class Letter(n: Int, route: List[ActorRef]) + final case class Letter(n: Int, route: List[ActorRef]) extends CborSerializable class Postman extends Actor { def receive = { diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/remote/RemoteQuarantinePiercingSpec.scala b/akka-remote-tests/src/multi-jvm/scala/akka/remote/RemoteQuarantinePiercingSpec.scala index 20f3b77aa6..50c198d96e 100644 --- a/akka-remote-tests/src/multi-jvm/scala/akka/remote/RemoteQuarantinePiercingSpec.scala +++ b/akka-remote-tests/src/multi-jvm/scala/akka/remote/RemoteQuarantinePiercingSpec.scala @@ -21,6 +21,9 @@ class RemoteQuarantinePiercingConfig(artery: Boolean) extends MultiNodeConfig { akka.loglevel = INFO akka.remote.log-remote-lifecycle-events = INFO akka.remote.artery.enabled = $artery + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """)).withFallback(RemotingMultiNodeSpec.commonConfig)) } diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/DirectMemorySpec.scala b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/DirectMemorySpec.scala index a142f7ece2..f2b69ac9e2 100644 --- a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/DirectMemorySpec.scala +++ b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/DirectMemorySpec.scala @@ -5,10 +5,12 @@ package akka.remote.artery import scala.concurrent.duration._ + import akka.actor.{ Actor, ActorPath, ActorRef, Props } import akka.remote.RemotingMultiNodeSpec import akka.remote.testkit.{ MultiNodeConfig, MultiNodeSpec, STMultiNodeSpec } import akka.testkit.ImplicitSender +import akka.testkit.JavaSerializable import com.typesafe.config.ConfigFactory object DirectMemorySpec extends MultiNodeConfig { @@ -31,9 +33,9 @@ object DirectMemorySpec extends MultiNodeConfig { // buffer pool + large buffer pool = 16M, see DirectMemorySpecMultiJvmNode1.opts - case class Message() - case class Start(rootPath: ActorPath) - case class Done(actor: ActorRef) + case object Message extends JavaSerializable + case class Start(rootPath: ActorPath) extends JavaSerializable + case class Done(actor: ActorRef) extends JavaSerializable class CountingEcho(reportTo: ActorRef, private var count: Int) extends Actor { override def receive: Receive = { case Start(rootPath) => diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/HandshakeRestartReceiverSpec.scala b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/HandshakeRestartReceiverSpec.scala index 51e29c055f..1ef209c8b8 100644 --- a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/HandshakeRestartReceiverSpec.scala +++ b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/HandshakeRestartReceiverSpec.scala @@ -28,6 +28,9 @@ object HandshakeRestartReceiverSpec extends MultiNodeConfig { enabled = on } } + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """))) class Subject extends Actor { diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/LatencySpec.scala b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/LatencySpec.scala index 75c1c795c8..46edbdb975 100644 --- a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/LatencySpec.scala +++ b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/LatencySpec.scala @@ -15,6 +15,7 @@ import akka.dispatch.Dispatchers import akka.remote.RemotingMultiNodeSpec import akka.remote.testconductor.RoleName import akka.remote.testkit.MultiNodeConfig +import akka.serialization.jackson.CborSerializable import akka.stream.ActorMaterializer import akka.testkit._ import com.typesafe.config.ConfigFactory @@ -65,7 +66,7 @@ object LatencySpec extends MultiNodeConfig { } """)).withFallback(RemotingMultiNodeSpec.commonConfig)) - final case object Reset + final case object Reset extends CborSerializable def echoProps(): Props = Props(new Echo).withDispatcher(Dispatchers.InternalDispatcherId) diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/MaxThroughputSpec.scala b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/MaxThroughputSpec.scala index 7990f8ac8e..01c8cb8f56 100644 --- a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/MaxThroughputSpec.scala +++ b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/MaxThroughputSpec.scala @@ -9,6 +9,7 @@ import java.util.concurrent.Executors import java.util.concurrent.TimeUnit.NANOSECONDS import scala.concurrent.duration._ + import akka.actor._ import akka.remote.{ RARP, RemoteActorRefProvider, RemotingMultiNodeSpec } import akka.remote.testconductor.RoleName @@ -19,6 +20,7 @@ import akka.serialization.SerializerWithStringManifest import akka.testkit._ import com.typesafe.config.ConfigFactory import akka.remote.artery.compress.CompressionProtocol.Events.ReceivedActorRefCompressionTable +import akka.serialization.jackson.CborSerializable object MaxThroughputSpec extends MultiNodeConfig { val first = role("first") @@ -82,16 +84,17 @@ object MaxThroughputSpec extends MultiNodeConfig { # Set to 10 by default. Might be worthwhile to experiment with. # throughput = 100 } - """) + """) commonConfig(debugConfig(on = false).withFallback(cfg).withFallback(RemotingMultiNodeSpec.commonConfig)) case object Run - sealed trait Echo extends DeadLetterSuppression with JavaSerializable + sealed trait Echo extends DeadLetterSuppression with CborSerializable + final case object StartAck extends Echo final case class Start(correspondingReceiver: ActorRef) extends Echo final case object End extends Echo - final case class Warmup(msg: AnyRef) - final case class EndResult(totalReceived: Long) extends JavaSerializable + final case class Warmup(payload: AnyRef) extends CborSerializable + final case class EndResult(totalReceived: Long) extends CborSerializable final case class FlowControl(id: Int, burstStartTime: Long) extends Echo sealed trait Target { @@ -129,7 +132,7 @@ object MaxThroughputSpec extends MultiNodeConfig { case Start(corresponding) => if (corresponding == self) correspondingSender = sender() - sender() ! Start + sender() ! StartAck case End if endMessagesMissing > 1 => endMessagesMissing -= 1 // wait for End message from all senders @@ -216,7 +219,7 @@ object MaxThroughputSpec extends MultiNodeConfig { } def warmup: Receive = { - case Start => + case StartAck => println( s"${self.path.name}: Starting benchmark of $totalMessages messages with burst size " + s"$burstSize and payload size $payloadSize") diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/RemoteRestartedQuarantinedSpec.scala b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/RemoteRestartedQuarantinedSpec.scala index 7e2f4f5664..48268d9955 100644 --- a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/RemoteRestartedQuarantinedSpec.scala +++ b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/RemoteRestartedQuarantinedSpec.scala @@ -20,11 +20,16 @@ object RemoteRestartedQuarantinedSpec extends MultiNodeConfig { val second = role("second") commonConfig( - debugConfig(on = false).withFallback(ConfigFactory.parseString(""" + debugConfig(on = false) + .withFallback(ConfigFactory.parseString(""" akka.loglevel = WARNING akka.remote.log-remote-lifecycle-events = WARNING akka.remote.artery.enabled = on - """)).withFallback(RemotingMultiNodeSpec.commonConfig)) + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """)) + .withFallback(RemotingMultiNodeSpec.commonConfig)) class Subject extends Actor { def receive = { diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/UdpPortActor.scala b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/UdpPortActor.scala index c5d7f1db37..a88eb5512c 100644 --- a/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/UdpPortActor.scala +++ b/akka-remote-tests/src/multi-jvm/scala/akka/remote/artery/UdpPortActor.scala @@ -6,10 +6,11 @@ package akka.remote.artery import akka.actor.Actor import akka.remote.RARP +import akka.serialization.jackson.CborSerializable import akka.testkit.SocketUtil object UdpPortActor { - case object GetUdpPort + case object GetUdpPort extends CborSerializable } /** diff --git a/akka-remote-tests/src/multi-jvm/scala/akka/remote/classic/RemoteRestartedQuarantinedSpec.scala b/akka-remote-tests/src/multi-jvm/scala/akka/remote/classic/RemoteRestartedQuarantinedSpec.scala index b95d63a04e..c549189be8 100644 --- a/akka-remote-tests/src/multi-jvm/scala/akka/remote/classic/RemoteRestartedQuarantinedSpec.scala +++ b/akka-remote-tests/src/multi-jvm/scala/akka/remote/classic/RemoteRestartedQuarantinedSpec.scala @@ -33,7 +33,10 @@ object RemoteRestartedQuarantinedSpec extends MultiNodeConfig { # TODO should not be needed, but see TODO at the end of the test akka.remote.classic.transport-failure-detector.heartbeat-interval = 1 s akka.remote.classic.transport-failure-detector.acceptable-heartbeat-pause = 10 s - """))) + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """))) testTransport(on = true) diff --git a/akka-remote-tests/src/test/resources/reference.conf b/akka-remote-tests/src/test/resources/reference.conf index 87c449d340..36ca1444da 100644 --- a/akka-remote-tests/src/test/resources/reference.conf +++ b/akka-remote-tests/src/test/resources/reference.conf @@ -1,6 +1,5 @@ akka { actor { - serialize-messages = on - warn-about-java-serializer-usage = off + serialize-messages = off # FIXME try to enable again? } } diff --git a/akka-remote-tests/src/test/scala/akka/remote/SerializationChecksSpec.scala b/akka-remote-tests/src/test/scala/akka/remote/SerializationChecksSpec.scala deleted file mode 100644 index d83f85a09a..0000000000 --- a/akka-remote-tests/src/test/scala/akka/remote/SerializationChecksSpec.scala +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.remote - -import akka.testkit.AkkaSpec - -class SerializationChecksSpec extends AkkaSpec { - - "Settings serialize-messages" must { - - "be on for tests" in { - system.settings.SerializeAllMessages should ===(true) - } - - } - -} diff --git a/akka-remote/src/main/java/akka/remote/ArteryControlFormats.java b/akka-remote/src/main/java/akka/remote/ArteryControlFormats.java index 50466ecc81..b8cc1380f0 100644 --- a/akka-remote/src/main/java/akka/remote/ArteryControlFormats.java +++ b/akka-remote/src/main/java/akka/remote/ArteryControlFormats.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2019 Lightbend Inc. + * Copyright (C) 2019 Lightbend Inc. */ // Generated by the protocol buffer compiler. DO NOT EDIT! diff --git a/akka-remote/src/main/java/akka/remote/ContainerFormats.java b/akka-remote/src/main/java/akka/remote/ContainerFormats.java index f9b905fb9f..416118acdb 100644 --- a/akka-remote/src/main/java/akka/remote/ContainerFormats.java +++ b/akka-remote/src/main/java/akka/remote/ContainerFormats.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2019 Lightbend Inc. + * Copyright (C) 2019 Lightbend Inc. */ // Generated by the protocol buffer compiler. DO NOT EDIT! @@ -6184,6 +6184,813 @@ public final class ContainerFormats { // @@protoc_insertion_point(class_scope:Throwable) } + public interface ThrowableNotSerializableOrBuilder + extends akka.protobuf.MessageOrBuilder { + + // required string message = 1; + /** + * required string message = 1; + */ + boolean hasMessage(); + /** + * required string message = 1; + */ + java.lang.String getMessage(); + /** + * required string message = 1; + */ + akka.protobuf.ByteString + getMessageBytes(); + + // required string originalMessage = 2; + /** + * required string originalMessage = 2; + */ + boolean hasOriginalMessage(); + /** + * required string originalMessage = 2; + */ + java.lang.String getOriginalMessage(); + /** + * required string originalMessage = 2; + */ + akka.protobuf.ByteString + getOriginalMessageBytes(); + + // required string originalClassName = 3; + /** + * required string originalClassName = 3; + */ + boolean hasOriginalClassName(); + /** + * required string originalClassName = 3; + */ + java.lang.String getOriginalClassName(); + /** + * required string originalClassName = 3; + */ + akka.protobuf.ByteString + getOriginalClassNameBytes(); + } + /** + * Protobuf type {@code ThrowableNotSerializable} + */ + public static final class ThrowableNotSerializable extends + akka.protobuf.GeneratedMessage + implements ThrowableNotSerializableOrBuilder { + // Use ThrowableNotSerializable.newBuilder() to construct. + private ThrowableNotSerializable(akka.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private ThrowableNotSerializable(boolean noInit) { this.unknownFields = akka.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final ThrowableNotSerializable defaultInstance; + public static ThrowableNotSerializable getDefaultInstance() { + return defaultInstance; + } + + public ThrowableNotSerializable getDefaultInstanceForType() { + return defaultInstance; + } + + private final akka.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final akka.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private ThrowableNotSerializable( + akka.protobuf.CodedInputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws akka.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + akka.protobuf.UnknownFieldSet.Builder unknownFields = + akka.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + bitField0_ |= 0x00000001; + message_ = input.readBytes(); + break; + } + case 18: { + bitField0_ |= 0x00000002; + originalMessage_ = input.readBytes(); + break; + } + case 26: { + bitField0_ |= 0x00000004; + originalClassName_ = input.readBytes(); + break; + } + } + } + } catch (akka.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new akka.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final akka.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.ContainerFormats.internal_static_ThrowableNotSerializable_descriptor; + } + + protected akka.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.ContainerFormats.internal_static_ThrowableNotSerializable_fieldAccessorTable + .ensureFieldAccessorsInitialized( + akka.remote.ContainerFormats.ThrowableNotSerializable.class, akka.remote.ContainerFormats.ThrowableNotSerializable.Builder.class); + } + + public static akka.protobuf.Parser PARSER = + new akka.protobuf.AbstractParser() { + public ThrowableNotSerializable parsePartialFrom( + akka.protobuf.CodedInputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws akka.protobuf.InvalidProtocolBufferException { + return new ThrowableNotSerializable(input, extensionRegistry); + } + }; + + @java.lang.Override + public akka.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + // required string message = 1; + public static final int MESSAGE_FIELD_NUMBER = 1; + private java.lang.Object message_; + /** + * required string message = 1; + */ + public boolean hasMessage() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required string message = 1; + */ + public java.lang.String getMessage() { + java.lang.Object ref = message_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + akka.protobuf.ByteString bs = + (akka.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + message_ = s; + } + return s; + } + } + /** + * required string message = 1; + */ + public akka.protobuf.ByteString + getMessageBytes() { + java.lang.Object ref = message_; + if (ref instanceof java.lang.String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + message_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + + // required string originalMessage = 2; + public static final int ORIGINALMESSAGE_FIELD_NUMBER = 2; + private java.lang.Object originalMessage_; + /** + * required string originalMessage = 2; + */ + public boolean hasOriginalMessage() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * required string originalMessage = 2; + */ + public java.lang.String getOriginalMessage() { + java.lang.Object ref = originalMessage_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + akka.protobuf.ByteString bs = + (akka.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + originalMessage_ = s; + } + return s; + } + } + /** + * required string originalMessage = 2; + */ + public akka.protobuf.ByteString + getOriginalMessageBytes() { + java.lang.Object ref = originalMessage_; + if (ref instanceof java.lang.String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + originalMessage_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + + // required string originalClassName = 3; + public static final int ORIGINALCLASSNAME_FIELD_NUMBER = 3; + private java.lang.Object originalClassName_; + /** + * required string originalClassName = 3; + */ + public boolean hasOriginalClassName() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * required string originalClassName = 3; + */ + public java.lang.String getOriginalClassName() { + java.lang.Object ref = originalClassName_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + akka.protobuf.ByteString bs = + (akka.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + originalClassName_ = s; + } + return s; + } + } + /** + * required string originalClassName = 3; + */ + public akka.protobuf.ByteString + getOriginalClassNameBytes() { + java.lang.Object ref = originalClassName_; + if (ref instanceof java.lang.String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + originalClassName_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + + private void initFields() { + message_ = ""; + originalMessage_ = ""; + originalClassName_ = ""; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + if (!hasMessage()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasOriginalMessage()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasOriginalClassName()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(akka.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBytes(1, getMessageBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(2, getOriginalMessageBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeBytes(3, getOriginalClassNameBytes()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += akka.protobuf.CodedOutputStream + .computeBytesSize(1, getMessageBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += akka.protobuf.CodedOutputStream + .computeBytesSize(2, getOriginalMessageBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += akka.protobuf.CodedOutputStream + .computeBytesSize(3, getOriginalClassNameBytes()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseFrom( + akka.protobuf.ByteString data) + throws akka.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseFrom( + akka.protobuf.ByteString data, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws akka.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseFrom(byte[] data) + throws akka.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseFrom( + byte[] data, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws akka.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseFrom( + java.io.InputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseDelimitedFrom( + java.io.InputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseFrom( + akka.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static akka.remote.ContainerFormats.ThrowableNotSerializable parseFrom( + akka.protobuf.CodedInputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(akka.remote.ContainerFormats.ThrowableNotSerializable prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + akka.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code ThrowableNotSerializable} + */ + public static final class Builder extends + akka.protobuf.GeneratedMessage.Builder + implements akka.remote.ContainerFormats.ThrowableNotSerializableOrBuilder { + public static final akka.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.ContainerFormats.internal_static_ThrowableNotSerializable_descriptor; + } + + protected akka.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.ContainerFormats.internal_static_ThrowableNotSerializable_fieldAccessorTable + .ensureFieldAccessorsInitialized( + akka.remote.ContainerFormats.ThrowableNotSerializable.class, akka.remote.ContainerFormats.ThrowableNotSerializable.Builder.class); + } + + // Construct using akka.remote.ContainerFormats.ThrowableNotSerializable.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + akka.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (akka.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + message_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + originalMessage_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + originalClassName_ = ""; + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public akka.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return akka.remote.ContainerFormats.internal_static_ThrowableNotSerializable_descriptor; + } + + public akka.remote.ContainerFormats.ThrowableNotSerializable getDefaultInstanceForType() { + return akka.remote.ContainerFormats.ThrowableNotSerializable.getDefaultInstance(); + } + + public akka.remote.ContainerFormats.ThrowableNotSerializable build() { + akka.remote.ContainerFormats.ThrowableNotSerializable result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public akka.remote.ContainerFormats.ThrowableNotSerializable buildPartial() { + akka.remote.ContainerFormats.ThrowableNotSerializable result = new akka.remote.ContainerFormats.ThrowableNotSerializable(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.message_ = message_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.originalMessage_ = originalMessage_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.originalClassName_ = originalClassName_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(akka.protobuf.Message other) { + if (other instanceof akka.remote.ContainerFormats.ThrowableNotSerializable) { + return mergeFrom((akka.remote.ContainerFormats.ThrowableNotSerializable)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(akka.remote.ContainerFormats.ThrowableNotSerializable other) { + if (other == akka.remote.ContainerFormats.ThrowableNotSerializable.getDefaultInstance()) return this; + if (other.hasMessage()) { + bitField0_ |= 0x00000001; + message_ = other.message_; + onChanged(); + } + if (other.hasOriginalMessage()) { + bitField0_ |= 0x00000002; + originalMessage_ = other.originalMessage_; + onChanged(); + } + if (other.hasOriginalClassName()) { + bitField0_ |= 0x00000004; + originalClassName_ = other.originalClassName_; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + if (!hasMessage()) { + + return false; + } + if (!hasOriginalMessage()) { + + return false; + } + if (!hasOriginalClassName()) { + + return false; + } + return true; + } + + public Builder mergeFrom( + akka.protobuf.CodedInputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + akka.remote.ContainerFormats.ThrowableNotSerializable parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (akka.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (akka.remote.ContainerFormats.ThrowableNotSerializable) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // required string message = 1; + private java.lang.Object message_ = ""; + /** + * required string message = 1; + */ + public boolean hasMessage() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required string message = 1; + */ + public java.lang.String getMessage() { + java.lang.Object ref = message_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((akka.protobuf.ByteString) ref) + .toStringUtf8(); + message_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * required string message = 1; + */ + public akka.protobuf.ByteString + getMessageBytes() { + java.lang.Object ref = message_; + if (ref instanceof String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + message_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + /** + * required string message = 1; + */ + public Builder setMessage( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + message_ = value; + onChanged(); + return this; + } + /** + * required string message = 1; + */ + public Builder clearMessage() { + bitField0_ = (bitField0_ & ~0x00000001); + message_ = getDefaultInstance().getMessage(); + onChanged(); + return this; + } + /** + * required string message = 1; + */ + public Builder setMessageBytes( + akka.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + message_ = value; + onChanged(); + return this; + } + + // required string originalMessage = 2; + private java.lang.Object originalMessage_ = ""; + /** + * required string originalMessage = 2; + */ + public boolean hasOriginalMessage() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * required string originalMessage = 2; + */ + public java.lang.String getOriginalMessage() { + java.lang.Object ref = originalMessage_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((akka.protobuf.ByteString) ref) + .toStringUtf8(); + originalMessage_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * required string originalMessage = 2; + */ + public akka.protobuf.ByteString + getOriginalMessageBytes() { + java.lang.Object ref = originalMessage_; + if (ref instanceof String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + originalMessage_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + /** + * required string originalMessage = 2; + */ + public Builder setOriginalMessage( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + originalMessage_ = value; + onChanged(); + return this; + } + /** + * required string originalMessage = 2; + */ + public Builder clearOriginalMessage() { + bitField0_ = (bitField0_ & ~0x00000002); + originalMessage_ = getDefaultInstance().getOriginalMessage(); + onChanged(); + return this; + } + /** + * required string originalMessage = 2; + */ + public Builder setOriginalMessageBytes( + akka.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + originalMessage_ = value; + onChanged(); + return this; + } + + // required string originalClassName = 3; + private java.lang.Object originalClassName_ = ""; + /** + * required string originalClassName = 3; + */ + public boolean hasOriginalClassName() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * required string originalClassName = 3; + */ + public java.lang.String getOriginalClassName() { + java.lang.Object ref = originalClassName_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((akka.protobuf.ByteString) ref) + .toStringUtf8(); + originalClassName_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * required string originalClassName = 3; + */ + public akka.protobuf.ByteString + getOriginalClassNameBytes() { + java.lang.Object ref = originalClassName_; + if (ref instanceof String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + originalClassName_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + /** + * required string originalClassName = 3; + */ + public Builder setOriginalClassName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + originalClassName_ = value; + onChanged(); + return this; + } + /** + * required string originalClassName = 3; + */ + public Builder clearOriginalClassName() { + bitField0_ = (bitField0_ & ~0x00000004); + originalClassName_ = getDefaultInstance().getOriginalClassName(); + onChanged(); + return this; + } + /** + * required string originalClassName = 3; + */ + public Builder setOriginalClassNameBytes( + akka.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + originalClassName_ = value; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:ThrowableNotSerializable) + } + + static { + defaultInstance = new ThrowableNotSerializable(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:ThrowableNotSerializable) + } + public interface ActorInitializationExceptionOrBuilder extends akka.protobuf.MessageOrBuilder { @@ -8016,6 +8823,11 @@ public final class ContainerFormats { private static akka.protobuf.GeneratedMessage.FieldAccessorTable internal_static_Throwable_fieldAccessorTable; + private static akka.protobuf.Descriptors.Descriptor + internal_static_ThrowableNotSerializable_descriptor; + private static + akka.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_ThrowableNotSerializable_fieldAccessorTable; private static akka.protobuf.Descriptors.Descriptor internal_static_ActorInitializationException_descriptor; private static @@ -8051,13 +8863,16 @@ public final class ContainerFormats { "uid\030\001 \002(\004\"p\n\tThrowable\022\021\n\tclassName\030\001 \002(" + "\t\022\017\n\007message\030\002 \001(\t\022\027\n\005cause\030\003 \001(\0132\010.Payl" + "oad\022&\n\nstackTrace\030\004 \003(\0132\022.StackTraceElem" + - "ent\"b\n\034ActorInitializationException\022\030\n\005a" + - "ctor\030\001 \001(\0132\t.ActorRef\022\017\n\007message\030\002 \002(\t\022\027" + - "\n\005cause\030\003 \002(\0132\010.Payload\"`\n\021StackTraceEle" + - "ment\022\021\n\tclassName\030\001 \002(\t\022\022\n\nmethodName\030\002 ", - "\002(\t\022\020\n\010fileName\030\003 \002(\t\022\022\n\nlineNumber\030\004 \002(" + - "\005*<\n\013PatternType\022\n\n\006PARENT\020\000\022\016\n\nCHILD_NA" + - "ME\020\001\022\021\n\rCHILD_PATTERN\020\002B\017\n\013akka.remoteH\001" + "ent\"_\n\030ThrowableNotSerializable\022\017\n\007messa" + + "ge\030\001 \002(\t\022\027\n\017originalMessage\030\002 \002(\t\022\031\n\021ori" + + "ginalClassName\030\003 \002(\t\"b\n\034ActorInitializat" + + "ionException\022\030\n\005actor\030\001 \001(\0132\t.ActorRef\022\017", + "\n\007message\030\002 \002(\t\022\027\n\005cause\030\003 \002(\0132\010.Payload" + + "\"`\n\021StackTraceElement\022\021\n\tclassName\030\001 \002(\t" + + "\022\022\n\nmethodName\030\002 \002(\t\022\020\n\010fileName\030\003 \002(\t\022\022" + + "\n\nlineNumber\030\004 \002(\005*<\n\013PatternType\022\n\n\006PAR" + + "ENT\020\000\022\016\n\nCHILD_NAME\020\001\022\021\n\rCHILD_PATTERN\020\002" + + "B\017\n\013akka.remoteH\001" }; akka.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new akka.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -8118,14 +8933,20 @@ public final class ContainerFormats { akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_Throwable_descriptor, new java.lang.String[] { "ClassName", "Message", "Cause", "StackTrace", }); - internal_static_ActorInitializationException_descriptor = + internal_static_ThrowableNotSerializable_descriptor = getDescriptor().getMessageTypes().get(9); + internal_static_ThrowableNotSerializable_fieldAccessorTable = new + akka.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_ThrowableNotSerializable_descriptor, + new java.lang.String[] { "Message", "OriginalMessage", "OriginalClassName", }); + internal_static_ActorInitializationException_descriptor = + getDescriptor().getMessageTypes().get(10); internal_static_ActorInitializationException_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_ActorInitializationException_descriptor, new java.lang.String[] { "Actor", "Message", "Cause", }); internal_static_StackTraceElement_descriptor = - getDescriptor().getMessageTypes().get(10); + getDescriptor().getMessageTypes().get(11); internal_static_StackTraceElement_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_StackTraceElement_descriptor, diff --git a/akka-remote/src/main/java/akka/remote/SystemMessageFormats.java b/akka-remote/src/main/java/akka/remote/SystemMessageFormats.java index fb57b10a06..4c08cb716e 100644 --- a/akka-remote/src/main/java/akka/remote/SystemMessageFormats.java +++ b/akka-remote/src/main/java/akka/remote/SystemMessageFormats.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2019 Lightbend Inc. + * Copyright (C) 2019 Lightbend Inc. */ // Generated by the protocol buffer compiler. DO NOT EDIT! diff --git a/akka-remote/src/main/java/akka/remote/WireFormats.java b/akka-remote/src/main/java/akka/remote/WireFormats.java index 474aea7156..c9da5a3827 100644 --- a/akka-remote/src/main/java/akka/remote/WireFormats.java +++ b/akka-remote/src/main/java/akka/remote/WireFormats.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2019 Lightbend Inc. + * Copyright (C) 2019 Lightbend Inc. */ // Generated by the protocol buffer compiler. DO NOT EDIT! @@ -7985,910 +7985,6 @@ public final class WireFormats { // @@protoc_insertion_point(class_scope:DeployData) } - public interface AddressDataOrBuilder - extends akka.protobuf.MessageOrBuilder { - - // required string system = 1; - /** - * required string system = 1; - */ - boolean hasSystem(); - /** - * required string system = 1; - */ - java.lang.String getSystem(); - /** - * required string system = 1; - */ - akka.protobuf.ByteString - getSystemBytes(); - - // required string hostname = 2; - /** - * required string hostname = 2; - */ - boolean hasHostname(); - /** - * required string hostname = 2; - */ - java.lang.String getHostname(); - /** - * required string hostname = 2; - */ - akka.protobuf.ByteString - getHostnameBytes(); - - // required uint32 port = 3; - /** - * required uint32 port = 3; - */ - boolean hasPort(); - /** - * required uint32 port = 3; - */ - int getPort(); - - // optional string protocol = 4; - /** - * optional string protocol = 4; - */ - boolean hasProtocol(); - /** - * optional string protocol = 4; - */ - java.lang.String getProtocol(); - /** - * optional string protocol = 4; - */ - akka.protobuf.ByteString - getProtocolBytes(); - } - /** - * Protobuf type {@code AddressData} - * - *
-   **
-   * Defines a remote address, for classic remoting.
-   *
-   * Note that while the same message definition exists in cluster, as well as an updated one exists for Artery.
-   * This encoding will ONLY be used when an `akka.actor.Address` is attempted to be serialized *directly*.
-   * 
- */ - public static final class AddressData extends - akka.protobuf.GeneratedMessage - implements AddressDataOrBuilder { - // Use AddressData.newBuilder() to construct. - private AddressData(akka.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private AddressData(boolean noInit) { this.unknownFields = akka.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final AddressData defaultInstance; - public static AddressData getDefaultInstance() { - return defaultInstance; - } - - public AddressData getDefaultInstanceForType() { - return defaultInstance; - } - - private final akka.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final akka.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private AddressData( - akka.protobuf.CodedInputStream input, - akka.protobuf.ExtensionRegistryLite extensionRegistry) - throws akka.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - akka.protobuf.UnknownFieldSet.Builder unknownFields = - akka.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - system_ = input.readBytes(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - hostname_ = input.readBytes(); - break; - } - case 24: { - bitField0_ |= 0x00000004; - port_ = input.readUInt32(); - break; - } - case 34: { - bitField0_ |= 0x00000008; - protocol_ = input.readBytes(); - break; - } - } - } - } catch (akka.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new akka.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final akka.protobuf.Descriptors.Descriptor - getDescriptor() { - return akka.remote.WireFormats.internal_static_AddressData_descriptor; - } - - protected akka.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return akka.remote.WireFormats.internal_static_AddressData_fieldAccessorTable - .ensureFieldAccessorsInitialized( - akka.remote.WireFormats.AddressData.class, akka.remote.WireFormats.AddressData.Builder.class); - } - - public static akka.protobuf.Parser PARSER = - new akka.protobuf.AbstractParser() { - public AddressData parsePartialFrom( - akka.protobuf.CodedInputStream input, - akka.protobuf.ExtensionRegistryLite extensionRegistry) - throws akka.protobuf.InvalidProtocolBufferException { - return new AddressData(input, extensionRegistry); - } - }; - - @java.lang.Override - public akka.protobuf.Parser getParserForType() { - return PARSER; - } - - private int bitField0_; - // required string system = 1; - public static final int SYSTEM_FIELD_NUMBER = 1; - private java.lang.Object system_; - /** - * required string system = 1; - */ - public boolean hasSystem() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * required string system = 1; - */ - public java.lang.String getSystem() { - java.lang.Object ref = system_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - akka.protobuf.ByteString bs = - (akka.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - system_ = s; - } - return s; - } - } - /** - * required string system = 1; - */ - public akka.protobuf.ByteString - getSystemBytes() { - java.lang.Object ref = system_; - if (ref instanceof java.lang.String) { - akka.protobuf.ByteString b = - akka.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - system_ = b; - return b; - } else { - return (akka.protobuf.ByteString) ref; - } - } - - // required string hostname = 2; - public static final int HOSTNAME_FIELD_NUMBER = 2; - private java.lang.Object hostname_; - /** - * required string hostname = 2; - */ - public boolean hasHostname() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * required string hostname = 2; - */ - public java.lang.String getHostname() { - java.lang.Object ref = hostname_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - akka.protobuf.ByteString bs = - (akka.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - hostname_ = s; - } - return s; - } - } - /** - * required string hostname = 2; - */ - public akka.protobuf.ByteString - getHostnameBytes() { - java.lang.Object ref = hostname_; - if (ref instanceof java.lang.String) { - akka.protobuf.ByteString b = - akka.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - hostname_ = b; - return b; - } else { - return (akka.protobuf.ByteString) ref; - } - } - - // required uint32 port = 3; - public static final int PORT_FIELD_NUMBER = 3; - private int port_; - /** - * required uint32 port = 3; - */ - public boolean hasPort() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * required uint32 port = 3; - */ - public int getPort() { - return port_; - } - - // optional string protocol = 4; - public static final int PROTOCOL_FIELD_NUMBER = 4; - private java.lang.Object protocol_; - /** - * optional string protocol = 4; - */ - public boolean hasProtocol() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - /** - * optional string protocol = 4; - */ - public java.lang.String getProtocol() { - java.lang.Object ref = protocol_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - akka.protobuf.ByteString bs = - (akka.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - protocol_ = s; - } - return s; - } - } - /** - * optional string protocol = 4; - */ - public akka.protobuf.ByteString - getProtocolBytes() { - java.lang.Object ref = protocol_; - if (ref instanceof java.lang.String) { - akka.protobuf.ByteString b = - akka.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protocol_ = b; - return b; - } else { - return (akka.protobuf.ByteString) ref; - } - } - - private void initFields() { - system_ = ""; - hostname_ = ""; - port_ = 0; - protocol_ = ""; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - if (!hasSystem()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasHostname()) { - memoizedIsInitialized = 0; - return false; - } - if (!hasPort()) { - memoizedIsInitialized = 0; - return false; - } - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(akka.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getSystemBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, getHostnameBytes()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeUInt32(3, port_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - output.writeBytes(4, getProtocolBytes()); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += akka.protobuf.CodedOutputStream - .computeBytesSize(1, getSystemBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += akka.protobuf.CodedOutputStream - .computeBytesSize(2, getHostnameBytes()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += akka.protobuf.CodedOutputStream - .computeUInt32Size(3, port_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - size += akka.protobuf.CodedOutputStream - .computeBytesSize(4, getProtocolBytes()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static akka.remote.WireFormats.AddressData parseFrom( - akka.protobuf.ByteString data) - throws akka.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static akka.remote.WireFormats.AddressData parseFrom( - akka.protobuf.ByteString data, - akka.protobuf.ExtensionRegistryLite extensionRegistry) - throws akka.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static akka.remote.WireFormats.AddressData parseFrom(byte[] data) - throws akka.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static akka.remote.WireFormats.AddressData parseFrom( - byte[] data, - akka.protobuf.ExtensionRegistryLite extensionRegistry) - throws akka.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static akka.remote.WireFormats.AddressData parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static akka.remote.WireFormats.AddressData parseFrom( - java.io.InputStream input, - akka.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static akka.remote.WireFormats.AddressData parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static akka.remote.WireFormats.AddressData parseDelimitedFrom( - java.io.InputStream input, - akka.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static akka.remote.WireFormats.AddressData parseFrom( - akka.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static akka.remote.WireFormats.AddressData parseFrom( - akka.protobuf.CodedInputStream input, - akka.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(akka.remote.WireFormats.AddressData prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - akka.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code AddressData} - * - *
-     **
-     * Defines a remote address, for classic remoting.
-     *
-     * Note that while the same message definition exists in cluster, as well as an updated one exists for Artery.
-     * This encoding will ONLY be used when an `akka.actor.Address` is attempted to be serialized *directly*.
-     * 
- */ - public static final class Builder extends - akka.protobuf.GeneratedMessage.Builder - implements akka.remote.WireFormats.AddressDataOrBuilder { - public static final akka.protobuf.Descriptors.Descriptor - getDescriptor() { - return akka.remote.WireFormats.internal_static_AddressData_descriptor; - } - - protected akka.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return akka.remote.WireFormats.internal_static_AddressData_fieldAccessorTable - .ensureFieldAccessorsInitialized( - akka.remote.WireFormats.AddressData.class, akka.remote.WireFormats.AddressData.Builder.class); - } - - // Construct using akka.remote.WireFormats.AddressData.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - akka.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (akka.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - system_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - hostname_ = ""; - bitField0_ = (bitField0_ & ~0x00000002); - port_ = 0; - bitField0_ = (bitField0_ & ~0x00000004); - protocol_ = ""; - bitField0_ = (bitField0_ & ~0x00000008); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public akka.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return akka.remote.WireFormats.internal_static_AddressData_descriptor; - } - - public akka.remote.WireFormats.AddressData getDefaultInstanceForType() { - return akka.remote.WireFormats.AddressData.getDefaultInstance(); - } - - public akka.remote.WireFormats.AddressData build() { - akka.remote.WireFormats.AddressData result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public akka.remote.WireFormats.AddressData buildPartial() { - akka.remote.WireFormats.AddressData result = new akka.remote.WireFormats.AddressData(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.system_ = system_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.hostname_ = hostname_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.port_ = port_; - if (((from_bitField0_ & 0x00000008) == 0x00000008)) { - to_bitField0_ |= 0x00000008; - } - result.protocol_ = protocol_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(akka.protobuf.Message other) { - if (other instanceof akka.remote.WireFormats.AddressData) { - return mergeFrom((akka.remote.WireFormats.AddressData)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(akka.remote.WireFormats.AddressData other) { - if (other == akka.remote.WireFormats.AddressData.getDefaultInstance()) return this; - if (other.hasSystem()) { - bitField0_ |= 0x00000001; - system_ = other.system_; - onChanged(); - } - if (other.hasHostname()) { - bitField0_ |= 0x00000002; - hostname_ = other.hostname_; - onChanged(); - } - if (other.hasPort()) { - setPort(other.getPort()); - } - if (other.hasProtocol()) { - bitField0_ |= 0x00000008; - protocol_ = other.protocol_; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - if (!hasSystem()) { - - return false; - } - if (!hasHostname()) { - - return false; - } - if (!hasPort()) { - - return false; - } - return true; - } - - public Builder mergeFrom( - akka.protobuf.CodedInputStream input, - akka.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - akka.remote.WireFormats.AddressData parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (akka.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (akka.remote.WireFormats.AddressData) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // required string system = 1; - private java.lang.Object system_ = ""; - /** - * required string system = 1; - */ - public boolean hasSystem() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * required string system = 1; - */ - public java.lang.String getSystem() { - java.lang.Object ref = system_; - if (!(ref instanceof java.lang.String)) { - java.lang.String s = ((akka.protobuf.ByteString) ref) - .toStringUtf8(); - system_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * required string system = 1; - */ - public akka.protobuf.ByteString - getSystemBytes() { - java.lang.Object ref = system_; - if (ref instanceof String) { - akka.protobuf.ByteString b = - akka.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - system_ = b; - return b; - } else { - return (akka.protobuf.ByteString) ref; - } - } - /** - * required string system = 1; - */ - public Builder setSystem( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - system_ = value; - onChanged(); - return this; - } - /** - * required string system = 1; - */ - public Builder clearSystem() { - bitField0_ = (bitField0_ & ~0x00000001); - system_ = getDefaultInstance().getSystem(); - onChanged(); - return this; - } - /** - * required string system = 1; - */ - public Builder setSystemBytes( - akka.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - system_ = value; - onChanged(); - return this; - } - - // required string hostname = 2; - private java.lang.Object hostname_ = ""; - /** - * required string hostname = 2; - */ - public boolean hasHostname() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * required string hostname = 2; - */ - public java.lang.String getHostname() { - java.lang.Object ref = hostname_; - if (!(ref instanceof java.lang.String)) { - java.lang.String s = ((akka.protobuf.ByteString) ref) - .toStringUtf8(); - hostname_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * required string hostname = 2; - */ - public akka.protobuf.ByteString - getHostnameBytes() { - java.lang.Object ref = hostname_; - if (ref instanceof String) { - akka.protobuf.ByteString b = - akka.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - hostname_ = b; - return b; - } else { - return (akka.protobuf.ByteString) ref; - } - } - /** - * required string hostname = 2; - */ - public Builder setHostname( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - hostname_ = value; - onChanged(); - return this; - } - /** - * required string hostname = 2; - */ - public Builder clearHostname() { - bitField0_ = (bitField0_ & ~0x00000002); - hostname_ = getDefaultInstance().getHostname(); - onChanged(); - return this; - } - /** - * required string hostname = 2; - */ - public Builder setHostnameBytes( - akka.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - hostname_ = value; - onChanged(); - return this; - } - - // required uint32 port = 3; - private int port_ ; - /** - * required uint32 port = 3; - */ - public boolean hasPort() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * required uint32 port = 3; - */ - public int getPort() { - return port_; - } - /** - * required uint32 port = 3; - */ - public Builder setPort(int value) { - bitField0_ |= 0x00000004; - port_ = value; - onChanged(); - return this; - } - /** - * required uint32 port = 3; - */ - public Builder clearPort() { - bitField0_ = (bitField0_ & ~0x00000004); - port_ = 0; - onChanged(); - return this; - } - - // optional string protocol = 4; - private java.lang.Object protocol_ = ""; - /** - * optional string protocol = 4; - */ - public boolean hasProtocol() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - /** - * optional string protocol = 4; - */ - public java.lang.String getProtocol() { - java.lang.Object ref = protocol_; - if (!(ref instanceof java.lang.String)) { - java.lang.String s = ((akka.protobuf.ByteString) ref) - .toStringUtf8(); - protocol_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string protocol = 4; - */ - public akka.protobuf.ByteString - getProtocolBytes() { - java.lang.Object ref = protocol_; - if (ref instanceof String) { - akka.protobuf.ByteString b = - akka.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protocol_ = b; - return b; - } else { - return (akka.protobuf.ByteString) ref; - } - } - /** - * optional string protocol = 4; - */ - public Builder setProtocol( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000008; - protocol_ = value; - onChanged(); - return this; - } - /** - * optional string protocol = 4; - */ - public Builder clearProtocol() { - bitField0_ = (bitField0_ & ~0x00000008); - protocol_ = getDefaultInstance().getProtocol(); - onChanged(); - return this; - } - /** - * optional string protocol = 4; - */ - public Builder setProtocolBytes( - akka.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000008; - protocol_ = value; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:AddressData) - } - - static { - defaultInstance = new AddressData(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:AddressData) - } - public interface AkkaProtocolMessageOrBuilder extends akka.protobuf.MessageOrBuilder { @@ -16060,6 +15156,904 @@ public final class WireFormats { // @@protoc_insertion_point(class_scope:TailChoppingPool) } + public interface AddressDataOrBuilder + extends akka.protobuf.MessageOrBuilder { + + // required string system = 1; + /** + * required string system = 1; + */ + boolean hasSystem(); + /** + * required string system = 1; + */ + java.lang.String getSystem(); + /** + * required string system = 1; + */ + akka.protobuf.ByteString + getSystemBytes(); + + // required string hostname = 2; + /** + * required string hostname = 2; + */ + boolean hasHostname(); + /** + * required string hostname = 2; + */ + java.lang.String getHostname(); + /** + * required string hostname = 2; + */ + akka.protobuf.ByteString + getHostnameBytes(); + + // required uint32 port = 3; + /** + * required uint32 port = 3; + */ + boolean hasPort(); + /** + * required uint32 port = 3; + */ + int getPort(); + + // optional string protocol = 4; + /** + * optional string protocol = 4; + */ + boolean hasProtocol(); + /** + * optional string protocol = 4; + */ + java.lang.String getProtocol(); + /** + * optional string protocol = 4; + */ + akka.protobuf.ByteString + getProtocolBytes(); + } + /** + * Protobuf type {@code AddressData} + * + *
+   **
+   * Defines a remote address.
+   * 
+ */ + public static final class AddressData extends + akka.protobuf.GeneratedMessage + implements AddressDataOrBuilder { + // Use AddressData.newBuilder() to construct. + private AddressData(akka.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private AddressData(boolean noInit) { this.unknownFields = akka.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final AddressData defaultInstance; + public static AddressData getDefaultInstance() { + return defaultInstance; + } + + public AddressData getDefaultInstanceForType() { + return defaultInstance; + } + + private final akka.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final akka.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private AddressData( + akka.protobuf.CodedInputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws akka.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + akka.protobuf.UnknownFieldSet.Builder unknownFields = + akka.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + bitField0_ |= 0x00000001; + system_ = input.readBytes(); + break; + } + case 18: { + bitField0_ |= 0x00000002; + hostname_ = input.readBytes(); + break; + } + case 24: { + bitField0_ |= 0x00000004; + port_ = input.readUInt32(); + break; + } + case 34: { + bitField0_ |= 0x00000008; + protocol_ = input.readBytes(); + break; + } + } + } + } catch (akka.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new akka.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final akka.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.WireFormats.internal_static_AddressData_descriptor; + } + + protected akka.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.WireFormats.internal_static_AddressData_fieldAccessorTable + .ensureFieldAccessorsInitialized( + akka.remote.WireFormats.AddressData.class, akka.remote.WireFormats.AddressData.Builder.class); + } + + public static akka.protobuf.Parser PARSER = + new akka.protobuf.AbstractParser() { + public AddressData parsePartialFrom( + akka.protobuf.CodedInputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws akka.protobuf.InvalidProtocolBufferException { + return new AddressData(input, extensionRegistry); + } + }; + + @java.lang.Override + public akka.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + // required string system = 1; + public static final int SYSTEM_FIELD_NUMBER = 1; + private java.lang.Object system_; + /** + * required string system = 1; + */ + public boolean hasSystem() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required string system = 1; + */ + public java.lang.String getSystem() { + java.lang.Object ref = system_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + akka.protobuf.ByteString bs = + (akka.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + system_ = s; + } + return s; + } + } + /** + * required string system = 1; + */ + public akka.protobuf.ByteString + getSystemBytes() { + java.lang.Object ref = system_; + if (ref instanceof java.lang.String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + system_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + + // required string hostname = 2; + public static final int HOSTNAME_FIELD_NUMBER = 2; + private java.lang.Object hostname_; + /** + * required string hostname = 2; + */ + public boolean hasHostname() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * required string hostname = 2; + */ + public java.lang.String getHostname() { + java.lang.Object ref = hostname_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + akka.protobuf.ByteString bs = + (akka.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + hostname_ = s; + } + return s; + } + } + /** + * required string hostname = 2; + */ + public akka.protobuf.ByteString + getHostnameBytes() { + java.lang.Object ref = hostname_; + if (ref instanceof java.lang.String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + hostname_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + + // required uint32 port = 3; + public static final int PORT_FIELD_NUMBER = 3; + private int port_; + /** + * required uint32 port = 3; + */ + public boolean hasPort() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * required uint32 port = 3; + */ + public int getPort() { + return port_; + } + + // optional string protocol = 4; + public static final int PROTOCOL_FIELD_NUMBER = 4; + private java.lang.Object protocol_; + /** + * optional string protocol = 4; + */ + public boolean hasProtocol() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + /** + * optional string protocol = 4; + */ + public java.lang.String getProtocol() { + java.lang.Object ref = protocol_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + akka.protobuf.ByteString bs = + (akka.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + protocol_ = s; + } + return s; + } + } + /** + * optional string protocol = 4; + */ + public akka.protobuf.ByteString + getProtocolBytes() { + java.lang.Object ref = protocol_; + if (ref instanceof java.lang.String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + protocol_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + + private void initFields() { + system_ = ""; + hostname_ = ""; + port_ = 0; + protocol_ = ""; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + if (!hasSystem()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasHostname()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasPort()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(akka.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBytes(1, getSystemBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(2, getHostnameBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeUInt32(3, port_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + output.writeBytes(4, getProtocolBytes()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += akka.protobuf.CodedOutputStream + .computeBytesSize(1, getSystemBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += akka.protobuf.CodedOutputStream + .computeBytesSize(2, getHostnameBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += akka.protobuf.CodedOutputStream + .computeUInt32Size(3, port_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + size += akka.protobuf.CodedOutputStream + .computeBytesSize(4, getProtocolBytes()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static akka.remote.WireFormats.AddressData parseFrom( + akka.protobuf.ByteString data) + throws akka.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static akka.remote.WireFormats.AddressData parseFrom( + akka.protobuf.ByteString data, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws akka.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static akka.remote.WireFormats.AddressData parseFrom(byte[] data) + throws akka.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static akka.remote.WireFormats.AddressData parseFrom( + byte[] data, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws akka.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static akka.remote.WireFormats.AddressData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static akka.remote.WireFormats.AddressData parseFrom( + java.io.InputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static akka.remote.WireFormats.AddressData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static akka.remote.WireFormats.AddressData parseDelimitedFrom( + java.io.InputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static akka.remote.WireFormats.AddressData parseFrom( + akka.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static akka.remote.WireFormats.AddressData parseFrom( + akka.protobuf.CodedInputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(akka.remote.WireFormats.AddressData prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + akka.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code AddressData} + * + *
+     **
+     * Defines a remote address.
+     * 
+ */ + public static final class Builder extends + akka.protobuf.GeneratedMessage.Builder + implements akka.remote.WireFormats.AddressDataOrBuilder { + public static final akka.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.WireFormats.internal_static_AddressData_descriptor; + } + + protected akka.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.WireFormats.internal_static_AddressData_fieldAccessorTable + .ensureFieldAccessorsInitialized( + akka.remote.WireFormats.AddressData.class, akka.remote.WireFormats.AddressData.Builder.class); + } + + // Construct using akka.remote.WireFormats.AddressData.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + akka.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (akka.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + system_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + hostname_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + port_ = 0; + bitField0_ = (bitField0_ & ~0x00000004); + protocol_ = ""; + bitField0_ = (bitField0_ & ~0x00000008); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public akka.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return akka.remote.WireFormats.internal_static_AddressData_descriptor; + } + + public akka.remote.WireFormats.AddressData getDefaultInstanceForType() { + return akka.remote.WireFormats.AddressData.getDefaultInstance(); + } + + public akka.remote.WireFormats.AddressData build() { + akka.remote.WireFormats.AddressData result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public akka.remote.WireFormats.AddressData buildPartial() { + akka.remote.WireFormats.AddressData result = new akka.remote.WireFormats.AddressData(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.system_ = system_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.hostname_ = hostname_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.port_ = port_; + if (((from_bitField0_ & 0x00000008) == 0x00000008)) { + to_bitField0_ |= 0x00000008; + } + result.protocol_ = protocol_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(akka.protobuf.Message other) { + if (other instanceof akka.remote.WireFormats.AddressData) { + return mergeFrom((akka.remote.WireFormats.AddressData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(akka.remote.WireFormats.AddressData other) { + if (other == akka.remote.WireFormats.AddressData.getDefaultInstance()) return this; + if (other.hasSystem()) { + bitField0_ |= 0x00000001; + system_ = other.system_; + onChanged(); + } + if (other.hasHostname()) { + bitField0_ |= 0x00000002; + hostname_ = other.hostname_; + onChanged(); + } + if (other.hasPort()) { + setPort(other.getPort()); + } + if (other.hasProtocol()) { + bitField0_ |= 0x00000008; + protocol_ = other.protocol_; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + if (!hasSystem()) { + + return false; + } + if (!hasHostname()) { + + return false; + } + if (!hasPort()) { + + return false; + } + return true; + } + + public Builder mergeFrom( + akka.protobuf.CodedInputStream input, + akka.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + akka.remote.WireFormats.AddressData parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (akka.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (akka.remote.WireFormats.AddressData) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // required string system = 1; + private java.lang.Object system_ = ""; + /** + * required string system = 1; + */ + public boolean hasSystem() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required string system = 1; + */ + public java.lang.String getSystem() { + java.lang.Object ref = system_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((akka.protobuf.ByteString) ref) + .toStringUtf8(); + system_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * required string system = 1; + */ + public akka.protobuf.ByteString + getSystemBytes() { + java.lang.Object ref = system_; + if (ref instanceof String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + system_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + /** + * required string system = 1; + */ + public Builder setSystem( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + system_ = value; + onChanged(); + return this; + } + /** + * required string system = 1; + */ + public Builder clearSystem() { + bitField0_ = (bitField0_ & ~0x00000001); + system_ = getDefaultInstance().getSystem(); + onChanged(); + return this; + } + /** + * required string system = 1; + */ + public Builder setSystemBytes( + akka.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + system_ = value; + onChanged(); + return this; + } + + // required string hostname = 2; + private java.lang.Object hostname_ = ""; + /** + * required string hostname = 2; + */ + public boolean hasHostname() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * required string hostname = 2; + */ + public java.lang.String getHostname() { + java.lang.Object ref = hostname_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((akka.protobuf.ByteString) ref) + .toStringUtf8(); + hostname_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * required string hostname = 2; + */ + public akka.protobuf.ByteString + getHostnameBytes() { + java.lang.Object ref = hostname_; + if (ref instanceof String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + hostname_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + /** + * required string hostname = 2; + */ + public Builder setHostname( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + hostname_ = value; + onChanged(); + return this; + } + /** + * required string hostname = 2; + */ + public Builder clearHostname() { + bitField0_ = (bitField0_ & ~0x00000002); + hostname_ = getDefaultInstance().getHostname(); + onChanged(); + return this; + } + /** + * required string hostname = 2; + */ + public Builder setHostnameBytes( + akka.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + hostname_ = value; + onChanged(); + return this; + } + + // required uint32 port = 3; + private int port_ ; + /** + * required uint32 port = 3; + */ + public boolean hasPort() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * required uint32 port = 3; + */ + public int getPort() { + return port_; + } + /** + * required uint32 port = 3; + */ + public Builder setPort(int value) { + bitField0_ |= 0x00000004; + port_ = value; + onChanged(); + return this; + } + /** + * required uint32 port = 3; + */ + public Builder clearPort() { + bitField0_ = (bitField0_ & ~0x00000004); + port_ = 0; + onChanged(); + return this; + } + + // optional string protocol = 4; + private java.lang.Object protocol_ = ""; + /** + * optional string protocol = 4; + */ + public boolean hasProtocol() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + /** + * optional string protocol = 4; + */ + public java.lang.String getProtocol() { + java.lang.Object ref = protocol_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((akka.protobuf.ByteString) ref) + .toStringUtf8(); + protocol_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string protocol = 4; + */ + public akka.protobuf.ByteString + getProtocolBytes() { + java.lang.Object ref = protocol_; + if (ref instanceof String) { + akka.protobuf.ByteString b = + akka.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + protocol_ = b; + return b; + } else { + return (akka.protobuf.ByteString) ref; + } + } + /** + * optional string protocol = 4; + */ + public Builder setProtocol( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + protocol_ = value; + onChanged(); + return this; + } + /** + * optional string protocol = 4; + */ + public Builder clearProtocol() { + bitField0_ = (bitField0_ & ~0x00000008); + protocol_ = getDefaultInstance().getProtocol(); + onChanged(); + return this; + } + /** + * optional string protocol = 4; + */ + public Builder setProtocolBytes( + akka.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + protocol_ = value; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:AddressData) + } + + static { + defaultInstance = new AddressData(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:AddressData) + } + public interface RemoteRouterConfigOrBuilder extends akka.protobuf.MessageOrBuilder { @@ -16997,11 +16991,6 @@ public final class WireFormats { private static akka.protobuf.GeneratedMessage.FieldAccessorTable internal_static_DeployData_fieldAccessorTable; - private static akka.protobuf.Descriptors.Descriptor - internal_static_AddressData_descriptor; - private static - akka.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_AddressData_fieldAccessorTable; private static akka.protobuf.Descriptors.Descriptor internal_static_AkkaProtocolMessage_descriptor; private static @@ -17052,6 +17041,11 @@ public final class WireFormats { private static akka.protobuf.GeneratedMessage.FieldAccessorTable internal_static_TailChoppingPool_fieldAccessorTable; + private static akka.protobuf.Descriptors.Descriptor + internal_static_AddressData_descriptor; + private static + akka.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_AddressData_fieldAccessorTable; private static akka.protobuf.Descriptors.Descriptor internal_static_RemoteRouterConfig_descriptor; private static @@ -17090,33 +17084,33 @@ public final class WireFormats { "(\005\022\025\n\rscopeManifest\030\007 \001(\t\022\032\n\022configSeria" + "lizerId\030\010 \001(\005\022\026\n\016configManifest\030\t \001(\t\022 \n" + "\030routerConfigSerializerId\030\n \001(\005\022\034\n\024route" + - "rConfigManifest\030\013 \001(\t\"O\n\013AddressData\022\016\n\006" + - "system\030\001 \002(\t\022\020\n\010hostname\030\002 \002(\t\022\014\n\004port\030\003" + - " \002(\r\022\020\n\010protocol\030\004 \001(\t\"P\n\023AkkaProtocolMe" + - "ssage\022\017\n\007payload\030\001 \001(\014\022(\n\013instruction\030\002 " + - "\001(\0132\023.AkkaControlMessage\"b\n\022AkkaControlM" + - "essage\022!\n\013commandType\030\001 \002(\0162\014.CommandTyp", - "e\022)\n\rhandshakeInfo\030\002 \001(\0132\022.AkkaHandshake" + - "Info\"N\n\021AkkaHandshakeInfo\022\034\n\006origin\030\001 \002(" + - "\0132\014.AddressData\022\013\n\003uid\030\002 \002(\006\022\016\n\006cookie\030\003" + - " \001(\t\"8\n\016FiniteDuration\022\r\n\005value\030\001 \002(\003\022\027\n" + - "\004unit\030\002 \002(\0162\t.TimeUnit\")\n\013RemoteScope\022\032\n" + - "\004node\030\001 \002(\0132\014.AddressData\"\261\001\n\016DefaultRes" + - "izer\022\022\n\nlowerBound\030\001 \002(\r\022\022\n\nupperBound\030\002" + - " \002(\r\022\031\n\021pressureThreshold\030\003 \002(\r\022\022\n\nrampu" + - "pRate\030\004 \002(\001\022\030\n\020backoffThreshold\030\005 \002(\001\022\023\n" + - "\013backoffRate\030\006 \002(\001\022\031\n\021messagesPerResize\030", - "\007 \002(\r\"A\n\nFromConfig\022\031\n\007resizer\030\001 \001(\0132\010.P" + - "ayload\022\030\n\020routerDispatcher\030\002 \001(\t\"{\n\022Gene" + - "ricRoutingPool\022\025\n\rnrOfInstances\030\001 \002(\r\022\030\n" + - "\020routerDispatcher\030\002 \001(\t\022\031\n\021usePoolDispat" + - "cher\030\003 \002(\010\022\031\n\007resizer\030\004 \001(\0132\010.Payload\"Z\n" + - "\021ScatterGatherPool\022$\n\007generic\030\001 \002(\0132\023.Ge" + - "nericRoutingPool\022\037\n\006within\030\002 \002(\0132\017.Finit" + - "eDuration\"|\n\020TailChoppingPool\022$\n\007generic" + - "\030\001 \002(\0132\023.GenericRoutingPool\022\037\n\006within\030\002 " + - "\002(\0132\017.FiniteDuration\022!\n\010interval\030\003 \002(\0132\017", - ".FiniteDuration\"J\n\022RemoteRouterConfig\022\027\n" + + "rConfigManifest\030\013 \001(\t\"P\n\023AkkaProtocolMes" + + "sage\022\017\n\007payload\030\001 \001(\014\022(\n\013instruction\030\002 \001" + + "(\0132\023.AkkaControlMessage\"b\n\022AkkaControlMe" + + "ssage\022!\n\013commandType\030\001 \002(\0162\014.CommandType" + + "\022)\n\rhandshakeInfo\030\002 \001(\0132\022.AkkaHandshakeI" + + "nfo\"N\n\021AkkaHandshakeInfo\022\034\n\006origin\030\001 \002(\013", + "2\014.AddressData\022\013\n\003uid\030\002 \002(\006\022\016\n\006cookie\030\003 " + + "\001(\t\"8\n\016FiniteDuration\022\r\n\005value\030\001 \002(\003\022\027\n\004" + + "unit\030\002 \002(\0162\t.TimeUnit\")\n\013RemoteScope\022\032\n\004" + + "node\030\001 \002(\0132\014.AddressData\"\261\001\n\016DefaultResi" + + "zer\022\022\n\nlowerBound\030\001 \002(\r\022\022\n\nupperBound\030\002 " + + "\002(\r\022\031\n\021pressureThreshold\030\003 \002(\r\022\022\n\nrampup" + + "Rate\030\004 \002(\001\022\030\n\020backoffThreshold\030\005 \002(\001\022\023\n\013" + + "backoffRate\030\006 \002(\001\022\031\n\021messagesPerResize\030\007" + + " \002(\r\"A\n\nFromConfig\022\031\n\007resizer\030\001 \001(\0132\010.Pa" + + "yload\022\030\n\020routerDispatcher\030\002 \001(\t\"{\n\022Gener", + "icRoutingPool\022\025\n\rnrOfInstances\030\001 \002(\r\022\030\n\020" + + "routerDispatcher\030\002 \001(\t\022\031\n\021usePoolDispatc" + + "her\030\003 \002(\010\022\031\n\007resizer\030\004 \001(\0132\010.Payload\"Z\n\021" + + "ScatterGatherPool\022$\n\007generic\030\001 \002(\0132\023.Gen" + + "ericRoutingPool\022\037\n\006within\030\002 \002(\0132\017.Finite" + + "Duration\"|\n\020TailChoppingPool\022$\n\007generic\030" + + "\001 \002(\0132\023.GenericRoutingPool\022\037\n\006within\030\002 \002" + + "(\0132\017.FiniteDuration\022!\n\010interval\030\003 \002(\0132\017." + + "FiniteDuration\"O\n\013AddressData\022\016\n\006system\030" + + "\001 \002(\t\022\020\n\010hostname\030\002 \002(\t\022\014\n\004port\030\003 \002(\r\022\020\n", + "\010protocol\030\004 \001(\t\"J\n\022RemoteRouterConfig\022\027\n" + "\005local\030\001 \002(\0132\010.Payload\022\033\n\005nodes\030\002 \003(\0132\014." + "AddressData*{\n\013CommandType\022\r\n\tASSOCIATE\020" + "\001\022\020\n\014DISASSOCIATE\020\002\022\r\n\tHEARTBEAT\020\003\022\036\n\032DI" + @@ -17179,72 +17173,72 @@ public final class WireFormats { akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_DeployData_descriptor, new java.lang.String[] { "Path", "Config", "RouterConfig", "Scope", "Dispatcher", "ScopeSerializerId", "ScopeManifest", "ConfigSerializerId", "ConfigManifest", "RouterConfigSerializerId", "RouterConfigManifest", }); - internal_static_AddressData_descriptor = - getDescriptor().getMessageTypes().get(8); - internal_static_AddressData_fieldAccessorTable = new - akka.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_AddressData_descriptor, - new java.lang.String[] { "System", "Hostname", "Port", "Protocol", }); internal_static_AkkaProtocolMessage_descriptor = - getDescriptor().getMessageTypes().get(9); + getDescriptor().getMessageTypes().get(8); internal_static_AkkaProtocolMessage_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_AkkaProtocolMessage_descriptor, new java.lang.String[] { "Payload", "Instruction", }); internal_static_AkkaControlMessage_descriptor = - getDescriptor().getMessageTypes().get(10); + getDescriptor().getMessageTypes().get(9); internal_static_AkkaControlMessage_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_AkkaControlMessage_descriptor, new java.lang.String[] { "CommandType", "HandshakeInfo", }); internal_static_AkkaHandshakeInfo_descriptor = - getDescriptor().getMessageTypes().get(11); + getDescriptor().getMessageTypes().get(10); internal_static_AkkaHandshakeInfo_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_AkkaHandshakeInfo_descriptor, new java.lang.String[] { "Origin", "Uid", "Cookie", }); internal_static_FiniteDuration_descriptor = - getDescriptor().getMessageTypes().get(12); + getDescriptor().getMessageTypes().get(11); internal_static_FiniteDuration_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_FiniteDuration_descriptor, new java.lang.String[] { "Value", "Unit", }); internal_static_RemoteScope_descriptor = - getDescriptor().getMessageTypes().get(13); + getDescriptor().getMessageTypes().get(12); internal_static_RemoteScope_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_RemoteScope_descriptor, new java.lang.String[] { "Node", }); internal_static_DefaultResizer_descriptor = - getDescriptor().getMessageTypes().get(14); + getDescriptor().getMessageTypes().get(13); internal_static_DefaultResizer_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_DefaultResizer_descriptor, new java.lang.String[] { "LowerBound", "UpperBound", "PressureThreshold", "RampupRate", "BackoffThreshold", "BackoffRate", "MessagesPerResize", }); internal_static_FromConfig_descriptor = - getDescriptor().getMessageTypes().get(15); + getDescriptor().getMessageTypes().get(14); internal_static_FromConfig_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_FromConfig_descriptor, new java.lang.String[] { "Resizer", "RouterDispatcher", }); internal_static_GenericRoutingPool_descriptor = - getDescriptor().getMessageTypes().get(16); + getDescriptor().getMessageTypes().get(15); internal_static_GenericRoutingPool_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_GenericRoutingPool_descriptor, new java.lang.String[] { "NrOfInstances", "RouterDispatcher", "UsePoolDispatcher", "Resizer", }); internal_static_ScatterGatherPool_descriptor = - getDescriptor().getMessageTypes().get(17); + getDescriptor().getMessageTypes().get(16); internal_static_ScatterGatherPool_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_ScatterGatherPool_descriptor, new java.lang.String[] { "Generic", "Within", }); internal_static_TailChoppingPool_descriptor = - getDescriptor().getMessageTypes().get(18); + getDescriptor().getMessageTypes().get(17); internal_static_TailChoppingPool_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_TailChoppingPool_descriptor, new java.lang.String[] { "Generic", "Within", "Interval", }); + internal_static_AddressData_descriptor = + getDescriptor().getMessageTypes().get(18); + internal_static_AddressData_fieldAccessorTable = new + akka.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_AddressData_descriptor, + new java.lang.String[] { "System", "Hostname", "Port", "Protocol", }); internal_static_RemoteRouterConfig_descriptor = getDescriptor().getMessageTypes().get(19); internal_static_RemoteRouterConfig_fieldAccessorTable = new diff --git a/akka-remote/src/main/mima-filters/2.5.x.backwards.excludes b/akka-remote/src/main/mima-filters/2.5.x.backwards.excludes index 35415ec43c..479c88973b 100644 --- a/akka-remote/src/main/mima-filters/2.5.x.backwards.excludes +++ b/akka-remote/src/main/mima-filters/2.5.x.backwards.excludes @@ -30,3 +30,5 @@ ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.RemoteWatcher.pr # #26432 Log of Dropped ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.artery.InboundContext.publishDropped") +# #22333 Disable Java serialization +ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.serialization.ThrowableSupport.stackTraceElementBuilder") diff --git a/akka-remote/src/main/protobuf/ContainerFormats.proto b/akka-remote/src/main/protobuf/ContainerFormats.proto index b160ffe0c5..68fc3c4e30 100644 --- a/akka-remote/src/main/protobuf/ContainerFormats.proto +++ b/akka-remote/src/main/protobuf/ContainerFormats.proto @@ -62,6 +62,12 @@ message Throwable { repeated StackTraceElement stackTrace = 4; } +message ThrowableNotSerializable { + required string message = 1; + required string originalMessage = 2; + required string originalClassName = 3; +} + message ActorInitializationException { optional ActorRef actor = 1; required string message = 2; diff --git a/akka-remote/src/main/resources/reference.conf b/akka-remote/src/main/resources/reference.conf index 0273312983..f279873060 100644 --- a/akka-remote/src/main/resources/reference.conf +++ b/akka-remote/src/main/resources/reference.conf @@ -22,10 +22,6 @@ akka { artery = "akka.remote.serialization.ArteryMessageSerializer" proto = "akka.remote.serialization.ProtobufSerializer" daemon-create = "akka.remote.serialization.DaemonMsgCreateSerializer" - primitive-long = "akka.remote.serialization.LongSerializer" - primitive-int = "akka.remote.serialization.IntSerializer" - primitive-string = "akka.remote.serialization.StringSerializer" - primitive-bytestring = "akka.remote.serialization.ByteStringSerializer" akka-system-msg = "akka.remote.serialization.SystemMessageSerializer" } @@ -70,6 +66,8 @@ akka { "akka.actor.ActorKilledException" = akka-misc "akka.actor.InvalidActorNameException" = akka-misc "akka.actor.InvalidMessageException" = akka-misc + "java.util.concurrent.TimeoutException" = akka-misc + "akka.remote.serialization.ThrowableNotSerializableException" = akka-misc "akka.actor.LocalScope$" = akka-misc "akka.remote.RemoteScope" = akka-misc @@ -95,21 +93,17 @@ akka { "akka.dispatch.sysmsg.SystemMessage" = akka-system-msg - "java.lang.String" = primitive-string - "akka.util.ByteString$ByteString1C" = primitive-bytestring - "akka.util.ByteString$ByteString1" = primitive-bytestring - "akka.util.ByteString$ByteStrings" = primitive-bytestring - "java.lang.Long" = primitive-long - "scala.Long" = primitive-long - "java.lang.Integer" = primitive-int - "scala.Int" = primitive-int - - # Java Serializer is by default used for exceptions. + # Java Serializer is by default used for exceptions and will by default + # not be allowed to be serialized, but in certain cases they are replaced + # by `akka.remote.serialization.ThrowableNotSerializableException` if + # no specific serializer has been defined: + # - when wrapped in `akka.actor.Status.Failure` for ask replies + # - when wrapped in system messages for exceptions from remote deployed child actors + # # It's recommended that you implement custom serializer for exceptions that are - # sent remotely, e.g. in akka.actor.Status.Failure for ask replies. You can add - # binding to akka-misc (MiscMessageSerializerSpec) for the exceptions that have - # a constructor with single message String or constructor with message String as - # first parameter and cause Throwable as second parameter. Note that it's not + # sent remotely, You can add binding to akka-misc (MiscMessageSerializerSpec) for the + # exceptions that have a constructor with single message String or constructor with + # message String as first parameter and cause Throwable as second parameter. Note that it's not # safe to add this binding for general exceptions such as IllegalArgumentException # because it may have a subclass without required constructor. "java.lang.Throwable" = java @@ -121,11 +115,17 @@ akka { "akka.remote.serialization.MessageContainerSerializer" = 6 "akka.remote.serialization.MiscMessageSerializer" = 16 "akka.remote.serialization.ArteryMessageSerializer" = 17 - "akka.remote.serialization.LongSerializer" = 18 - "akka.remote.serialization.IntSerializer" = 19 - "akka.remote.serialization.StringSerializer" = 20 - "akka.remote.serialization.ByteStringSerializer" = 21 + "akka.remote.serialization.SystemMessageSerializer" = 22 + + # deprecated in 2.6.0, moved to akka-actor + "akka.remote.serialization.LongSerializer" = 18 + # deprecated in 2.6.0, moved to akka-actor + "akka.remote.serialization.IntSerializer" = 19 + # deprecated in 2.6.0, moved to akka-actor + "akka.remote.serialization.StringSerializer" = 20 + # deprecated in 2.6.0, moved to akka-actor + "akka.remote.serialization.ByteStringSerializer" = 21 } deployment { diff --git a/akka-remote/src/main/scala/akka/remote/serialization/MiscMessageSerializer.scala b/akka-remote/src/main/scala/akka/remote/serialization/MiscMessageSerializer.scala index e4cb1421c9..d28d762a03 100644 --- a/akka-remote/src/main/scala/akka/remote/serialization/MiscMessageSerializer.scala +++ b/akka-remote/src/main/scala/akka/remote/serialization/MiscMessageSerializer.scala @@ -18,7 +18,6 @@ import akka.remote._ import akka.routing._ import akka.serialization.{ BaseSerializer, Serialization, SerializationExtension, SerializerWithStringManifest } import com.typesafe.config.{ Config, ConfigFactory, ConfigRenderOptions } - import akka.util.ccompat.JavaConverters._ import scala.concurrent.duration.{ FiniteDuration, TimeUnit } @@ -33,37 +32,38 @@ class MiscMessageSerializer(val system: ExtendedActorSystem) extends SerializerW private val EmptyConfig = ConfigFactory.empty() def toBinary(obj: AnyRef): Array[Byte] = obj match { - case identify: Identify => serializeIdentify(identify) - case identity: ActorIdentity => serializeActorIdentity(identity) - case Some(value) => serializeSome(value) - case None => ParameterlessSerializedMessage - case o: Optional[_] => serializeOptional(o) - case r: ActorRef => serializeActorRef(r) - case s: Status.Success => serializeStatusSuccess(s) - case f: Status.Failure => serializeStatusFailure(f) - case ex: ActorInitializationException => serializeActorInitializationException(ex) - case t: Throwable => throwableSupport.serializeThrowable(t) - case PoisonPill => ParameterlessSerializedMessage - case Kill => ParameterlessSerializedMessage - case RemoteWatcher.Heartbeat => ParameterlessSerializedMessage - case Done => ParameterlessSerializedMessage - case NotUsed => ParameterlessSerializedMessage - case hbrsp: RemoteWatcher.HeartbeatRsp => serializeHeartbeatRsp(hbrsp) - case rs: RemoteScope => serializeRemoteScope(rs) - case LocalScope => ParameterlessSerializedMessage - case a: Address => serializeAddressData(a) - case u: UniqueAddress => serializeClassicUniqueAddress(u) - case c: Config => serializeConfig(c) - case dr: DefaultResizer => serializeDefaultResizer(dr) - case fc: FromConfig => serializeFromConfig(fc) - case bp: BalancingPool => serializeBalancingPool(bp) - case bp: BroadcastPool => serializeBroadcastPool(bp) - case rp: RandomPool => serializeRandomPool(rp) - case rrp: RoundRobinPool => serializeRoundRobinPool(rrp) - case sgp: ScatterGatherFirstCompletedPool => serializeScatterGatherFirstCompletedPool(sgp) - case tp: TailChoppingPool => serializeTailChoppingPool(tp) - case rrc: RemoteRouterConfig => serializeRemoteRouterConfig(rrc) - case _ => throw new IllegalArgumentException(s"Cannot serialize object of type [${obj.getClass.getName}]") + case identify: Identify => serializeIdentify(identify) + case identity: ActorIdentity => serializeActorIdentity(identity) + case Some(value) => serializeSome(value) + case None => ParameterlessSerializedMessage + case o: Optional[_] => serializeOptional(o) + case r: ActorRef => serializeActorRef(r) + case s: Status.Success => serializeStatusSuccess(s) + case f: Status.Failure => serializeStatusFailure(f) + case ex: ActorInitializationException => serializeActorInitializationException(ex) + case ex: ThrowableNotSerializableException => serializeThrowableNotSerializableException(ex) + case t: Throwable => throwableSupport.serializeThrowable(t) + case PoisonPill => ParameterlessSerializedMessage + case Kill => ParameterlessSerializedMessage + case RemoteWatcher.Heartbeat => ParameterlessSerializedMessage + case Done => ParameterlessSerializedMessage + case NotUsed => ParameterlessSerializedMessage + case hbrsp: RemoteWatcher.HeartbeatRsp => serializeHeartbeatRsp(hbrsp) + case rs: RemoteScope => serializeRemoteScope(rs) + case LocalScope => ParameterlessSerializedMessage + case a: Address => serializeAddressData(a) + case u: UniqueAddress => serializeClassicUniqueAddress(u) + case c: Config => serializeConfig(c) + case dr: DefaultResizer => serializeDefaultResizer(dr) + case fc: FromConfig => serializeFromConfig(fc) + case bp: BalancingPool => serializeBalancingPool(bp) + case bp: BroadcastPool => serializeBroadcastPool(bp) + case rp: RandomPool => serializeRandomPool(rp) + case rrp: RoundRobinPool => serializeRoundRobinPool(rrp) + case sgp: ScatterGatherFirstCompletedPool => serializeScatterGatherFirstCompletedPool(sgp) + case tp: TailChoppingPool => serializeTailChoppingPool(tp) + case rrc: RemoteRouterConfig => serializeRemoteRouterConfig(rrc) + case _ => throw new IllegalArgumentException(s"Cannot serialize object of type [${obj.getClass.getName}]") } private def serializeIdentify(identify: Identify): Array[Byte] = @@ -122,10 +122,20 @@ class MiscMessageSerializer(val system: ExtendedActorSystem) extends SerializerW val builder = ContainerFormats.ActorInitializationException.newBuilder() if (ex.getActor ne null) builder.setActor(actorRefBuilder(ex.getActor)) - builder.setMessage(ex.getMessage).setCause(payloadSupport.payloadBuilder(ex.getCause)).build().toByteArray } + private def serializeThrowableNotSerializableException(ex: ThrowableNotSerializableException): Array[Byte] = { + val builder = ContainerFormats.ThrowableNotSerializable.newBuilder() + builder.setMessage(ex.getMessage) + if (ex.originalMessage eq null) + builder.setOriginalMessage("") + else + builder.setOriginalMessage(ex.originalMessage) + builder.setOriginalClassName(ex.originalClassName) + builder.build().toByteArray + } + private def serializeConfig(c: Config): Array[Byte] = { c.root.render(ConfigRenderOptions.concise()).getBytes(StandardCharsets.UTF_8) } @@ -287,6 +297,7 @@ class MiscMessageSerializer(val system: ExtendedActorSystem) extends SerializerW private val UniqueAddressManifest = "UD" private val RemoteWatcherHBRespManifest = "RWHR" private val ActorInitializationExceptionManifest = "AIEX" + private val ThrowableNotSerializableExceptionManifest = "TNSEX" private val LocalScopeManifest = "LS" private val RemoteScopeManifest = "RS" private val ConfigManifest = "CF" @@ -318,6 +329,7 @@ class MiscMessageSerializer(val system: ExtendedActorSystem) extends SerializerW UniqueAddressManifest -> deserializeUniqueAddress, RemoteWatcherHBRespManifest -> deserializeHeartbeatRsp, ActorInitializationExceptionManifest -> deserializeActorInitializationException, + ThrowableNotSerializableExceptionManifest -> deserializeThrowableNotSerializableException, LocalScopeManifest -> ((_) => LocalScope), RemoteScopeManifest -> deserializeRemoteScope, ConfigManifest -> deserializeConfig, @@ -333,35 +345,36 @@ class MiscMessageSerializer(val system: ExtendedActorSystem) extends SerializerW override def manifest(o: AnyRef): String = o match { - case _: Identify => IdentifyManifest - case _: ActorIdentity => ActorIdentityManifest - case _: Option[Any] => OptionManifest - case _: Optional[_] => OptionalManifest - case _: ActorRef => ActorRefManifest - case _: Status.Success => StatusSuccessManifest - case _: Status.Failure => StatusFailureManifest - case _: ActorInitializationException => ActorInitializationExceptionManifest - case _: Throwable => ThrowableManifest - case PoisonPill => PoisonPillManifest - case Kill => KillManifest - case RemoteWatcher.Heartbeat => RemoteWatcherHBManifest - case Done => DoneManifest - case NotUsed => NotUsedManifest - case _: Address => AddressManifest - case _: UniqueAddress => UniqueAddressManifest - case _: RemoteWatcher.HeartbeatRsp => RemoteWatcherHBRespManifest - case LocalScope => LocalScopeManifest - case _: RemoteScope => RemoteScopeManifest - case _: Config => ConfigManifest - case _: FromConfig => FromConfigManifest - case _: DefaultResizer => DefaultResizerManifest - case _: BalancingPool => BalancingPoolManifest - case _: BroadcastPool => BroadcastPoolManifest - case _: RandomPool => RandomPoolManifest - case _: RoundRobinPool => RoundRobinPoolManifest - case _: ScatterGatherFirstCompletedPool => ScatterGatherPoolManifest - case _: TailChoppingPool => TailChoppingPoolManifest - case _: RemoteRouterConfig => RemoteRouterConfigManifest + case _: Identify => IdentifyManifest + case _: ActorIdentity => ActorIdentityManifest + case _: Option[Any] => OptionManifest + case _: Optional[_] => OptionalManifest + case _: ActorRef => ActorRefManifest + case _: Status.Success => StatusSuccessManifest + case _: Status.Failure => StatusFailureManifest + case _: ActorInitializationException => ActorInitializationExceptionManifest + case _: ThrowableNotSerializableException => ThrowableNotSerializableExceptionManifest + case _: Throwable => ThrowableManifest + case PoisonPill => PoisonPillManifest + case Kill => KillManifest + case RemoteWatcher.Heartbeat => RemoteWatcherHBManifest + case Done => DoneManifest + case NotUsed => NotUsedManifest + case _: Address => AddressManifest + case _: UniqueAddress => UniqueAddressManifest + case _: RemoteWatcher.HeartbeatRsp => RemoteWatcherHBRespManifest + case LocalScope => LocalScopeManifest + case _: RemoteScope => RemoteScopeManifest + case _: Config => ConfigManifest + case _: FromConfig => FromConfigManifest + case _: DefaultResizer => DefaultResizerManifest + case _: BalancingPool => BalancingPoolManifest + case _: BroadcastPool => BroadcastPoolManifest + case _: RandomPool => RandomPoolManifest + case _: RoundRobinPool => RoundRobinPoolManifest + case _: ScatterGatherFirstCompletedPool => ScatterGatherPoolManifest + case _: TailChoppingPool => TailChoppingPoolManifest + case _: RemoteRouterConfig => RemoteRouterConfigManifest case _ => throw new IllegalArgumentException(s"Can't serialize object of type ${o.getClass} in [${getClass.getName}]") } @@ -466,6 +479,11 @@ class MiscMessageSerializer(val system: ExtendedActorSystem) extends SerializerW payloadSupport.deserializePayload(serializedEx.getCause).asInstanceOf[Throwable]) } + private def deserializeThrowableNotSerializableException(bytes: Array[Byte]): ThrowableNotSerializableException = { + val serializedEx = ContainerFormats.ThrowableNotSerializable.parseFrom(bytes) + new ThrowableNotSerializableException(serializedEx.getOriginalMessage, serializedEx.getOriginalClassName) + } + private def deserializeRemoteScope(bytes: Array[Byte]): RemoteScope = { val rs = WireFormats.RemoteScope.parseFrom(bytes) RemoteScope(deserializeAddressData(rs.getNode)) diff --git a/akka-remote/src/main/scala/akka/remote/serialization/PrimitiveSerializers.scala b/akka-remote/src/main/scala/akka/remote/serialization/PrimitiveSerializers.scala index 636f338adf..fb48c2381b 100644 --- a/akka-remote/src/main/scala/akka/remote/serialization/PrimitiveSerializers.scala +++ b/akka-remote/src/main/scala/akka/remote/serialization/PrimitiveSerializers.scala @@ -4,118 +4,60 @@ package akka.remote.serialization -import java.nio.{ BufferOverflowException, ByteBuffer } +import java.nio.ByteBuffer import akka.actor.ExtendedActorSystem -import akka.serialization.{ BaseSerializer, ByteBufferSerializer } -import akka.util.ByteString +import akka.serialization.BaseSerializer +import akka.serialization.ByteBufferSerializer +@deprecated("Moved to akka.serialization.LongSerializer in akka-actor", "2.6.0") class LongSerializer(val system: ExtendedActorSystem) extends BaseSerializer with ByteBufferSerializer { - override def includeManifest: Boolean = false + // this serializer is not used unless someone is instantiating it manually, it's not in config + private val delegate = new akka.serialization.LongSerializer(system) - override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = { - buf.putLong(Long.unbox(o)) - } - - override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = { - Long.box(buf.getLong) - } - - override def toBinary(o: AnyRef): Array[Byte] = { - val result = new Array[Byte](8) - var long = Long.unbox(o) - var i = 0 - while (long != 0) { - result(i) = (long & 0xFF).toByte - i += 1 - long >>>= 8 - } - result - } - - override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = { - var result = 0L - var i = 7 - while (i >= 0) { - result <<= 8 - result |= (bytes(i).toLong & 0xFF) - i -= 1 - } - Long.box(result) - } + override def includeManifest: Boolean = delegate.includeManifest + override val identifier: Int = delegate.identifier + override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = delegate.toBinary(o, buf) + override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = delegate.fromBinary(buf, manifest) + override def toBinary(o: AnyRef): Array[Byte] = delegate.toBinary(o) + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = delegate.fromBinary(bytes, manifest) } +@deprecated("Moved to akka.serialization.IntSerializer in akka-actor", "2.6.0") class IntSerializer(val system: ExtendedActorSystem) extends BaseSerializer with ByteBufferSerializer { - override def includeManifest: Boolean = false + // this serializer is not used unless someone is instantiating it manually, it's not in config + private val delegate = new akka.serialization.IntSerializer(system) - override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = buf.putInt(Int.unbox(o)) - - override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = Int.box(buf.getInt) - - override def toBinary(o: AnyRef): Array[Byte] = { - val result = new Array[Byte](4) - var int = Int.unbox(o) - var i = 0 - while (int != 0) { - result(i) = (int & 0xFF).toByte - i += 1 - int >>>= 8 - } - result - } - - override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = { - var result = 0 - var i = 3 - while (i >= 0) { - result <<= 8 - result |= (bytes(i).toInt & 0xFF) - i -= 1 - } - Int.box(result) - } + override def includeManifest: Boolean = delegate.includeManifest + override val identifier: Int = delegate.identifier + override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = delegate.toBinary(o, buf) + override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = delegate.fromBinary(buf, manifest) + override def toBinary(o: AnyRef): Array[Byte] = delegate.toBinary(o) + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = delegate.fromBinary(bytes, manifest) } +@deprecated("Moved to akka.serialization.StringSerializer in akka-actor", "2.6.0") class StringSerializer(val system: ExtendedActorSystem) extends BaseSerializer with ByteBufferSerializer { - override def includeManifest: Boolean = false - - override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = buf.put(toBinary(o)) - - override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = { - val bytes = new Array[Byte](buf.remaining()) - buf.get(bytes) - new String(bytes, "UTF-8") - } - - override def toBinary(o: AnyRef): Array[Byte] = o.asInstanceOf[String].getBytes("UTF-8") - - override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = new String(bytes, "UTF-8") + // this serializer is not used unless someone is instantiating it manually, it's not in config + private val delegate = new akka.serialization.StringSerializer(system) + override def includeManifest: Boolean = delegate.includeManifest + override val identifier: Int = delegate.identifier + override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = delegate.toBinary(o, buf) + override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = delegate.fromBinary(buf, manifest) + override def toBinary(o: AnyRef): Array[Byte] = delegate.toBinary(o) + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = delegate.fromBinary(bytes, manifest) } +@deprecated("Moved to akka.serialization.ByteStringSerializer in akka-actor", "2.6.0") class ByteStringSerializer(val system: ExtendedActorSystem) extends BaseSerializer with ByteBufferSerializer { - override def includeManifest: Boolean = false - - override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = { - val bs = o.asInstanceOf[ByteString] - - // ByteString.copyToBuffer does not throw BufferOverflowException - if (bs.copyToBuffer(buf) < bs.length) - throw new BufferOverflowException() - } - - override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = - ByteString.fromByteBuffer(buf) - - override def toBinary(o: AnyRef): Array[Byte] = { - val bs = o.asInstanceOf[ByteString] - val result = new Array[Byte](bs.length) - bs.copyToArray(result, 0, bs.length) - result - } - - override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = { - ByteString(bytes) - } + // this serializer is not used unless someone is instantiating it manually, it's not in config + private val delegate = new akka.serialization.ByteStringSerializer(system) + override def includeManifest: Boolean = delegate.includeManifest + override val identifier: Int = delegate.identifier + override def toBinary(o: AnyRef, buf: ByteBuffer): Unit = delegate.toBinary(o, buf) + override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = delegate.fromBinary(buf, manifest) + override def toBinary(o: AnyRef): Array[Byte] = delegate.toBinary(o) + override def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = delegate.fromBinary(bytes, manifest) } diff --git a/akka-remote/src/main/scala/akka/remote/serialization/ThrowableNotSerializableException.scala b/akka-remote/src/main/scala/akka/remote/serialization/ThrowableNotSerializableException.scala new file mode 100644 index 0000000000..aa5d48c117 --- /dev/null +++ b/akka-remote/src/main/scala/akka/remote/serialization/ThrowableNotSerializableException.scala @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2019 Lightbend Inc. + */ + +package akka.remote.serialization + +/** + * Use as replacement for an original exception when it can't be serialized or deserialized. + * @param originalMessage the message of the original exception + * @param originalClassName the class name of the original exception + * @param cause exception that caused deserialization error, optional and will not be serialized + */ +final class ThrowableNotSerializableException( + val originalMessage: String, + val originalClassName: String, + cause: Throwable) + extends IllegalArgumentException(s"Serialization of [$originalClassName] failed. $originalMessage", cause) { + + def this(originalMessage: String, originalClassName: String) = this(originalMessage, originalClassName, null) +} diff --git a/akka-remote/src/main/scala/akka/remote/serialization/ThrowableSupport.scala b/akka-remote/src/main/scala/akka/remote/serialization/ThrowableSupport.scala index e058708633..b9c05ec171 100644 --- a/akka-remote/src/main/scala/akka/remote/serialization/ThrowableSupport.scala +++ b/akka-remote/src/main/scala/akka/remote/serialization/ThrowableSupport.scala @@ -4,8 +4,14 @@ package akka.remote.serialization +import scala.util.Failure +import scala.util.Success +import scala.util.control.NonFatal + import akka.actor.ExtendedActorSystem +import akka.event.Logging import akka.remote.ContainerFormats +import akka.serialization.DisabledJavaSerializer import akka.serialization.SerializationExtension /** @@ -15,6 +21,7 @@ private[akka] class ThrowableSupport(system: ExtendedActorSystem) { private lazy val serialization = SerializationExtension(system) private val payloadSupport = new WrappedPayloadSupport(system) + private val log = Logging(system, getClass) def serializeThrowable(t: Throwable): Array[Byte] = { toProtobufThrowable(t).build().toByteArray @@ -38,7 +45,7 @@ private[akka] class ThrowableSupport(system: ExtendedActorSystem) { b } - def stackTraceElementBuilder(elem: StackTraceElement): ContainerFormats.StackTraceElement.Builder = { + private def stackTraceElementBuilder(elem: StackTraceElement): ContainerFormats.StackTraceElement.Builder = { val builder = ContainerFormats.StackTraceElement .newBuilder() .setClassName(elem.getClassName) @@ -53,23 +60,46 @@ private[akka] class ThrowableSupport(system: ExtendedActorSystem) { } def fromProtobufThrowable(protoT: ContainerFormats.Throwable): Throwable = { - val t: Throwable = - if (protoT.hasCause) { - val cause = payloadSupport.deserializePayload(protoT.getCause).asInstanceOf[Throwable] - system.dynamicAccess - .createInstanceFor[Throwable]( - protoT.getClassName, - List(classOf[String] -> protoT.getMessage, classOf[Throwable] -> cause)) - .get + val className = protoT.getClassName + try { + // Important security note: before creating an instance of from the class name we + // check that the class is a Throwable and that it has a configured serializer. + val clazz = system.dynamicAccess.getClassFor[Throwable](className).get + // this will throw NotSerializableException if no serializer configured, caught below + val serializer = serialization.serializerFor(clazz) + if (serializer.isInstanceOf[DisabledJavaSerializer]) { + val notSerializableException = + new ThrowableNotSerializableException(protoT.getMessage, "unknown") + log.debug( + "Couldn't deserialize [{}] because Java serialization is disabled. Fallback to " + + "ThrowableNotSerializableException. {}", + notSerializableException.originalClassName, + notSerializableException.originalMessage) + notSerializableException } else { - // Important security note: before creating an instance of from the class name we - // check that the class is a Throwable and that it has a configured serializer. - val clazz = system.dynamicAccess.getClassFor[Throwable](protoT.getClassName).get - serialization.serializerFor(clazz) // this will throw NotSerializableException if no serializer configured - system.dynamicAccess.createInstanceFor[Throwable](clazz, List(classOf[String] -> protoT.getMessage)).get + (if (protoT.hasCause) { + val cause = payloadSupport.deserializePayload(protoT.getCause).asInstanceOf[Throwable] + system.dynamicAccess.createInstanceFor[Throwable]( + className, + List(classOf[String] -> protoT.getMessage, classOf[Throwable] -> cause)) + } else { + system.dynamicAccess.createInstanceFor[Throwable](clazz, List(classOf[String] -> protoT.getMessage)) + }) match { + case Success(t) => + fillInStackTrace(protoT, t) + t + case Failure(e) => + new ThrowableNotSerializableException(protoT.getMessage, className, e) + } } + } catch { + case NonFatal(e) => + new ThrowableNotSerializableException(protoT.getMessage, className, e) + } + } + private def fillInStackTrace(protoT: ContainerFormats.Throwable, t: Throwable): Unit = { import akka.util.ccompat.JavaConverters._ val stackTrace = protoT.getStackTraceList.asScala.map { elem => @@ -81,7 +111,5 @@ private[akka] class ThrowableSupport(system: ExtendedActorSystem) { elem.getLineNumber) }.toArray t.setStackTrace(stackTrace) - t } - } diff --git a/akka-remote/src/main/scala/akka/remote/serialization/WrappedPayloadSupport.scala b/akka-remote/src/main/scala/akka/remote/serialization/WrappedPayloadSupport.scala index e4d55a2e44..dca25bf751 100644 --- a/akka-remote/src/main/scala/akka/remote/serialization/WrappedPayloadSupport.scala +++ b/akka-remote/src/main/scala/akka/remote/serialization/WrappedPayloadSupport.scala @@ -5,9 +5,11 @@ package akka.remote.serialization import akka.actor.ExtendedActorSystem +import akka.event.Logging import akka.remote.ContainerFormats import akka.serialization.{ SerializationExtension, Serializers } import akka.protobuf.ByteString +import akka.serialization.DisabledJavaSerializer /** * INTERNAL API @@ -15,16 +17,42 @@ import akka.protobuf.ByteString private[akka] class WrappedPayloadSupport(system: ExtendedActorSystem) { private lazy val serialization = SerializationExtension(system) + private val log = Logging(system, getClass) + /** + * Serialize the `input` along with its `manifest` and `serializerId`. + * + * If `input` is a `Throwable` and can't be serialized because Java serialization is disabled it + * will fallback to `ThrowableNotSerializableException`. + */ def payloadBuilder(input: Any): ContainerFormats.Payload.Builder = { val payload = input.asInstanceOf[AnyRef] val builder = ContainerFormats.Payload.newBuilder() val serializer = serialization.findSerializerFor(payload) - builder.setEnclosedMessage(ByteString.copyFrom(serializer.toBinary(payload))).setSerializerId(serializer.identifier) + payload match { + case t: Throwable if serializer.isInstanceOf[DisabledJavaSerializer] => + val notSerializableException = + new ThrowableNotSerializableException(t.getMessage, t.getClass.getName, t.getCause) + log.debug( + "Couldn't serialize [{}] because Java serialization is disabled. Fallback to " + + "ThrowableNotSerializableException. {}", + notSerializableException.originalClassName, + notSerializableException.originalMessage) + val serializer2 = serialization.findSerializerFor(notSerializableException) + builder + .setEnclosedMessage(ByteString.copyFrom(serializer2.toBinary(notSerializableException))) + .setSerializerId(serializer2.identifier) + val manifest = Serializers.manifestFor(serializer2, notSerializableException) + if (manifest.nonEmpty) builder.setMessageManifest(ByteString.copyFromUtf8(manifest)) - val ms = Serializers.manifestFor(serializer, payload) - if (ms.nonEmpty) builder.setMessageManifest(ByteString.copyFromUtf8(ms)) + case _ => + builder + .setEnclosedMessage(ByteString.copyFrom(serializer.toBinary(payload))) + .setSerializerId(serializer.identifier) + val manifest = Serializers.manifestFor(serializer, payload) + if (manifest.nonEmpty) builder.setMessageManifest(ByteString.copyFromUtf8(manifest)) + } builder } diff --git a/akka-remote/src/test/java/akka/remote/ProtobufProtocol.java b/akka-remote/src/test/java/akka/remote/ProtobufProtocol.java index c258bbc93d..3f91a56a4d 100644 --- a/akka-remote/src/test/java/akka/remote/ProtobufProtocol.java +++ b/akka-remote/src/test/java/akka/remote/ProtobufProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2019 Lightbend Inc. + * Copyright (C) 2019 Lightbend Inc. */ // Generated by the protocol buffer compiler. DO NOT EDIT! diff --git a/akka-remote/src/test/resources/reference.conf b/akka-remote/src/test/resources/reference.conf index 87c449d340..a90d6908f0 100644 --- a/akka-remote/src/test/resources/reference.conf +++ b/akka-remote/src/test/resources/reference.conf @@ -1,6 +1,5 @@ akka { actor { - serialize-messages = on - warn-about-java-serializer-usage = off + serialize-messages = off } } diff --git a/akka-remote/src/test/scala/akka/remote/MessageLoggingSpec.scala b/akka-remote/src/test/scala/akka/remote/MessageLoggingSpec.scala index a4e7b0d690..97f4a476e3 100644 --- a/akka-remote/src/test/scala/akka/remote/MessageLoggingSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/MessageLoggingSpec.scala @@ -8,6 +8,7 @@ import akka.actor.{ Actor, ActorIdentity, ActorSystem, ExtendedActorSystem, Iden import akka.testkit.{ AkkaSpec, ImplicitSender, TestKit } import com.typesafe.config.{ Config, ConfigFactory } import MessageLoggingSpec._ +import akka.serialization.jackson.CborSerializable object MessageLoggingSpec { def config(artery: Boolean) = ConfigFactory.parseString(s""" @@ -36,7 +37,7 @@ object MessageLoggingSpec { } """.stripMargin) - case class BadMsg(msg: String) { + case class BadMsg(msg: String) extends CborSerializable { override def toString = throw new RuntimeException("Don't log me") } diff --git a/akka-remote/src/test/scala/akka/remote/RemoteFeaturesSpec.scala b/akka-remote/src/test/scala/akka/remote/RemoteFeaturesSpec.scala index 92b2b3fe39..00c49946db 100644 --- a/akka-remote/src/test/scala/akka/remote/RemoteFeaturesSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/RemoteFeaturesSpec.scala @@ -160,7 +160,7 @@ class RemoteFeaturesDisabledSpec extends RemoteFeaturesSpec(RemoteFeaturesSpec.d masterRef.tell(42, senderProbe.ref) senderProbe.expectMsg(42) EventFilter[Exception]("crash", occurrences = 1).intercept { - masterRef ! new Exception("crash") + masterRef ! "throwException" }(masterSystem) senderProbe.expectMsg("preRestart") masterRef.tell(43, senderProbe.ref) diff --git a/akka-remote/src/test/scala/akka/remote/RemoteRouterSpec.scala b/akka-remote/src/test/scala/akka/remote/RemoteRouterSpec.scala index 7ddee30074..abcdc2dcd7 100644 --- a/akka-remote/src/test/scala/akka/remote/RemoteRouterSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/RemoteRouterSpec.scala @@ -23,7 +23,6 @@ object RemoteRouterSpec { class RemoteRouterSpec extends AkkaSpec(s""" akka.actor.provider = remote - akka.actor.allow-java-serialization = off akka.actor.serialize-messages = off akka.remote.use-unsafe-remote-features-without-cluster = on akka.remote.classic.netty.tcp { diff --git a/akka-remote/src/test/scala/akka/remote/SerializationChecksPlainRemotingSpec.scala b/akka-remote/src/test/scala/akka/remote/SerializationChecksPlainRemotingSpec.scala deleted file mode 100644 index 700fed6b7c..0000000000 --- a/akka-remote/src/test/scala/akka/remote/SerializationChecksPlainRemotingSpec.scala +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2009-2019 Lightbend Inc. - */ - -package akka.remote - -import akka.testkit.AkkaSpec - -class SerializationChecksPlainRemotingSpec extends AkkaSpec { - - "Settings serialize-messages" must { - - "be on for tests" in { - system.settings.SerializeAllMessages should ===(true) - } - - } - -} diff --git a/akka-remote/src/test/scala/akka/remote/Ticket1978CommunicationSpec.scala b/akka-remote/src/test/scala/akka/remote/Ticket1978CommunicationSpec.scala index 513d7a6ca1..15dd04792c 100644 --- a/akka-remote/src/test/scala/akka/remote/Ticket1978CommunicationSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/Ticket1978CommunicationSpec.scala @@ -57,6 +57,9 @@ object Configuration { } } } + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """ final case class CipherConfig( diff --git a/akka-remote/src/test/scala/akka/remote/artery/ArterySpecSupport.scala b/akka-remote/src/test/scala/akka/remote/artery/ArterySpecSupport.scala index db9c8080b5..560a96b9ba 100644 --- a/akka-remote/src/test/scala/akka/remote/artery/ArterySpecSupport.scala +++ b/akka-remote/src/test/scala/akka/remote/artery/ArterySpecSupport.scala @@ -20,7 +20,6 @@ object ArterySpecSupport { akka { actor { provider = remote - warn-about-java-serializer-usage = off serialize-creators = off } akka.remote.warn-about-direct-use = off @@ -33,7 +32,7 @@ object ArterySpecSupport { } }""") - def newFlightRecorderConfig = + def newFlightRecorderConfig: Config = ConfigFactory.parseString(s""" akka { remote.artery { @@ -49,7 +48,7 @@ object ArterySpecSupport { * Artery enabled, flight recorder enabled, dynamic selection of port on localhost. * Combine with [[FlightRecorderSpecIntegration]] or remember to delete flight recorder file if using manually */ - def defaultConfig = + def defaultConfig: Config = newFlightRecorderConfig .withFallback(staticArteryRemotingConfig) .withFallback(tlsConfig) // TLS only used if transport=tls-tcp diff --git a/akka-remote/src/test/scala/akka/remote/artery/MetadataCarryingSpec.scala b/akka-remote/src/test/scala/akka/remote/artery/MetadataCarryingSpec.scala index adcc2d233a..dbf936dbb0 100644 --- a/akka-remote/src/test/scala/akka/remote/artery/MetadataCarryingSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/artery/MetadataCarryingSpec.scala @@ -5,6 +5,7 @@ package akka.remote.artery import java.util.concurrent.atomic.AtomicReference + import akka.actor._ import akka.testkit.ImplicitSender import akka.testkit.TestActors @@ -13,6 +14,8 @@ import akka.util.ByteString import java.nio.{ ByteBuffer, CharBuffer } import java.nio.charset.Charset +import akka.testkit.JavaSerializable + object MetadataCarryingSpy extends ExtensionId[MetadataCarryingSpy] with ExtensionIdProvider { override def get(system: ActorSystem): MetadataCarryingSpy = super.get(system) override def lookup = MetadataCarryingSpy @@ -87,7 +90,7 @@ class TestInstrument(system: ExtendedActorSystem) extends RemoteInstrument { } object MetadataCarryingSpec { - final case class Ping(payload: ByteString = ByteString.empty) + final case class Ping(payload: ByteString = ByteString.empty) extends JavaSerializable class ProxyActor(local: ActorRef, remotePath: ActorPath) extends Actor { val remote = context.system.actorSelection(remotePath) diff --git a/akka-remote/src/test/scala/akka/remote/artery/RemoteDeathWatchSpec.scala b/akka-remote/src/test/scala/akka/remote/artery/RemoteDeathWatchSpec.scala index 403458625d..16f8f7072c 100644 --- a/akka-remote/src/test/scala/akka/remote/artery/RemoteDeathWatchSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/artery/RemoteDeathWatchSpec.scala @@ -36,6 +36,9 @@ object RemoteDeathWatchSpec { aeron.image-liveness-timeout = 9 seconds } } + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """).withFallback(ArterySpecSupport.defaultConfig) } @@ -100,8 +103,8 @@ class RemoteDeathWatchSpec // this immediately. With TCP it will trigger after handshake timeout. Can we see the UnknownHostException // reason somehow and fail the stream immediately for that case? val path = RootActorPath(Address("akka", system.name, "unknownhost2", 2552)) / "user" / "subject" - system.actorSelection(path) ! Identify(path) - expectMsg(60.seconds, ActorIdentity(path, None)) + system.actorSelection(path) ! Identify(path.toString) + expectMsg(60.seconds, ActorIdentity(path.toString, None)) } } diff --git a/akka-remote/src/test/scala/akka/remote/artery/RemoteDeploymentSpec.scala b/akka-remote/src/test/scala/akka/remote/artery/RemoteDeploymentSpec.scala index 483600dbcb..acbb104e7f 100644 --- a/akka-remote/src/test/scala/akka/remote/artery/RemoteDeploymentSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/artery/RemoteDeploymentSpec.scala @@ -14,8 +14,14 @@ object RemoteDeploymentSpec { var target: ActorRef = context.system.deadLetters def receive = { - case ex: Exception => throw ex - case x => target = sender(); sender() ! x + case "throwInvalidActorNameException" => + // InvalidActorNameException is supported by akka-misc + throw InvalidActorNameException("wrong name") + case "throwException" => + // no specific serialization binding for Exception + throw new Exception("crash") + case x => + target = sender(); sender() ! x } override def preStart(): Unit = {} @@ -73,6 +79,7 @@ class RemoteDeploymentSpec s""" akka.actor.deployment { /blub.remote = "akka://${system.name}@localhost:$port" + /blub2.remote = "akka://${system.name}@localhost:$port" "/parent*/*".remote = "akka://${system.name}@localhost:$port" } akka.remote.artery.advanced.inbound-lanes = 10 @@ -92,8 +99,26 @@ class RemoteDeploymentSpec r.tell(42, senderProbe.ref) senderProbe.expectMsg(42) - EventFilter[Exception]("crash", occurrences = 1).intercept { - r ! new Exception("crash") + EventFilter[Exception]("wrong name", occurrences = 1).intercept { + r ! "throwInvalidActorNameException" + }(masterSystem) + senderProbe.expectMsg("preRestart") + r.tell(43, senderProbe.ref) + senderProbe.expectMsg(43) + masterSystem.stop(r) + senderProbe.expectMsg("postStop") + } + + "create and supervise children on remote node for unknown exception" in { + val senderProbe = TestProbe()(masterSystem) + val r = masterSystem.actorOf(Props[Echo1], "blub2") + r.path.toString should ===( + s"akka://${system.name}@localhost:${port}/remote/akka/${masterSystem.name}@localhost:${masterPort}/user/blub2") + + r.tell(42, senderProbe.ref) + senderProbe.expectMsg(42) + EventFilter[Exception]("Serialization of [java.lang.Exception] failed. crash", occurrences = 1).intercept { + r ! "throwException" }(masterSystem) senderProbe.expectMsg("preRestart") r.tell(43, senderProbe.ref) diff --git a/akka-remote/src/test/scala/akka/remote/artery/RemoteFailureSpec.scala b/akka-remote/src/test/scala/akka/remote/artery/RemoteFailureSpec.scala index e6b493db1d..03f3729e56 100644 --- a/akka-remote/src/test/scala/akka/remote/artery/RemoteFailureSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/artery/RemoteFailureSpec.scala @@ -8,11 +8,12 @@ import akka.remote.EndpointDisassociatedException import akka.testkit.{ EventFilter, ImplicitSender, TestActors, TestEvent } import scala.concurrent.duration._ +import akka.serialization.jackson.CborSerializable import akka.testkit.DeadLettersFilter import akka.testkit.TestEvent.Mute object RemoteFailureSpec { - final case class Ping(s: String) + final case class Ping(s: String) extends CborSerializable } class RemoteFailureSpec extends ArteryMultiNodeSpec with ImplicitSender { diff --git a/akka-remote/src/test/scala/akka/remote/artery/UntrustedSpec.scala b/akka-remote/src/test/scala/akka/remote/artery/UntrustedSpec.scala index c31e6eb579..e44f65ae91 100644 --- a/akka-remote/src/test/scala/akka/remote/artery/UntrustedSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/artery/UntrustedSpec.scala @@ -5,6 +5,7 @@ package akka.remote.artery import scala.concurrent.duration._ + import com.typesafe.config.ConfigFactory import akka.actor.Actor import akka.actor.ActorIdentity @@ -21,12 +22,12 @@ import akka.actor.ActorSelection import akka.testkit.TestEvent import akka.event.Logging import akka.remote.RARP +import akka.serialization.jackson.CborSerializable import akka.testkit.EventFilter -import akka.testkit.JavaSerializable object UntrustedSpec { - final case class IdentifyReq(path: String) extends JavaSerializable - final case class StopChild(name: String) extends JavaSerializable + final case class IdentifyReq(path: String) extends CborSerializable + final case class StopChild(name: String) extends CborSerializable class Receptionist(testActor: ActorRef) extends Actor { context.actorOf(Props(classOf[Child], testActor), "child1") diff --git a/akka-remote/src/test/scala/akka/remote/classic/ActorsLeakSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/ActorsLeakSpec.scala index 8eadecdf8b..670d3ab15e 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/ActorsLeakSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/ActorsLeakSpec.scala @@ -30,6 +30,9 @@ object ActorsLeakSpec { akka.remote.classic.transport-failure-detector.acceptable-heartbeat-pause = 3 s akka.remote.classic.quarantine-after-silence = 3 s akka.test.filter-leeway = 12 s + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """) def collectLiveActors(root: Option[ActorRef]): immutable.Seq[ActorRef] = { diff --git a/akka-remote/src/test/scala/akka/remote/classic/RemoteDeathWatchSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/RemoteDeathWatchSpec.scala index c6d4127848..c4c57e8a7c 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/RemoteDeathWatchSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/RemoteDeathWatchSpec.scala @@ -22,6 +22,7 @@ akka { deployment { /watchers.remote = "akka.tcp://other@localhost:2666" } + } remote.use-unsafe-remote-features-without-cluster = on remote.artery.enabled = off @@ -34,6 +35,9 @@ akka { } } } +# test is using Java serialization and not priority to rewrite +akka.actor.allow-java-serialization = on +akka.actor.warn-about-java-serializer-usage = off """)) with ImplicitSender with DefaultTimeout diff --git a/akka-remote/src/test/scala/akka/remote/classic/RemoteDeploymentWhitelistSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/RemoteDeploymentWhitelistSpec.scala index 1ad0e7477c..693f89df76 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/RemoteDeploymentWhitelistSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/RemoteDeploymentWhitelistSpec.scala @@ -55,7 +55,7 @@ object RemoteDeploymentWhitelistSpec { val cfg: Config = ConfigFactory.parseString(s""" akka { actor.provider = remote - + remote { use-unsafe-remote-features-without-cluster = on classic.enabled-transports = [ @@ -89,6 +89,9 @@ object RemoteDeploymentWhitelistSpec { /danger-mouse.remote = "akka.test://remote-sys@localhost:12346" } } + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """) def muteSystem(system: ActorSystem): Unit = { diff --git a/akka-remote/src/test/scala/akka/remote/classic/RemoteWatcherSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/RemoteWatcherSpec.scala index 8522ab0190..8b38141bd4 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/RemoteWatcherSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/RemoteWatcherSpec.scala @@ -68,7 +68,8 @@ object RemoteWatcherSpec { } @silent // deprecated -class RemoteWatcherSpec extends AkkaSpec("""akka { +class RemoteWatcherSpec extends AkkaSpec(""" + akka { loglevel = INFO log-dead-letters-during-shutdown = false actor.provider = remote @@ -78,7 +79,11 @@ class RemoteWatcherSpec extends AkkaSpec("""akka { } remote.artery.enabled = off remote.use-unsafe-remote-features-without-cluster = on - }""") with ImplicitSender { + } + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """) with ImplicitSender { import RemoteWatcher._ import RemoteWatcherSpec._ diff --git a/akka-remote/src/test/scala/akka/remote/classic/RemotingSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/RemotingSpec.scala index 02696321ef..ba88ea4421 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/RemotingSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/RemotingSpec.scala @@ -84,6 +84,9 @@ object RemotingSpec { akka { actor.provider = remote actor.serialize-messages = off + # test is using Java serialization and not priority to rewrite + actor.allow-java-serialization = on + actor.warn-about-java-serializer-usage = off remote { use-unsafe-remote-features-without-cluster = on diff --git a/akka-remote/src/test/scala/akka/remote/classic/UntrustedSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/UntrustedSpec.scala index 920b6ce2b5..5074706eb7 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/UntrustedSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/UntrustedSpec.scala @@ -5,6 +5,7 @@ package akka.remote.classic import scala.concurrent.duration._ + import com.typesafe.config.ConfigFactory import akka.actor.Actor import akka.actor.ActorIdentity @@ -24,10 +25,11 @@ import akka.actor.ActorSelection import akka.testkit.TestEvent import akka.event.Logging import akka.testkit.EventFilter +import akka.testkit.JavaSerializable object UntrustedSpec { - final case class IdentifyReq(path: String) - final case class StopChild(name: String) + final case class IdentifyReq(path: String) extends JavaSerializable + final case class StopChild(name: String) extends JavaSerializable class Receptionist(testActor: ActorRef) extends Actor { context.actorOf(Props(classOf[Child], testActor), "child1") @@ -68,6 +70,12 @@ akka.remote.classic.untrusted-mode = on akka.remote.classic.trusted-selection-paths = ["/user/receptionist", ] akka.remote.classic.netty.tcp.port = 0 akka.loglevel = DEBUG # test verifies debug +# test is using Java serialization and not priority to rewrite +akka.actor.allow-java-serialization = on +akka.actor.warn-about-java-serializer-usage = off +akka.actor.serialization-bindings { + "akka.actor.Terminated" = java-test +} """) with ImplicitSender { import UntrustedSpec._ @@ -80,6 +88,12 @@ akka.loglevel = DEBUG # test verifies debug akka.remote.artery.enabled = off akka.remote.warn-about-direct-use = off akka.remote.classic.netty.tcp.port = 0 + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = off + akka.actor.warn-about-java-serializer-usage = off + akka.actor.serialization-bindings { + "akka.actor.Terminated" = java-test + } """)) val address = system.asInstanceOf[ExtendedActorSystem].provider.getDefaultAddress diff --git a/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolSpec.scala index 91c7cf144e..ec8e5fae63 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolSpec.scala @@ -68,6 +68,9 @@ class AkkaProtocolSpec extends AkkaSpec("""akka.actor.provider = remote """) wit } } + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """).withFallback(system.settings.config) val localAddress = Address("test", "testsystem", "testhost", 1234) diff --git a/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolStressTest.scala b/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolStressTest.scala index 3f649c74e2..764b1e264f 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolStressTest.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/transport/AkkaProtocolStressTest.scala @@ -41,7 +41,10 @@ object AkkaProtocolStressTest { } } - """) + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """) object ResendFinal diff --git a/akka-remote/src/test/scala/akka/remote/classic/transport/GenericTransportSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/transport/GenericTransportSpec.scala index dc37a68ac8..7271794e10 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/transport/GenericTransportSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/transport/GenericTransportSpec.scala @@ -20,7 +20,10 @@ import com.github.ghik.silencer.silent abstract class GenericTransportSpec(withAkkaProtocol: Boolean = false) extends AkkaSpec(""" akka.remote.artery.enabled = false - akka.actor.provider = remote + akka.actor.provider = remote + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off """) with DefaultTimeout with ImplicitSender { diff --git a/akka-remote/src/test/scala/akka/remote/classic/transport/SystemMessageDeliveryStressTest.scala b/akka-remote/src/test/scala/akka/remote/classic/transport/SystemMessageDeliveryStressTest.scala index d77b3ab2d5..92a1d9272d 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/transport/SystemMessageDeliveryStressTest.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/transport/SystemMessageDeliveryStressTest.scala @@ -28,6 +28,9 @@ object SystemMessageDeliveryStressTest { remote.artery.enabled = false actor.provider = remote actor.serialize-messages = off + # test is using Java serialization and not priority to rewrite + actor.allow-java-serialization = on + actor.warn-about-java-serializer-usage = off remote.classic { log-remote-lifecycle-events = on diff --git a/akka-remote/src/test/scala/akka/remote/classic/transport/ThrottlerTransportAdapterSpec.scala b/akka-remote/src/test/scala/akka/remote/classic/transport/ThrottlerTransportAdapterSpec.scala index 69b37411e1..781f7e59f5 100644 --- a/akka-remote/src/test/scala/akka/remote/classic/transport/ThrottlerTransportAdapterSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/classic/transport/ThrottlerTransportAdapterSpec.scala @@ -32,7 +32,10 @@ object ThrottlerTransportAdapterSpec { remote.classic.netty.tcp.applied-adapters = ["trttl"] remote.classic.netty.tcp.port = 0 } - """) + # test is using Java serialization and not priority to rewrite + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """) class Echo extends Actor { override def receive = { diff --git a/akka-remote/src/test/scala/akka/remote/serialization/AllowJavaSerializationOffSpec.scala b/akka-remote/src/test/scala/akka/remote/serialization/AllowJavaSerializationOffSpec.scala index 25e4ed24cb..17748f1e81 100644 --- a/akka-remote/src/test/scala/akka/remote/serialization/AllowJavaSerializationOffSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/serialization/AllowJavaSerializationOffSpec.scala @@ -4,16 +4,18 @@ package akka.remote.serialization -import akka.actor.setup.ActorSystemSetup -import akka.actor.{ ActorSystem, BootstrapSetup, ExtendedActorSystem } -import akka.serialization._ -import akka.testkit.{ AkkaSpec, TestKit, TestProbe } -import com.typesafe.config.ConfigFactory -import scala.concurrent.duration._ -import akka.actor.actorRef2Scala import java.util.{ BitSet => ProgrammaticJavaDummy } import java.util.{ Date => SerializableDummy } +import akka.actor.setup.ActorSystemSetup +import akka.actor.ActorSystem +import akka.actor.BootstrapSetup +import akka.actor.ExtendedActorSystem +import akka.serialization._ +import akka.testkit.AkkaSpec +import akka.testkit.TestKit +import com.typesafe.config.ConfigFactory + class ConfigurationDummy class ProgrammaticDummy @@ -30,6 +32,9 @@ object AllowJavaSerializationOffSpec { akka { actor { serialize-messages = off + + allow-java-serialization = on + # this is by default on, but tests are running with off, use defaults here warn-about-java-serializer-usage = on @@ -84,7 +89,7 @@ class AllowJavaSerializationOffSpec # this is by default on, but tests are running with off, use defaults here warn-about-java-serializer-usage = on } - } + } """)), None) @@ -93,6 +98,14 @@ class AllowJavaSerializationOffSpec "addedJavaSerializationSystem", ActorSystemSetup(addedJavaSerializationProgramaticallyButDisabledSettings, addedJavaSerializationSettings)) + private def verifySerialization(sys: ActorSystem, obj: AnyRef): Unit = { + val serialization = SerializationExtension(sys) + val bytes = serialization.serialize(obj).get + val serializer = serialization.findSerializerFor(obj) + val manifest = Serializers.manifestFor(serializer, obj) + serialization.deserialize(bytes, serializer.identifier, manifest).get + } + "Disabling java serialization" should { "throw if passed system to JavaSerializer has allow-java-serialization = off" in { @@ -108,15 +121,17 @@ class AllowJavaSerializationOffSpec } "have replaced java serializer" in { - val p = TestProbe()(dontAllowJavaSystem) // only receiver has the serialization disabled + // allow-java-serialization = on in `system` + val serializer = SerializationExtension(system).findSerializerFor(new ProgrammaticJavaDummy) + serializer.getClass should ===(classOf[JavaSerializer]) - p.ref ! new ProgrammaticJavaDummy - SerializationExtension(system).findSerializerFor(new ProgrammaticJavaDummy).toBinary(new ProgrammaticJavaDummy) - // should not receive this one, it would have been java serialization! - p.expectNoMessage(100.millis) + // should not allow deserialization, it would have been java serialization! + val serializer2 = SerializationExtension(dontAllowJavaSystem).findSerializerFor(new ProgrammaticJavaDummy) + serializer2.getClass should ===(classOf[DisabledJavaSerializer]) + serializer2.identifier should ===(serializer.identifier) - p.ref ! new ProgrammaticDummy - p.expectMsgType[ProgrammaticDummy] + verifySerialization(system, new ProgrammaticDummy) + verifySerialization(dontAllowJavaSystem, new ProgrammaticDummy) } "disable java serialization also for incoming messages if serializer id usually would have found the serializer" in { diff --git a/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala b/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerAllowJavaSerializationSpec.scala similarity index 75% rename from akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala rename to akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerAllowJavaSerializationSpec.scala index 93216a4b84..2c96986631 100644 --- a/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerAllowJavaSerializationSpec.scala @@ -12,15 +12,18 @@ import akka.actor.Props import akka.actor.SupervisorStrategy import akka.remote.DaemonMsgCreate import akka.remote.RemoteScope +import akka.remote.serialization.DaemonMsgCreateSerializerAllowJavaSerializationSpec.ActorWithDummyParameter +import akka.remote.serialization.DaemonMsgCreateSerializerAllowJavaSerializationSpec.MyActorWithParam import akka.routing.FromConfig import akka.routing.RoundRobinPool import akka.serialization.Serialization import akka.serialization.SerializationExtension import akka.testkit.AkkaSpec +import akka.testkit.JavaSerializable import akka.util.unused import com.typesafe.config.ConfigFactory -object DaemonMsgCreateSerializerSpec { +object DaemonMsgCreateSerializerAllowJavaSerializationSpec { trait EmptyActor extends Actor { def receive = Actor.emptyBehavior @@ -32,7 +35,7 @@ object DaemonMsgCreateSerializerSpec { extends EmptyActor } -case class DummyParameter(val inner: String) extends Serializable +case class DummyParameter(val inner: String) extends JavaSerializable private[akka] trait SerializationVerification { self: AkkaSpec => @@ -61,9 +64,15 @@ private[akka] trait SerializationVerification { self: AkkaSpec => } } -class DaemonMsgCreateSerializerSpec extends AkkaSpec with SerializationVerification { +class DaemonMsgCreateSerializerAllowJavaSerializationSpec + extends AkkaSpec(""" + # test is verifying Java serialization + akka.actor.allow-java-serialization = on + akka.actor.warn-about-java-serializer-usage = off + """) + with SerializationVerification { - import DaemonMsgCreateSerializerSpec._ + import DaemonMsgCreateSerializerAllowJavaSerializationSpec._ val ser = SerializationExtension(system) val supervisor = system.actorOf(Props[MyActor], "supervisor") @@ -73,22 +82,6 @@ class DaemonMsgCreateSerializerSpec extends AkkaSpec with SerializationVerificat ser.serializerFor(classOf[DaemonMsgCreate]).getClass should ===(classOf[DaemonMsgCreateSerializer]) } - "serialize and de-serialize DaemonMsgCreate with FromClassCreator" in { - verifySerialization { - DaemonMsgCreate(props = Props[MyActor], deploy = Deploy(), path = "foo", supervisor = supervisor) - } - } - - "serialize and de-serialize DaemonMsgCreate with FromClassCreator, with null parameters for Props" in { - verifySerialization { - DaemonMsgCreate( - props = Props(classOf[MyActorWithParam], null), - deploy = Deploy(), - path = "foo", - supervisor = supervisor) - } - } - "serialize and de-serialize DaemonMsgCreate with function creator" in { verifySerialization { DaemonMsgCreate(props = Props(new MyActor), deploy = Deploy(), path = "foo", supervisor = supervisor) @@ -130,17 +123,6 @@ class DaemonMsgCreateSerializerSpec extends AkkaSpec with SerializationVerificat } } - "allows for mixing serializers with and without manifests for props parameters" in { - verifySerialization { - DaemonMsgCreate( - // parameters should trigger JavaSerializer for the first one and additional protobuf for the second (?) - props = Props(classOf[ActorWithDummyParameter], new DummyParameter("dummy"), system.deadLetters), - deploy = Deploy(), - path = "foo", - supervisor = supervisor) - } - } - } } @@ -150,11 +132,27 @@ class DaemonMsgCreateSerializerNoJavaSerializationSpec extends AkkaSpec(""" akka.actor.serialize-creators=off """) with SerializationVerification { - import DaemonMsgCreateSerializerSpec.MyActor + import DaemonMsgCreateSerializerAllowJavaSerializationSpec.MyActor val supervisor = system.actorOf(Props[MyActor], "supervisor") val ser = SerializationExtension(system) + "serialize and de-serialize DaemonMsgCreate with FromClassCreator" in { + verifySerialization { + DaemonMsgCreate(props = Props[MyActor], deploy = Deploy(), path = "foo", supervisor = supervisor) + } + } + + "serialize and de-serialize DaemonMsgCreate with FromClassCreator, with null parameters for Props" in { + verifySerialization { + DaemonMsgCreate( + props = Props(classOf[MyActorWithParam], null), + deploy = Deploy(), + path = "foo", + supervisor = supervisor) + } + } + "serialize and de-serialize DaemonMsgCreate with Deploy and RouterConfig" in { verifySerialization { val deploy1 = Deploy( @@ -177,4 +175,15 @@ class DaemonMsgCreateSerializerNoJavaSerializationSpec extends AkkaSpec(""" } } + "allows for mixing serializers with and without manifests for props parameters" in { + verifySerialization { + DaemonMsgCreate( + // parameters should trigger JavaSerializer for the first one and additional protobuf for the second (?) + props = Props(classOf[ActorWithDummyParameter], new DummyParameter("dummy"), system.deadLetters), + deploy = Deploy(), + path = "foo", + supervisor = supervisor) + } + } + } diff --git a/akka-remote/src/test/scala/akka/remote/serialization/MiscMessageSerializerSpec.scala b/akka-remote/src/test/scala/akka/remote/serialization/MiscMessageSerializerSpec.scala index 793f0a20aa..e25cbfb518 100644 --- a/akka-remote/src/test/scala/akka/remote/serialization/MiscMessageSerializerSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/serialization/MiscMessageSerializerSpec.scala @@ -9,15 +9,17 @@ import akka.remote.{ RemoteScope, RemoteWatcher } import akka.serialization.SerializationExtension import akka.testkit.AkkaSpec import com.typesafe.config.ConfigFactory - import scala.util.control.NoStackTrace import scala.concurrent.duration._ import java.util.Optional import java.io.NotSerializableException +import java.util.concurrent.TimeoutException +import akka.pattern.AskTimeoutException import akka.{ Done, NotUsed } import akka.remote.routing.RemoteRouterConfig import akka.routing._ +import akka.testkit.JavaSerializable object MiscMessageSerializerSpec { val serializationTestOverrides = @@ -58,12 +60,13 @@ object MiscMessageSerializerSpec { } } - class OtherException(msg: String) extends IllegalArgumentException(msg) { + class OtherException(msg: String) extends IllegalArgumentException(msg) with JavaSerializable { override def equals(other: Any): Boolean = other match { case e: OtherException => e.getMessage == getMessage case _ => false } } + } class MiscMessageSerializerSpec extends AkkaSpec(MiscMessageSerializerSpec.testConfig) { @@ -81,6 +84,12 @@ class MiscMessageSerializerSpec extends AkkaSpec(MiscMessageSerializerSpec.testC "TestException" -> new TestException("err"), "TestExceptionNoStack" -> new TestExceptionNoStack("err2"), "TestException with cause" -> new TestException("err3", new TestException("cause")), + "TimeoutException" -> new TimeoutException("err"), + "AskTimeoutException" -> new AskTimeoutException("err"), + "ThrowableNotSerializableException" -> new ThrowableNotSerializableException( + "orgErr", + classOf[IllegalStateException].getName, + new IllegalStateException("orgErr")), "Status.Success" -> Status.Success("value"), "Status.Failure" -> Status.Failure(new TestException("err")), "Status.Failure JavaSer" -> Status.Failure(new OtherException("exc")), // exc with JavaSerializer @@ -147,7 +156,15 @@ class MiscMessageSerializerSpec extends AkkaSpec(MiscMessageSerializerSpec.testC def verifySerialization(msg: AnyRef): Unit = { val serializer = new MiscMessageSerializer(system.asInstanceOf[ExtendedActorSystem]) - serializer.fromBinary(serializer.toBinary(msg), serializer.manifest(msg)) should ===(msg) + val result = serializer.fromBinary(serializer.toBinary(msg), serializer.manifest(msg)) + msg match { + case t: Throwable => + // typically no equals in exceptions + result.getClass should ===(t.getClass) + result.asInstanceOf[Throwable].getMessage should ===(t.getMessage) + case _ => + result should ===(msg) + } } // Separate tests due to missing equality on ActorInitializationException @@ -200,5 +217,45 @@ class MiscMessageSerializerSpec extends AkkaSpec(MiscMessageSerializerSpec.testC // deserialized.getCause should ===(aiex.getCause) deserialized.getCause should be(null) } + + "serialize and deserialze ActorInitializationException when cause is not serializable" in { + val aiex = ActorInitializationException(ref, "test", new IllegalStateException("err")) + val serializer = new MiscMessageSerializer(system.asInstanceOf[ExtendedActorSystem]) + val deserialized = serializer + .fromBinary(serializer.toBinary(aiex), serializer.manifest(aiex)) + .asInstanceOf[ActorInitializationException] + + deserialized.getCause.getClass should ===(classOf[ThrowableNotSerializableException]) + val cause = deserialized.getCause.asInstanceOf[ThrowableNotSerializableException] + cause.originalMessage should ===("err") + cause.originalClassName should ===(aiex.getCause.getClass.getName) + } + } + + "serialize and deserialze ThrowableNotSerializableException" in { + val notExc = new ThrowableNotSerializableException( + "test", + classOf[IllegalStateException].getName, + new IllegalStateException("test")) + val serializer = new MiscMessageSerializer(system.asInstanceOf[ExtendedActorSystem]) + val deserialized = serializer + .fromBinary(serializer.toBinary(notExc), serializer.manifest(notExc)) + .asInstanceOf[ThrowableNotSerializableException] + + deserialized.originalMessage should ===(notExc.originalMessage) + deserialized.originalClassName should ===(notExc.originalClassName) + deserialized.getCause should ===(null) + } + + "serialize and deserialze Status.Failure with unknown exception" in { + val statusFailure = Status.Failure(new IllegalStateException("test")) + val serializer = new MiscMessageSerializer(system.asInstanceOf[ExtendedActorSystem]) + val deserialized = serializer + .fromBinary(serializer.toBinary(statusFailure), serializer.manifest(statusFailure)) + .asInstanceOf[Status.Failure] + + val e = deserialized.cause.asInstanceOf[ThrowableNotSerializableException] + e.originalClassName should ===(statusFailure.cause.getClass.getName) + e.getCause should ===(null) } } diff --git a/akka-remote/src/test/scala/akka/remote/serialization/PrimitivesSerializationSpec.scala b/akka-remote/src/test/scala/akka/remote/serialization/PrimitivesSerializationSpec.scala index 2921b7b2e5..ca27e301d4 100644 --- a/akka-remote/src/test/scala/akka/remote/serialization/PrimitivesSerializationSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/serialization/PrimitivesSerializationSpec.scala @@ -5,25 +5,26 @@ package akka.remote.serialization import java.nio.ByteBuffer +import java.nio.ByteOrder +import scala.util.Random + +import akka.actor.ExtendedActorSystem +import akka.serialization.BaseSerializer +import akka.serialization.ByteBufferSerializer import akka.serialization.SerializationExtension +import akka.serialization.Serializer import akka.testkit.AkkaSpec import akka.util.ByteString import com.typesafe.config.ConfigFactory -import scala.util.Random -import java.nio.ByteOrder -import akka.serialization.ByteBufferSerializer -import akka.serialization.Serializer - object PrimitivesSerializationSpec { - val serializationTestOverrides = - """ - """ + val serializationTestOverrides = "" val testConfig = ConfigFactory.parseString(serializationTestOverrides).withFallback(AkkaSpec.testConf) } +@deprecated("Moved to akka.serialization.* in akka-actor", "2.6.0") class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.testConfig) { val buffer = { @@ -33,14 +34,26 @@ class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.t } val serialization = SerializationExtension(system) + val extSystem = system.asInstanceOf[ExtendedActorSystem] def verifySerialization(msg: AnyRef): Unit = { + val deprecatedSerializer: BaseSerializer with ByteBufferSerializer = serializerFor(msg) + deprecatedSerializer.fromBinary(deprecatedSerializer.toBinary(msg), None) should ===(msg) + } + + private def serializerFor(msg: AnyRef) = { val serializer = serialization.serializerFor(msg.getClass) - serializer.fromBinary(serializer.toBinary(msg), None) should ===(msg) + // testing the deprecated here + serializer match { + case _: akka.serialization.LongSerializer => new LongSerializer(extSystem) + case _: akka.serialization.IntSerializer => new IntSerializer(extSystem) + case _: akka.serialization.StringSerializer => new StringSerializer(extSystem) + case _: akka.serialization.ByteStringSerializer => new ByteStringSerializer(extSystem) + } } def verifySerializationByteBuffer(msg: AnyRef): Unit = { - val serializer = serialization.serializerFor(msg.getClass).asInstanceOf[Serializer with ByteBufferSerializer] + val serializer = serializerFor(msg).asInstanceOf[Serializer with ByteBufferSerializer] buffer.clear() serializer.toBinary(msg, buffer) buffer.flip() @@ -60,8 +73,7 @@ class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.t .map(_.asInstanceOf[AnyRef]) .foreach { item => s"resolve serializer for value $item" in { - val serializer = SerializationExtension(system) - serializer.serializerFor(item.getClass).getClass should ===(classOf[LongSerializer]) + serializerFor(item).getClass should ===(classOf[LongSerializer]) } s"serialize and de-serialize value $item" in { @@ -73,14 +85,18 @@ class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.t } } + "have right serializer id" in { + // checking because moved to akka-actor + serializerFor(1L.asInstanceOf[AnyRef]).identifier === 18 + } + } "IntSerializer" must { Seq(0, 1, -1, Int.MinValue, Int.MinValue + 1, Int.MaxValue, Int.MaxValue - 1).map(_.asInstanceOf[AnyRef]).foreach { item => s"resolve serializer for value $item" in { - val serializer = SerializationExtension(system) - serializer.serializerFor(item.getClass).getClass should ===(classOf[IntSerializer]) + serializerFor(item).getClass should ===(classOf[IntSerializer]) } s"serialize and de-serialize value $item" in { @@ -91,6 +107,11 @@ class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.t verifySerializationByteBuffer(item) } } + + "have right serializer id" in { + // checking because moved to akka-actor + serializerFor(1L.asInstanceOf[AnyRef]).identifier === 19 + } } "StringSerializer" must { @@ -99,8 +120,7 @@ class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.t .foreach { case (scenario, item) => s"resolve serializer for [$scenario]" in { - val serializer = SerializationExtension(system) - serializer.serializerFor(item.getClass).getClass should ===(classOf[StringSerializer]) + serializerFor(item).getClass should ===(classOf[StringSerializer]) } s"serialize and de-serialize [$scenario]" in { @@ -112,6 +132,11 @@ class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.t } } + "have right serializer id" in { + // checking because moved to akka-actor + serializerFor(1L.asInstanceOf[AnyRef]).identifier === 20 + } + } "ByteStringSerializer" must { @@ -124,8 +149,7 @@ class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.t (ByteString(Array.fill[Byte](1000)(1)) ++ ByteString(Array.fill[Byte](1000)(2)))).foreach { case (scenario, item) => s"resolve serializer for [$scenario]" in { - val serializer = SerializationExtension(system) - serializer.serializerFor(item.getClass).getClass should ===(classOf[ByteStringSerializer]) + serializerFor(item).getClass should ===(classOf[ByteStringSerializer]) } s"serialize and de-serialize [$scenario]" in { @@ -137,6 +161,11 @@ class PrimitivesSerializationSpec extends AkkaSpec(PrimitivesSerializationSpec.t } } + "have right serializer id" in { + // checking because moved to akka-actor + serializerFor(1L.asInstanceOf[AnyRef]).identifier === 21 + } + } } diff --git a/akka-remote/src/test/scala/akka/remote/serialization/SerializationTransportInformationSpec.scala b/akka-remote/src/test/scala/akka/remote/serialization/SerializationTransportInformationSpec.scala index 5d7711dea4..8c22c5416f 100644 --- a/akka-remote/src/test/scala/akka/remote/serialization/SerializationTransportInformationSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/serialization/SerializationTransportInformationSpec.scala @@ -17,6 +17,7 @@ import akka.remote.RARP import akka.serialization.SerializerWithStringManifest import akka.testkit.AkkaSpec import akka.testkit.ImplicitSender +import akka.testkit.JavaSerializable import akka.testkit.TestActors import com.typesafe.config.Config import com.typesafe.config.ConfigFactory @@ -24,7 +25,7 @@ import com.typesafe.config.ConfigFactory object SerializationTransportInformationSpec { final case class TestMessage(from: ActorRef, to: ActorRef) - final case class JavaSerTestMessage(from: ActorRef, to: ActorRef) + final case class JavaSerTestMessage(from: ActorRef, to: ActorRef) extends JavaSerializable class TestSerializer(system: ExtendedActorSystem) extends SerializerWithStringManifest { def identifier: Int = 666 @@ -67,10 +68,8 @@ object SerializationTransportInformationSpec { } abstract class AbstractSerializationTransportInformationSpec(config: Config) - extends AkkaSpec( - config.withFallback( - ConfigFactory.parseString( - """ + extends AkkaSpec(config.withFallback( + ConfigFactory.parseString(""" akka { loglevel = info actor { @@ -82,7 +81,6 @@ abstract class AbstractSerializationTransportInformationSpec(config: Config) } serialization-bindings { "akka.remote.serialization.SerializationTransportInformationSpec$TestMessage" = test - "akka.remote.serialization.SerializationTransportInformationSpec$JavaSerTestMessage" = java } } } diff --git a/akka-remote/src/test/scala/akka/remote/serialization/SystemMessageSerializationSpec.scala b/akka-remote/src/test/scala/akka/remote/serialization/SystemMessageSerializationSpec.scala index 3e330fd32a..85634b1978 100644 --- a/akka-remote/src/test/scala/akka/remote/serialization/SystemMessageSerializationSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/serialization/SystemMessageSerializationSpec.scala @@ -7,6 +7,7 @@ package akka.remote.serialization import akka.actor.{ ActorInitializationException, ExtendedActorSystem, InternalActorRef } import akka.dispatch.sysmsg._ import akka.serialization.SerializationExtension +import akka.testkit.JavaSerializable import akka.testkit.{ AkkaSpec, TestProbe } import com.typesafe.config.ConfigFactory @@ -17,7 +18,7 @@ object SystemMessageSerializationSpec { val testConfig = ConfigFactory.parseString(serializationTestOverrides).withFallback(AkkaSpec.testConf) - class TestException(msg: String) extends RuntimeException(msg) { + class TestException(msg: String) extends RuntimeException(msg) with JavaSerializable { override def equals(other: Any): Boolean = other match { case e: TestException => e.getMessage == getMessage case _ => false @@ -31,7 +32,7 @@ class SystemMessageSerializationSpec extends AkkaSpec(PrimitivesSerializationSpe val testRef = TestProbe().ref.asInstanceOf[InternalActorRef] val testRef2 = TestProbe().ref.asInstanceOf[InternalActorRef] - "ByteStringSerializer" must { + "SystemMessageSerializer" must { Seq( "Create(None)" -> Create(None), "Recreate(ex)" -> Recreate(new TestException("test2")), @@ -61,7 +62,8 @@ class SystemMessageSerializationSpec extends AkkaSpec(PrimitivesSerializationSpe } // ActorInitializationException has no proper equality - "serialize and de-serialize Create(Some(ex))" in { + "serialize and de-serialize Create(Some(exc))" in { + // TestException is JavaSerializable val aiex = ActorInitializationException(testRef, "test", new TestException("test5")) val createMsg = Create(Some(aiex)) val serializer = new SystemMessageSerializer(system.asInstanceOf[ExtendedActorSystem]) @@ -70,7 +72,41 @@ class SystemMessageSerializationSpec extends AkkaSpec(PrimitivesSerializationSpe deserialized.failure.get.getCause should ===(aiex.getCause) deserialized.failure.get.getMessage should ===(aiex.getMessage) deserialized.failure.get.getActor should ===(aiex.getActor) + } + "serialize and de-serialize Create(Some(exc)) when exc not serializable" in { + val aiex = ActorInitializationException(testRef, "test", new IllegalStateException("test6")) + val createMsg = Create(Some(aiex)) + val serializer = new SystemMessageSerializer(system.asInstanceOf[ExtendedActorSystem]) + val deserialized = serializer.fromBinary(serializer.toBinary(createMsg), None).asInstanceOf[Create] + + deserialized.failure.get.getCause.getClass should ===(classOf[ThrowableNotSerializableException]) + val cause = deserialized.failure.get.getCause.asInstanceOf[ThrowableNotSerializableException] + cause.originalMessage should ===("test6") + cause.originalClassName should ===(aiex.getCause.getClass.getName) + } + + "serialize and de-serialize Failed" in { + // TestException is JavaSerializable + val testExc = new TestException("test7") + val createMsg = Failed(testRef, testExc, 1234) + val serializer = new SystemMessageSerializer(system.asInstanceOf[ExtendedActorSystem]) + val deserialized = serializer.fromBinary(serializer.toBinary(createMsg), None).asInstanceOf[Failed] + + deserialized.cause should ===(testExc) + deserialized.child should ===(testRef) + deserialized.uid should ===(1234) + } + + "serialize and de-serialize Failed when exc not serializable" in { + val createMsg = Failed(testRef, new IllegalStateException("test8"), 1234) + val serializer = new SystemMessageSerializer(system.asInstanceOf[ExtendedActorSystem]) + val deserialized = serializer.fromBinary(serializer.toBinary(createMsg), None).asInstanceOf[Failed] + + deserialized.cause.getClass should ===(classOf[ThrowableNotSerializableException]) + val cause = deserialized.cause.asInstanceOf[ThrowableNotSerializableException] + cause.originalMessage should ===("test8") + cause.originalClassName should ===(classOf[IllegalStateException].getName) } } diff --git a/akka-serialization-jackson/src/test/resources/reference.conf b/akka-serialization-jackson/src/test/resources/reference.conf new file mode 100644 index 0000000000..d75292e3c0 --- /dev/null +++ b/akka-serialization-jackson/src/test/resources/reference.conf @@ -0,0 +1,7 @@ +akka { + actor { + serialization-bindings { + "akka.serialization.jackson.CborSerializable" = jackson-cbor + } + } +} diff --git a/akka-serialization-jackson/src/test/scala/akka/serialization/jackson/CborSerializable.scala b/akka-serialization-jackson/src/test/scala/akka/serialization/jackson/CborSerializable.scala new file mode 100644 index 0000000000..02c801ab94 --- /dev/null +++ b/akka-serialization-jackson/src/test/scala/akka/serialization/jackson/CborSerializable.scala @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2019 Lightbend Inc. + */ + +package akka.serialization.jackson + +/** + * Marker trait for serialization with Jackson CBOR in tests + */ +trait CborSerializable diff --git a/akka-serialization-jackson/src/test/scala/akka/serialization/jackson/JacksonSerializerSpec.scala b/akka-serialization-jackson/src/test/scala/akka/serialization/jackson/JacksonSerializerSpec.scala index 6699768ab0..76e773950f 100644 --- a/akka-serialization-jackson/src/test/scala/akka/serialization/jackson/JacksonSerializerSpec.scala +++ b/akka-serialization-jackson/src/test/scala/akka/serialization/jackson/JacksonSerializerSpec.scala @@ -309,7 +309,6 @@ abstract class JacksonSerializerSpec(serializerName: String) "akka.serialization.jackson.ScalaTestMessages$$Event2" = "akka.serialization.jackson.ScalaTestEventMigration" } akka.actor { - allow-java-serialization = off serialization-bindings { "akka.serialization.jackson.ScalaTestMessages$$TestMessage" = $serializerName "akka.serialization.jackson.JavaTestMessages$$TestMessage" = $serializerName diff --git a/akka-testkit/src/main/mima-filters/2.5.x.backwards.excludes b/akka-testkit/src/main/mima-filters/2.5.x.backwards.excludes index ec7da197d5..d38e94defd 100644 --- a/akka-testkit/src/main/mima-filters/2.5.x.backwards.excludes +++ b/akka-testkit/src/main/mima-filters/2.5.x.backwards.excludes @@ -2,3 +2,6 @@ ProblemFilters.exclude[MissingClassProblem]("akka.testkit.JavaTestKit") ProblemFilters.exclude[MissingClassProblem]("akka.testkit.JavaTestKit$*") ProblemFilters.exclude[MissingClassProblem]("akka.testkit.CachingPartialFunction") + +# #22333 Disable Java serialization +ProblemFilters.exclude[MissingClassProblem]("akka.testkit.TestMessageSerializer") diff --git a/akka-testkit/src/main/resources/reference.conf b/akka-testkit/src/main/resources/reference.conf index 160602dcb3..c3123146e3 100644 --- a/akka-testkit/src/main/resources/reference.conf +++ b/akka-testkit/src/main/resources/reference.conf @@ -32,16 +32,17 @@ akka { } actor { + serializers { - test-message-serializer = "akka.testkit.TestMessageSerializer" + java-test = "akka.testkit.TestJavaSerializer" } serialization-identifiers { - "akka.testkit.TestMessageSerializer" = 23 + "akka.testkit.TestJavaSerializer" = 23 } serialization-bindings { - "akka.testkit.JavaSerializable" = java + "akka.testkit.JavaSerializable" = java-test } } } diff --git a/akka-testkit/src/main/scala/akka/testkit/JavaSerializable.scala b/akka-testkit/src/main/scala/akka/testkit/JavaSerializable.scala index 96fc6082ab..e6cf726ee5 100644 --- a/akka-testkit/src/main/scala/akka/testkit/JavaSerializable.scala +++ b/akka-testkit/src/main/scala/akka/testkit/JavaSerializable.scala @@ -7,6 +7,7 @@ package akka.testkit import java.io.Serializable /** - * Marker trait for test messages that will use JavaSerializer. + * Marker trait for test messages that will use Java serialization via + * [[akka.testkit.TestJavaSerializer]] */ trait JavaSerializable extends Serializable diff --git a/akka-testkit/src/main/scala/akka/testkit/TestException.scala b/akka-testkit/src/main/scala/akka/testkit/TestException.scala new file mode 100644 index 0000000000..ebcfa311bc --- /dev/null +++ b/akka-testkit/src/main/scala/akka/testkit/TestException.scala @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2019 Lightbend Inc. + */ + +package akka.testkit + +import scala.util.control.NoStackTrace + +/** + * A predefined exception that can be used in tests. It doesn't include a stack trace. + */ +final case class TestException(message: String) extends RuntimeException(message) with NoStackTrace diff --git a/akka-testkit/src/main/scala/akka/testkit/TestMessageSerializer.scala b/akka-testkit/src/main/scala/akka/testkit/TestJavaSerializer.scala similarity index 84% rename from akka-testkit/src/main/scala/akka/testkit/TestMessageSerializer.scala rename to akka-testkit/src/main/scala/akka/testkit/TestJavaSerializer.scala index 77cbfdcb9c..5e1fd0f58b 100644 --- a/akka-testkit/src/main/scala/akka/testkit/TestMessageSerializer.scala +++ b/akka-testkit/src/main/scala/akka/testkit/TestJavaSerializer.scala @@ -4,9 +4,6 @@ package akka.testkit -/** - * Copyright (C) 2009-2018 Lightbend Inc. - */ import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, ObjectOutputStream } import akka.actor.ExtendedActorSystem @@ -19,11 +16,11 @@ import akka.util.ClassLoaderObjectInputStream * * ``` * akka.actor.serialization-bindings { - * "my.test.AdHocMessage" = test-message-serializer + * "my.test.AdHocMessage" = java-test * } * ``` */ -class TestMessageSerializer(val system: ExtendedActorSystem) extends BaseSerializer { +class TestJavaSerializer(val system: ExtendedActorSystem) extends BaseSerializer { def includeManifest: Boolean = false diff --git a/build.sbt b/build.sbt index cd24836d24..f8cdb8c63c 100644 --- a/build.sbt +++ b/build.sbt @@ -36,41 +36,41 @@ def isScala213: Boolean = System.getProperty("akka.build.scalaVersion", "").star // When this is updated the set of modules in ActorSystem.allModules should also be updated lazy val aggregatedProjects: Seq[ProjectReference] = List[ProjectReference]( - actor, - actorTests, - actorTestkitTyped, - actorTyped, - actorTypedTests, - benchJmh, - benchJmhTyped, - cluster, - clusterMetrics, - clusterSharding, - clusterShardingTyped, - clusterTools, - clusterTyped, - coordination, - discovery, - distributedData, - docs, - jackson, - multiNodeTestkit, - osgi, - persistence, - persistenceQuery, - persistenceShared, - persistenceTck, - persistenceTyped, - protobuf, - remote, - remoteTests, - slf4j, - stream, - streamTestkit, - streamTests, - streamTestsTck, - streamTyped, - testkit) + actor, + actorTests, + actorTestkitTyped, + actorTyped, + actorTypedTests, + benchJmh, + benchJmhTyped, + cluster, + clusterMetrics, + clusterSharding, + clusterShardingTyped, + clusterTools, + clusterTyped, + coordination, + discovery, + distributedData, + docs, + jackson, + multiNodeTestkit, + osgi, + persistence, + persistenceQuery, + persistenceShared, + persistenceTck, + persistenceTyped, + protobuf, + remote, + remoteTests, + slf4j, + stream, + streamTestkit, + streamTests, + streamTestsTck, + streamTyped, + testkit) lazy val root = Project(id = "akka", base = file(".")) .aggregate(aggregatedProjects: _*) @@ -118,7 +118,7 @@ lazy val benchJmhTyped = akkaModule("akka-bench-jmh-typed") .disablePlugins(MimaPlugin, WhiteSourcePlugin, ValidatePullRequest, CopyrightHeaderInPr) lazy val cluster = akkaModule("akka-cluster") - .dependsOn(remote, remoteTests % "test->test", testkit % "test->test") + .dependsOn(remote, remoteTests % "test->test", testkit % "test->test", jackson % "test->test") .settings(Dependencies.cluster) .settings(AutomaticModuleName.settings("akka.cluster")) .settings(OSGi.cluster) @@ -128,7 +128,10 @@ lazy val cluster = akkaModule("akka-cluster") .enablePlugins(MultiNodeScalaTest) lazy val clusterMetrics = akkaModule("akka-cluster-metrics") - .dependsOn(cluster % "compile->compile;test->test;multi-jvm->multi-jvm", slf4j % "test->compile") + .dependsOn( + cluster % "compile->compile;test->test;multi-jvm->multi-jvm", + slf4j % "test->compile", + jackson % "test->test") .settings(OSGi.clusterMetrics) .settings(Dependencies.clusterMetrics) .settings(AutomaticModuleName.settings("akka.cluster.metrics")) @@ -147,7 +150,8 @@ lazy val clusterSharding = akkaModule("akka-cluster-sharding") cluster % "compile->compile;test->test;multi-jvm->multi-jvm", distributedData, persistence % "compile->compile", - clusterTools % "compile->compile;test->test") + clusterTools % "compile->compile;test->test", + jackson % "test->test") .settings(Dependencies.clusterSharding) .settings(AutomaticModuleName.settings("akka.cluster.sharding")) .settings(OSGi.clusterSharding) @@ -156,7 +160,7 @@ lazy val clusterSharding = akkaModule("akka-cluster-sharding") .enablePlugins(MultiNode, ScaladocNoVerificationOfDiagrams) lazy val clusterTools = akkaModule("akka-cluster-tools") - .dependsOn(cluster % "compile->compile;test->test;multi-jvm->multi-jvm", coordination) + .dependsOn(cluster % "compile->compile;test->test;multi-jvm->multi-jvm", coordination, jackson % "test->test") .settings(Dependencies.clusterTools) .settings(AutomaticModuleName.settings("akka.cluster.tools")) .settings(OSGi.clusterTools) @@ -165,7 +169,7 @@ lazy val clusterTools = akkaModule("akka-cluster-tools") .enablePlugins(MultiNode, ScaladocNoVerificationOfDiagrams) lazy val distributedData = akkaModule("akka-distributed-data") - .dependsOn(cluster % "compile->compile;test->test;multi-jvm->multi-jvm") + .dependsOn(cluster % "compile->compile;test->test;multi-jvm->multi-jvm", jackson % "test->test") .settings(Dependencies.distributedData) .settings(AutomaticModuleName.settings("akka.cluster.ddata")) .settings(OSGi.distributedData) @@ -303,7 +307,14 @@ lazy val protobuf = akkaModule("akka-protobuf") .disablePlugins(MimaPlugin) lazy val remote = akkaModule("akka-remote") - .dependsOn(actor, stream, actorTests % "test->test", testkit % "test->test", streamTestkit % "test", protobuf) + .dependsOn( + actor, + stream, + actorTests % "test->test", + testkit % "test->test", + streamTestkit % "test", + protobuf, + jackson % "test->test") .settings(Dependencies.remote) .settings(AutomaticModuleName.settings("akka.remote")) .settings(OSGi.remote) @@ -311,7 +322,12 @@ lazy val remote = akkaModule("akka-remote") .settings(parallelExecution in Test := false) lazy val remoteTests = akkaModule("akka-remote-tests") - .dependsOn(actorTests % "test->test", remote % "test->test", streamTestkit % "test", multiNodeTestkit) + .dependsOn( + actorTests % "test->test", + remote % "test->test", + streamTestkit % "test", + multiNodeTestkit, + jackson % "test->test") .settings(Dependencies.remoteTests) .settings(Protobuf.settings) .settings(parallelExecution in Test := false) @@ -385,7 +401,9 @@ lazy val persistenceTyped = akkaModule("akka-persistence-typed") persistence % "compile->compile;test->test", persistenceQuery % "test", actorTypedTests % "test->test", - actorTestkitTyped % "compile->compile;test->test") + actorTestkitTyped % "compile->compile;test->test", + jackson % "test->test") + .settings(javacOptions += "-parameters") // for Jackson .settings(Dependencies.persistenceShared) .settings(AutomaticModuleName.settings("akka.persistence.typed")) .settings(OSGi.persistenceTyped) @@ -401,7 +419,8 @@ lazy val clusterTyped = akkaModule("akka-cluster-typed") protobuf, actorTestkitTyped % "test->test", actorTypedTests % "test->test", - remoteTests % "test->test") + remoteTests % "test->test", + jackson % "test->test") .settings(AutomaticModuleName.settings("akka.cluster.typed")) .configs(MultiJvm) .enablePlugins(MultiNodeScalaTest) @@ -414,7 +433,9 @@ lazy val clusterShardingTyped = akkaModule("akka-cluster-sharding-typed") actorTestkitTyped % "test->test", actorTypedTests % "test->test", persistenceTyped % "test->test", - remoteTests % "test->test") + remoteTests % "test->test", + jackson % "test->test") + .settings(javacOptions += "-parameters") // for Jackson .settings(AutomaticModuleName.settings("akka.cluster.sharding.typed")) // To be able to import ContainerFormats.proto .settings(Protobuf.importPath := Some(baseDirectory.value / ".." / "akka-remote" / "src" / "main" / "protobuf"))