Adding support for having method parameters individually serialized and deserialized using its own serializer, closing ticket #765
This commit is contained in:
parent
c6297faa6f
commit
2cf64bccae
3 changed files with 34 additions and 8 deletions
|
|
@ -10,6 +10,8 @@ import akka.dispatch.{ MessageDispatcher, Dispatchers, Future, FutureTimeoutExce
|
|||
import java.lang.reflect.{ InvocationTargetException, Method, InvocationHandler, Proxy }
|
||||
import akka.util.{ Duration }
|
||||
import java.util.concurrent.atomic.{ AtomicReference ⇒ AtomVar }
|
||||
import akka.serialization.Serialization
|
||||
import com.sun.xml.internal.ws.developer.MemberSubmissionAddressing.Validation
|
||||
|
||||
//TODO Document this class, not only in Scaladoc, but also in a dedicated typed-actor.rst, for both java and scala
|
||||
/**
|
||||
|
|
@ -87,16 +89,35 @@ object TypedActor {
|
|||
}
|
||||
} catch { case i: InvocationTargetException ⇒ throw i.getTargetException }
|
||||
|
||||
private def writeReplace(): AnyRef = new SerializedMethodCall(method.getDeclaringClass, method.getName, method.getParameterTypes, parameters)
|
||||
private def writeReplace(): AnyRef = {
|
||||
val serializedParameters: Array[(Array[Byte],String)] = parameters match {
|
||||
case null => null
|
||||
case a if a.length == 0 => Array[(Array[Byte],String)]()
|
||||
case a => a.map( {
|
||||
case null => null
|
||||
case value => Serialization.serializerFor(value.getClass).fold(throw _, s => (s.toBinary(value), s.getClass.getName))
|
||||
})
|
||||
}
|
||||
new SerializedMethodCall(method.getDeclaringClass, method.getName, method.getParameterTypes, serializedParameters)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the serialized form of a MethodCall, uses readResolve and writeReplace to marshall the call
|
||||
*/
|
||||
case class SerializedMethodCall(ownerType: Class[_], methodName: String, parameterTypes: Array[Class[_]], parameterValues: Array[AnyRef]) {
|
||||
case class SerializedMethodCall(ownerType: Class[_], methodName: String, parameterTypes: Array[Class[_]], serializedParameters: Array[(Array[Byte],String)]) {
|
||||
//TODO implement writeObject and readObject to serialize
|
||||
//TODO Possible optimization is to special encode the parameter-types to conserve space
|
||||
private def readResolve(): AnyRef = MethodCall(ownerType.getDeclaredMethod(methodName, parameterTypes: _*), parameterValues)
|
||||
private def readResolve(): AnyRef = {
|
||||
MethodCall(ownerType.getDeclaredMethod(methodName, parameterTypes: _*), serializedParameters match {
|
||||
case null => null
|
||||
case a if a.length == 0 => Array[AnyRef]()
|
||||
case a => a.map( {
|
||||
case null => null
|
||||
case (bytes, serializerFQN) => Serialization.serializerOf(serializerFQN).fold(throw _, _.fromBinary(bytes))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import akka.config.Config
|
|||
import akka.config.Config._
|
||||
import akka.actor.{ ActorRef, Actor }
|
||||
import akka.AkkaException
|
||||
import akka.util.ReflectiveAccess
|
||||
|
||||
|
||||
case class NoSerializerFoundException(m: String) extends AkkaException(m)
|
||||
|
|
@ -40,6 +41,12 @@ object Serialization {
|
|||
case Left(e) => Left(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to load the specified Serializer by the FQN
|
||||
*/
|
||||
def serializerOf(serializerFQN: String): Either[Exception, Serializer] =
|
||||
createInstance(serializerFQN, ReflectiveAccess.emptyParams, ReflectiveAccess.emptyArguments)
|
||||
|
||||
private def serializerForBestMatchClass(cl: Class[_]): Either[Exception, Serializer] = {
|
||||
if (bindings.isEmpty)
|
||||
Left(NoSerializerFoundException("No mapping serializer found for " + cl))
|
||||
|
|
@ -51,11 +58,7 @@ object Serialization {
|
|||
case _ ⇒ false
|
||||
}
|
||||
} map {
|
||||
case (_, ser) ⇒
|
||||
getClassFor(ser) match {
|
||||
case Right(s) ⇒ Right(s.newInstance.asInstanceOf[Serializer])
|
||||
case _ ⇒ Left(new Exception("Error instantiating " + ser))
|
||||
}
|
||||
case (_, ser) ⇒ serializerOf(ser)
|
||||
} getOrElse Left(NoSerializerFoundException("No mapping serializer found for " + cl))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import java.net.InetSocketAddress
|
|||
object ReflectiveAccess {
|
||||
|
||||
val loader = getClass.getClassLoader
|
||||
val emptyParams: Array[Class[_]] = Array()
|
||||
val emptyArguments: Array[AnyRef] = Array()
|
||||
|
||||
/**
|
||||
* Reflective access to the Cluster module.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue