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 9ab93ed974..f510f848f8 100644 --- a/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala @@ -4,7 +4,7 @@ package akka.serialization -import akka.testkit.AkkaSpec +import akka.testkit.{ AkkaSpec, EventFilter } import akka.actor._ import java.io._ import akka.dispatch.Await @@ -179,9 +179,17 @@ class SerializeSpec extends AkkaSpec(SerializeSpec.config) { ser.serializerFor(classOf[ExtendedPlainMessage]).getClass must be(classOf[TestSerializer]) } - "throw exception for message with several bindings" in { - intercept[java.io.NotSerializableException] { - ser.serializerFor(classOf[Both]) + "give warning for message with several bindings" in { + EventFilter.warning(start = "Multiple serializers found", occurrences = 1) intercept { + ser.serializerFor(classOf[Both]).getClass must be(classOf[TestSerializer]) + } + } + + "resolve serializer in the order of the bindings" in { + ser.serializerFor(classOf[A]).getClass must be(classOf[JavaSerializer]) + ser.serializerFor(classOf[B]).getClass must be(classOf[TestSerializer]) + EventFilter.warning(start = "Multiple serializers found", occurrences = 1) intercept { + ser.serializerFor(classOf[C]).getClass must be(classOf[JavaSerializer]) } } diff --git a/akka-actor/src/main/resources/reference.conf b/akka-actor/src/main/resources/reference.conf index 4e6c42c704..ce9bf684e8 100644 --- a/akka-actor/src/main/resources/reference.conf +++ b/akka-actor/src/main/resources/reference.conf @@ -272,8 +272,8 @@ akka { } # Class to Serializer binding. You only need to specify the name of an interface - # or abstract base class of the messages. In case of ambiguity it is - # using the most specific configured class, throwing an exception otherwise. + # or abstract base class of the messages. In case of ambiguity it is using the + # most specific configured class, or giving a warning and choosing the “first” one. # # To disable one of the default serializers, assign its class to "none", like # "java.io.Serializable" = none diff --git a/akka-actor/src/main/scala/akka/serialization/Serialization.scala b/akka-actor/src/main/scala/akka/serialization/Serialization.scala index 3e86de6c1c..b26adcfc36 100644 --- a/akka-actor/src/main/scala/akka/serialization/Serialization.scala +++ b/akka-actor/src/main/scala/akka/serialization/Serialization.scala @@ -129,19 +129,20 @@ class Serialization(val system: ExtendedActorSystem) extends Extension { def unique(cs: Seq[Class[_]], ser: Set[Serializer]): Boolean = (cs forall (_ isAssignableFrom cs(0))) || ser.size == 1 val possible = bindings filter { _._1 isAssignableFrom clazz } - possible.size match { + val ser = possible.size match { case 0 ⇒ throw new NotSerializableException("No configured serialization-bindings for class [%s]" format clazz.getName) case x if x == 1 || unique(possible map (_._1), possible.map(_._2)(scala.collection.breakOut)) ⇒ - val ser = possible(0)._2 - serializerMap.putIfAbsent(clazz, ser) match { - case null ⇒ - log.debug("Using serializer[{}] for message [{}]", ser.getClass.getName, clazz.getName) - ser - case some ⇒ some - } + possible(0)._2 case _ ⇒ - throw new NotSerializableException("Multiple serializers found for " + clazz + ": " + possible) + log.warning("Multiple serializers found for " + clazz + ", choosing first: " + possible) + possible(0)._2 + } + serializerMap.putIfAbsent(clazz, ser) match { + case null ⇒ + log.debug("Using serializer[{}] for message [{}]", ser.getClass.getName, clazz.getName) + ser + case some ⇒ some } case ser ⇒ ser } diff --git a/akka-docs/java/serialization.rst b/akka-docs/java/serialization.rst index dad2174f91..e44d69f162 100644 --- a/akka-docs/java/serialization.rst +++ b/akka-docs/java/serialization.rst @@ -37,8 +37,7 @@ 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, an exception will be thrown during -serialization. +and neither is a subtype of the other, a warning will be issued. Akka provides serializers for :class:`java.io.Serializable` and `protobuf `_ diff --git a/akka-docs/scala/serialization.rst b/akka-docs/scala/serialization.rst index ec0f4ca706..4735548140 100644 --- a/akka-docs/scala/serialization.rst +++ b/akka-docs/scala/serialization.rst @@ -37,8 +37,7 @@ 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, an exception will be thrown during -serialization. +and neither is a subtype of the other, a warning will be issued Akka provides serializers for :class:`java.io.Serializable` and `protobuf `_ diff --git a/akka-remote/src/main/resources/reference.conf b/akka-remote/src/main/resources/reference.conf index a8854fc9df..017b531faa 100644 --- a/akka-remote/src/main/resources/reference.conf +++ b/akka-remote/src/main/resources/reference.conf @@ -5,20 +5,18 @@ # This the reference config file has all the default settings. # Make your edits/overrides in your application.conf. +# comments above akka.actor settings left out where they are already in akka- +# actor.jar, because otherwise they would be repeated in config rendering. + akka { actor { - # Entries for pluggable serializers and their bindings. serializers { proto = "akka.serialization.ProtobufSerializer" } - # Class to Serializer binding. You only need to specify the name of an interface - # or abstract base class of the messages. In case of ambiguity it is - # using the most specific configured class, giving an error if two mappings are found - # which cannot be decided by sub-typing relation. serialization-bindings { # Since com.google.protobuf.Message does not extend Serializable but GeneratedMessage # does, need to use the more specific one here in order to avoid ambiguity