
java.lang.reflect.Proxy
API in that the RProxy also allows the trapping of unhandled exceptions raised within the proxied object.
Such exceptions may be directed to the RProxy's InvocationHandler.trapException method.
The API for the RProxy is largely carried over from that of the java.lang.reflect.Proxy
package.
interface Foo)
to dynamically incorporate a trapping metalevel for the object. In our example we will proxy an
Object implementing the Foo interface below.
We can attach a proxy dynamically for the implementation of this interface at runtime.
The proxy provides a metalevel whereby all invocations on the object's presented
interface (i.e. invocations on the interface Foo) are dispatched
through the proxy's
public interface Foo {
public void bar();
}
invoke method.
This allows code to be dynamically added before and after method implementations.
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable
{
Object result;
try {
System.out.println("***METALEVEL before method: "
+ m.getName());
result = m.invoke(obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException
("unexpected invocation exception: " +
e.getMessage());
} finally {
System.out.println("***METALEVEL after method: "
+ m.getName());
}
return result;
}
Proxy implementors using the RProxy are free to provide their own implementations for the
invoke method as long as the proxy object implements the InvocationHandler interface
(see the above example implementation of the invoke method from the file TProxy.java).
The proxy also traps any exceptions raised from the implementation of the proxied object's interface.
Exceptions are directed to the trapException method of the InvocationHandler interface
implemented within the proxy.
So in the implementation of the
public void trapException(Method m, Exception e) {
System.out.println
("***METALEVEL - TRAPPED EXCEPTION : " + m);
System.out.println(e);
}
Foo interface below the proxy will trap the division by zero exception
at the above trapException method implemented in the proxy. The code below provides the implementation
of the Foo interface and is the Object that we are to proxy.
To invoke an object's methods via the proxy dynamically creating the metalevel (i.e. the
public class FooImpl implements Foo {
public void bar() {
System.out.println("CALLED bar()!");
System.out.print("Doing something naughty");
System.out.println(" to raise an exception 10/0: "
+ 10/0);
}
}
invoke
and trapException points) at runtime for the specified object, use the code,
whereas normally the following code is used to run the implementation of Foo without the proxy.
Foo foo = (Foo) TProxy.newInstance(new FooImpl());
foo.bar();
Foo foo = new FooImpl();
foo.bar();
In the case of executing bar() with the proxy pre and post execution of the method will be trapped by the proxy's invoke method allowing specified additional processing to be placed dynamically at runtime at these points. Proxies are also useful for debug tracing and program profiling as the execution path of the program may be easily logged by the proxy. When the code reaches an exception the proxy traps it and prints a message indicating the exception raised and in which delegated method.
Compare this to the non-proxy invocation of bar(). In this case no trapping of pre and post method execution or exceptions is available.