REMOTE + TYPEDACTOR: Implement support for automagically making TypedActor proxies remote/local when sent in messages
(No description)
Leave a comment
on 2011-10-07 09:17 *
By viktorklang
Summary changed from Implement support for automagically making TypedActor proxies remote/local when sent in messages to REMOTE + TYPEDACTOR: Implement support for automagically making TypedActor proxies remote/local when sent in messages
on 2011-11-22 14:14 *
By viktorklang
Profit, this works:
diff --git a/akka-actor/src/main/scala/akka/actor/TypedActor.scala b/akka-actor/src/main/scala/akka/actor/TypedActor.scala
index c0ecbb5..0e4e208 100644
--- a/akka-actor/src/main/scala/akka/actor/TypedActor.scala
+++ b/akka-actor/src/main/scala/akka/actor/TypedActor.scala
@@ -267,6 +267,18 @@ trait TypedActorFactory { this: ActorRefFactory ⇒
class TypedActor(val settings: ActorSystem.Settings, var ser: Serialization) {
import TypedActor.MethodCall
+
+ /**
+ * Autoinjected interface to support transparent serialization of TypedActor proxy references
+ /
+ trait TypedActorSerialization {
+ @throws(classOf[java.io.ObjectStreamException])
+ def writeReplace(): AnyRef
+ }
+
+ //Cache this for profit
+ private final val serializationInterface = Array(classOf[TypedActorSerialization])
+
/*
@@ -316,7 +328,7 @@ class TypedActor(val settings: ActorSystem.Settings, var ser: Serialization) {
case Props.`defaultTimeout` ⇒ settings.ActorTimeout
case x ⇒ x
}
- val proxy: T = Proxy.newProxyInstance(loader, interfaces, new TypedActorInvocationHandler(actorVar, timeout)).asInstanceOf[T]
+ val proxy: T = Proxy.newProxyInstance(loader, interfaces ++ serializationInterface , new TypedActorInvocationHandler(actorVar, timeout)).asInstanceOf[T]
proxyVar.set(proxy) // Chicken and egg situation we needed to solve, set the proxy so that we can set the self-reference inside each receive
val ref = if (name.isDefined) supervisor.actorOf(props, name.get) else supervisor.actorOf(props)
actorVar.set(ref) //Make sure the InvocationHandler gets ahold of the actor reference, this is not a problem since the proxy hasn't escaped this method yet
@@ -361,9 +373,10 @@ class TypedActor(val settings: ActorSystem.Settings, var ser: Serialization) {
def actor = actorVar.get
def invoke(proxy: AnyRef, method: Method, args: Array[AnyRef]): AnyRef = method.getName match {
- case "toString" ⇒ actor.toString
- case "equals" ⇒ (args.length == 1 && (proxy eq args(0)) || actor == getActorRefFor(args(0))).asInstanceOf[AnyRef] //Force boxing of the boolean
- case "hashCode" ⇒ actor.hashCode.asInstanceOf[AnyRef]
+ case "toString" ⇒ actor.toString
+ case "equals" ⇒ (args.length == 1 && (proxy eq args(0)) || actor == getActorRefFor(args(0))).asInstanceOf[AnyRef] //Force boxing of the boolean
+ case "hashCode" ⇒ actor.hashCode.asInstanceOf[AnyRef]
+ case "writeReplace" if (args eq null) && args.length == 0 ⇒ REPLACE WITH PLACEHOLDER THAT CONTAINS THE INTERFACES AND A SERIALIZED ACTOR REF THAT WHEN READRESOLVED DOES THE SHIT
case _ ⇒
MethodCall(ser, method, args) match {
case m if m.isOneWay ⇒ actor ! m; null //Null return value
diff --git a/akka-actor/src/main/scala/akka/actor/TypedActor.scala b/akka-actor/src/main/scala/akka/actor/TypedActor.scala
index c0ecbb5..0e4e208 100644
--- a/akka-actor/src/main/scala/akka/actor/TypedActor.scala
+++ b/akka-actor/src/main/scala/akka/actor/TypedActor.scala
@@ -267,6 +267,18 @@ trait TypedActorFactory { this: ActorRefFactory ⇒
class TypedActor(val settings: ActorSystem.Settings, var ser: Serialization) {
import TypedActor.MethodCall
+
+ /**
+ * Autoinjected interface to support transparent serialization of TypedActor proxy references
+ /
+ trait TypedActorSerialization {
+ @throws(classOf[java.io.ObjectStreamException])
+ def writeReplace(): AnyRef
+ }
+
+ //Cache this for profit
+ private final val serializationInterface = Array(classOf[TypedActorSerialization])
+
/*
- Stops the underlying ActorRef for the supplied TypedActor proxy, if any, returns whether it could stop it or not
@@ -316,7 +328,7 @@ class TypedActor(val settings: ActorSystem.Settings, var ser: Serialization) {
case Props.`defaultTimeout` ⇒ settings.ActorTimeout
case x ⇒ x
}
- val proxy: T = Proxy.newProxyInstance(loader, interfaces, new TypedActorInvocationHandler(actorVar, timeout)).asInstanceOf[T]
+ val proxy: T = Proxy.newProxyInstance(loader, interfaces ++ serializationInterface , new TypedActorInvocationHandler(actorVar, timeout)).asInstanceOf[T]
proxyVar.set(proxy) // Chicken and egg situation we needed to solve, set the proxy so that we can set the self-reference inside each receive
val ref = if (name.isDefined) supervisor.actorOf(props, name.get) else supervisor.actorOf(props)
actorVar.set(ref) //Make sure the InvocationHandler gets ahold of the actor reference, this is not a problem since the proxy hasn't escaped this method yet
@@ -361,9 +373,10 @@ class TypedActor(val settings: ActorSystem.Settings, var ser: Serialization) {
def actor = actorVar.get
def invoke(proxy: AnyRef, method: Method, args: Array[AnyRef]): AnyRef = method.getName match {
- case "toString" ⇒ actor.toString
- case "equals" ⇒ (args.length == 1 && (proxy eq args(0)) || actor == getActorRefFor(args(0))).asInstanceOf[AnyRef] //Force boxing of the boolean
- case "hashCode" ⇒ actor.hashCode.asInstanceOf[AnyRef]
+ case "toString" ⇒ actor.toString
+ case "equals" ⇒ (args.length == 1 && (proxy eq args(0)) || actor == getActorRefFor(args(0))).asInstanceOf[AnyRef] //Force boxing of the boolean
+ case "hashCode" ⇒ actor.hashCode.asInstanceOf[AnyRef]
+ case "writeReplace" if (args eq null) && args.length == 0 ⇒ REPLACE WITH PLACEHOLDER THAT CONTAINS THE INTERFACES AND A SERIALIZED ACTOR REF THAT WHEN READRESOLVED DOES THE SHIT
case _ ⇒
MethodCall(ser, method, args) match {
case m if m.isOneWay ⇒ actor ! m; null //Null return value
on 2012-01-19 02:45 *
By viktorklang
Assigned to set to viktorklang
Status changed from New to Accepted
Updating tickets (#520, #852, #857, #874, #935, #950, #1364, #1508, #1542, #1559, #1734, #1744, #1755, #1782, #1812, #1824, #1831, #1858, #1871, #1880, #1886, #1892, #1896, #1899, #1929, #1930, #1950, #1952, #1953, #1962, #1966, #1969, #1972, #1973, #1977, #1978, #1986, #1988, #1993, #1999, #2000, #2003, #2005, #2006, #2015, #2016, #2019, #2021, #2022, #2023, #2024, #2025, #2029, #2031, #2032, #2036, #2046, #2048, #2051, #2055, #2059, #2061, #2062, #2064, #2065, #2068, #2072, #2074, #2076, #2078, #2079, #2085, #2087, #2088, #2089, #2090, #2091, #2092, #2093, #2095, #2098, #2099, #2100, #2101, #2102, #2119, #2129, #2134, #2135, #2136, #2144, #2147, #2148, #2156, #2166, #2168, #2172, #2174, #2178, #2183)