my Google Guice method interceptor doesn’t execute but Why?

Tags: , ,



So I am testing a simple Google Guice interceptor –

My Annotation –

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD)
public @interface AppOpsOperation {

}

My Interceptor

public class AppOpsOperationDecorator implements MethodInterceptor {

    private ServiceCallStack callStack = null ;

    @Inject
    public void setServiceCallStack(ServiceCallStack stack ){
        callStack = stack ;
    }

    @Override
    public Object invoke(MethodInvocation arg0) throws Throwable {

        // Retrieve the call stack 
        // exclude service population if caller service is the same service 
        // else push the current service onto top of stack 

        System.out.println("Intercepting method  -- ::  " + arg0.getMethod().getName());
        System.out.println("On object             - ::  " + arg0.getThis().getClass().getName());
        System.out.println("On accessible object  - ::  " + arg0.getStaticPart().getClass().getName());
        return invocation.proceed();
    }

}

And now my Service interface and method

public interface MockCalledService extends AppOpsService {

@AppOpsOperation
public String methodOneCalled(String some);

@AppOpsOperation
public String methodTwoCalled(String some);
}

public class MockCalledServiceImpl extends BaseAppOpsService implements MockCalledService {

@Override
@AppOpsOperation
public String methodOneCalled(String some) {
    System.out.println("MockCalledServiceImpl.methodOneCalled()");
    return this.getClass().getCanonicalName() + "methodOneCalled";
}

@Override
public String methodTwoCalled(String some) {
    System.out.println("MockCalledServiceImpl.methodTwoCalled()");
    return this.getClass().getCanonicalName() + "methodTwoCalled";
}

}

And my Guice test module

public class MockTestGuiceModule extends AbstractModule {

@Override
protected void configure() {

    bind(ServiceCallStack.class).toInstance(new ServiceCallStack());

    AppOpsOperationDecorator decorator = new AppOpsOperationDecorator() ;

    requestInjection(decorator);

    bindInterceptor(Matchers.any(), Matchers.annotatedWith(AppOpsOperation.class), 
             decorator);

    bind(MockCalledService.class).toInstance(new MockCalledServiceImpl());
}

}

This interceptor doesn’t execute when I run the test below –

public class AppOpsOperationDecoratorTest {

private Injector injector = null ;

@Before
public void init(){
    injector =  Guice.createInjector(new MockTestGuiceModule());
}

@Test
public void testDecoratorInvocation() {

    MockCalledService called = injector.getInstance(MockCalledService.class);

    called.methodOneCalled("Test String");

}

}

Can you please highlight what I am doing wrong ?

Answer

I am answering after finding the real reason. Its so simple that its really tricky.

Method interception only works if you bind the interface with the class and not an instance of this implementation.

so instead of bind(MockCalledService.class).toInstance(new MockCalledServiceImpl());

we should write bind(MockCalledService.class).to(MockCalledServiceImpl.class);

Seems instances are not proxied 🙁



Source: stackoverflow