google / google/guice

Possibility to save state of InterceptorStackCallback in MethodInvocation implementation

Open
#684 0 comments 0 reactions 0 assignees View on GitHub
imported
Dominant language
Java
Stars
12.7k
Forks
1.7k
Avg merge
11m
Merged PRs (30d)
2

Description

_From [flamingpenguin](https://code.google.com/u/117278210618842392530/) on February 12, 2012 13:32:57_

When writing a MethodInterceptor the state of the MethodInvocation passed in by Guice is only valid before and after proceed has been called. And before the invoke method returns.

i.e.

`@`Override public Object invoke(final MethodInvocation invocation) throws Throwable {
   // invocation valid
   Object result = invocation.proceed(); // invocation changes for the duration of the proceed call
   // invocation valid
   return result;
   // invocation changes due to return
}

The reason for this is the use of the mutable "index" field in the InterceptedMethodInvocation class.

The implementation of "proceed()" recursively passes itself to each of the interceptors. Effectively "index" is working as a stack pointer.

The consequence of this is that I cannot keep a reference to the MethodInvocation object and use it somewhere else. For example, I want to write an method interceptor that executes the intercepted method in a different thread. An immutable implementation of MethodInvocation would be preferable.

For example copying the InterceptedMethodInvocation before each invocation would solve this problem by making the MethodInvocation more like an immutable object. Like this:

  private class InterceptedMethodInvocation implements MethodInvocation {

    final Object proxy;
    final Object[] arguments;
    final MethodProxy methodProxy;

    public InterceptedMethodInvocation(final Object proxy, final MethodProxy methodProxy,
        final Object[] arguments) {
        this(proxy, methodProxy, arguments, -1);
    }
    
    public InterceptedMethodInvocation(final Object proxy, final MethodProxy methodProxy,
            final Object[] arguments, int index) {
      this.proxy = proxy;
      this.methodProxy = methodProxy;
      this.arguments = arguments;
      this.index = index;
    }

    public Object proceed() throws Throwable {
      try {
        int nextIndex = index + 1;
        return nextIndex == interceptors.length
            ? methodProxy.invokeSuper(proxy, arguments)
            : interceptors[nextIndex].invoke(new InterceptedMethodInvocation(proxy, methodProxy, arguments, nextIndex));
      } catch (final Throwable t) {
        pruneStacktrace(t);
        throw t;
      }
    }

    public Method getMethod() {
      return method;
    }

    public Object[] getArguments() {
      return arguments;
    }

    public Object getThis() {
      return proxy;
    }

    public AccessibleObject getStaticPart() {
      return getMethod();
    }
  }

_Original issue: http://code.google.com/p/google-guice/issues/detail?id=684_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.