tone it down: just a Warning in case of ambiguous serializers

This commit is contained in:
Roland 2012-02-07 15:51:41 +01:00
parent 8b9f1caf67
commit 224ce7f773
6 changed files with 29 additions and 24 deletions

View file

@ -4,7 +4,7 @@
package akka.serialization package akka.serialization
import akka.testkit.AkkaSpec import akka.testkit.{ AkkaSpec, EventFilter }
import akka.actor._ import akka.actor._
import java.io._ import java.io._
import akka.dispatch.Await import akka.dispatch.Await
@ -179,9 +179,17 @@ class SerializeSpec extends AkkaSpec(SerializeSpec.config) {
ser.serializerFor(classOf[ExtendedPlainMessage]).getClass must be(classOf[TestSerializer]) ser.serializerFor(classOf[ExtendedPlainMessage]).getClass must be(classOf[TestSerializer])
} }
"throw exception for message with several bindings" in { "give warning for message with several bindings" in {
intercept[java.io.NotSerializableException] { EventFilter.warning(start = "Multiple serializers found", occurrences = 1) intercept {
ser.serializerFor(classOf[Both]) 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])
} }
} }

View file

@ -272,8 +272,8 @@ akka {
} }
# Class to Serializer binding. You only need to specify the name of an interface # 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 # or abstract base class of the messages. In case of ambiguity it is using the
# using the most specific configured class, throwing an exception otherwise. # 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 # To disable one of the default serializers, assign its class to "none", like
# "java.io.Serializable" = none # "java.io.Serializable" = none

View file

@ -129,20 +129,21 @@ class Serialization(val system: ExtendedActorSystem) extends Extension {
def unique(cs: Seq[Class[_]], ser: Set[Serializer]): Boolean = (cs forall (_ isAssignableFrom cs(0))) || ser.size == 1 def unique(cs: Seq[Class[_]], ser: Set[Serializer]): Boolean = (cs forall (_ isAssignableFrom cs(0))) || ser.size == 1
val possible = bindings filter { _._1 isAssignableFrom clazz } val possible = bindings filter { _._1 isAssignableFrom clazz }
possible.size match { val ser = possible.size match {
case 0 case 0
throw new NotSerializableException("No configured serialization-bindings for class [%s]" format clazz.getName) 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)) case x if x == 1 || unique(possible map (_._1), possible.map(_._2)(scala.collection.breakOut))
val ser = possible(0)._2 possible(0)._2
case _
log.warning("Multiple serializers found for " + clazz + ", choosing first: " + possible)
possible(0)._2
}
serializerMap.putIfAbsent(clazz, ser) match { serializerMap.putIfAbsent(clazz, ser) match {
case null case null
log.debug("Using serializer[{}] for message [{}]", ser.getClass.getName, clazz.getName) log.debug("Using serializer[{}] for message [{}]", ser.getClass.getName, clazz.getName)
ser ser
case some some case some some
} }
case _
throw new NotSerializableException("Multiple serializers found for " + clazz + ": " + possible)
}
case ser ser case ser ser
} }

View file

@ -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 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 one of which all other candidates are superclasses. If this condition cannot be
met, because e.g. ``java.io.Serializable`` and ``MyOwnSerializable`` both apply 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 and neither is a subtype of the other, a warning will be issued.
serialization.
Akka provides serializers for :class:`java.io.Serializable` and `protobuf Akka provides serializers for :class:`java.io.Serializable` and `protobuf
<http://code.google.com/p/protobuf/>`_ <http://code.google.com/p/protobuf/>`_

View file

@ -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 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 one of which all other candidates are superclasses. If this condition cannot be
met, because e.g. ``java.io.Serializable`` and ``MyOwnSerializable`` both apply 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 and neither is a subtype of the other, a warning will be issued
serialization.
Akka provides serializers for :class:`java.io.Serializable` and `protobuf Akka provides serializers for :class:`java.io.Serializable` and `protobuf
<http://code.google.com/p/protobuf/>`_ <http://code.google.com/p/protobuf/>`_

View file

@ -5,20 +5,18 @@
# This the reference config file has all the default settings. # This the reference config file has all the default settings.
# Make your edits/overrides in your application.conf. # 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 { akka {
actor { actor {
# Entries for pluggable serializers and their bindings.
serializers { serializers {
proto = "akka.serialization.ProtobufSerializer" 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 { serialization-bindings {
# Since com.google.protobuf.Message does not extend Serializable but GeneratedMessage # 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 # does, need to use the more specific one here in order to avoid ambiguity