Search
Calendar
April 2024
S M T W T F S
« Sep    
 123456
78910111213
14151617181920
21222324252627
282930  
Your widget title
Archives

Posts Tagged ‘Proxy’

PostHeaderIcon Proxying without AOP

Case

You have many operations to execute on each method call. At first glance, this is the perfect case to write an AOP mechanism (such as in this example Transaction Management with Spring in AOP).
Anyway, sometimes AOP won’t work, for instance when OSGi jars and their inherent opacity prevent you from cutting method calls.
Yet, I suggest here a workaround. In the following example, we log each method call, with inputs and outputs (returned values ; you can improve the code sample to handle raised exceptions, too).

Solution

Starting Point

Let’s consider an interface MyServiceInterface. It is actually implemented by MyServiceLogic.
An EJB MyServiceBean has a field of type MyServiceInterface, and the concrete implementation is of type MyServiceLogic.
Without proxying nor AOP, the EJB should look like:

public MyServiceBean extends ... implements ...{
  private MyServiceInterface myServiceLogic;

   public MyServiceBean() {
        this.myServiceLogic = new MyServiceLogic();
   }
}    

We have to insert a proxy in this piece of code.

Generic Code

The following piece of code is technical and generic, which means it can be used in any business context. We use the class InvocationHandler, that is part of package java.lang.reflect since JDK 1.4
(in order to keep the code light, we don’t handle the exceptions ; consider adding them as an exercise 😉 )

public class GenericInvocationHandler<T> implements InvocationHandler {
    private static final String NULL = "<null>";

    private static final Logger LOGGER = Logger.getLogger(GenericInvocationHandler.class);

    private final T invocable;

    public GenericInvocationHandler(T _invocable) {
        this.invocable = _invocable;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        final Object answer;
        LOGGER.info(">>> " + invocable.getClass().getSimpleName() + "." + method.getName() + " was called with args: " + arrayToString(args));
        answer = method.invoke(invocable, args);
        // TODO handle throwables
        if (method.getReturnType().equals(Void.class)) {
            LOGGER.info("<<< (was a void method) ");
        } else {
            LOGGER.info("<<< " + invocable.getClass().getSimpleName() + "." + method.getName() + " returns: " + (answer == null ? "<null>" : answer.toString()));
        }
        return answer;
    }

    private static String arrayToString(Object... args) {
        final StringBuilder stringBuilder;
        stringBuilder = new StringBuilder();
        for (Object o : args) {
            stringBuilder.append(null == o ? NULL : o.toString());
        }
        return stringBuilder.toString();
    }
}

Specific Code

Let’s return to our business requirement. The EJB has to be modified, and should be like:

public MyServiceBean extends ... implements ...{
  private MyServiceInterface myServiceLogic;

    public MyServiceBean() {
        final MyServiceInterface proxied;
        proxied = new MyServiceLogic();
        this.myServiceLogic = (MyServiceInterface) Proxy.newProxyInstance(proxied.getClass().getClassLoader(),
                proxied.getClass().getInterfaces(),
                new GenericInvocationHandler<MyServiceInterface>(proxied));
    }

From now and then, all the methods calls will be logged… All that without AOP!