I'm trying to implement a proxy pattern so that I can swap out an underlying instance dynamically under the covers when necessary along with an extension method to trigger the swap. I've implemented this in Java before, but I'm having trouble with it in Scala.
This is my scenario:
class Client { ...library code... }
trait DynamicClient extends Client {
def swap: Client
}
class Provider extends Provider[DynamicClient] {
def get():DynamicClient {
java.lang.reflect.Proxy.newProxyInstance(
classOf[DynamicClient].getClassLoader,
Array(classOf[DynamicClient]),
handler)
.asInstanceOf[DynamicClient]
}
}
class DynamicClientHandler extends java.lang.reflect.InvocationHandler {
var client:Client = createNewClient()
def swap(): {
client = createNewClient()
client
}
def createNewClient():Client: { ... }
def invoke(proxy: AnyRef, method: java.lang.reflect.Method, args: Array[AnyRef]): AnyRef = {
method.getDeclaringClass match {
case dyn if dyn == classOf[DynamicClient] => swap()
case _ => method.invoke(client, args: _*)
}
}
}
Now the problem: When I invoke methods from the DynamicClient or Object on the Proxy object, they work just fine.
val dynamicClient = injector.instanceOf[DynamicClient]
val initial = dynamicClient.client
val client = dynamicClient.swap()
val dynamicClient.toString // "Client@1234" (Object impl of toString via client instance)
assert(client != initial) //passes just fine, the underlying client is re-initialized
Any call to a method belonging to the Client class fails before it ever gets to the Invocation Handler.
//Both of the following scenarios fail independently of the other
//ERROR:
dynamicClient.asInstanceOf[Client]
//ERROR:
dynamicClient.doSomeClientMethod()
With this exception trace:
java.lang.ClassCastException: com.sun.proxy.$Proxy22 cannot be cast to Client
Why do I get this cast exception? Is there a better way to handle proxy invocation handling in Scala vs. the Java way?
Aucun commentaire:
Enregistrer un commentaire