Regarding Guice AOP - Method interceptor loaded and executed twice.

736 views
Skip to first unread message

Rishabh Joshi

unread,
Feb 15, 2017, 3:18:22 AM2/15/17
to Play Framework
Hi,

I have a  strange problem. My AOP method interceptor executes twice. And I am not able to figure out why. Any leads here would be really helpful.

The only thing I am able to identify is that the interceptor has been loaded twice and probably so it is executing twice.

The AOP Method interceptor:
package interceptors;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import services.Counter;

import javax.inject.Provider;

public class TestMethodInterceptor implements MethodInterceptor {

   
Provider<Counter> counter;

   
public TestMethodInterceptor(Provider<Counter> counter) {
       
this.counter = counter;
   
}

   
@Override
   
public Object invoke(MethodInvocation invocation) throws Throwable {
       
System.out.println("^^^^^^^^^^^^^^^^^^^^^^");
       
Object result = invocation.proceed();
        counter
.get().nextCount();
       
return result;
   
}
}

Configured the same in the app/Module.java as:
import com.google.inject.AbstractModule;
import java.time.Clock;

import com.google.inject.matcher.Matchers;
import interceptors.InterceptThis;
import interceptors.TestMethodInterceptor;
import services.ApplicationTimer;
import services.AtomicCounter;
import services.Counter;

/**
 * This class is a Guice module that tells Guice how to bind several
 * different types. This Guice module is created when the Play
 * application starts.
 *
 * Play will automatically use any class called `Module` that is in
 * the root package. You can create modules in other locations by
 * adding `play.modules.enabled` settings to the `application.conf`
 * configuration file.
 */

public class Module extends AbstractModule {

   
@Override
   
public void configure() {
       
// Use the system clock as the default implementation of Clock
        bind
(Clock.class).toInstance(Clock.systemDefaultZone());
       
// Ask Guice to create an instance of ApplicationTimer when the
       
// application starts.
        bind
(ApplicationTimer.class).asEagerSingleton();
       
// Set AtomicCounter as the implementation for Counter.
        bind
(Counter.class).to(AtomicCounter.class);

        bindInterceptor
(
               
Matchers.any(),
               
Matchers.annotatedWith(InterceptThis.class),
               
new TestMethodInterceptor(getProvider(Counter.class)));
   
}

}

The method to intercept:
package controllers;

import interceptors.InterceptThis;
import play.mvc.*;

import views.html.*;

/**
 * This controller contains an action to handle HTTP requests
 * to the application's home page.
 */

public class HomeController extends Controller {

   
/**
     * An action that renders an HTML page with a welcome message.
     * The configuration in the <code>routes</code> file means that
     * this method will be called when the application receives a
     * <code>GET</code> request with a path of <code>/</code>.
     */

   
@InterceptThis
   
public Result index() {
       
return ok("Your new application is ready.");
   
}

}

And just in case if it helps you guys, I have the Deadbolt module configured in application.conf as follows:
 
play.modules {
 
# By default, Play will load any class called Module that is defined
 
# in the root package (the "app" directory), or you can define them
 
# explicitly below.
 
# If there are any built-in modules that you want to disable, you can list them here.
 
#enabled += my.application.Module
  enabled
+= be.objectify.deadbolt.java.DeadboltModule

 
# If there are any built-in modules that you want to disable, you can list them here.
 
#disabled += ""
}

Regards,
Rishabh

Rishabh Joshi

unread,
Feb 15, 2017, 4:40:21 AM2/15/17
to Play Framework
I think I found the solution to my own problem.
The interceptor wasn't loaded twice but was just intercepting twice as the interceptor matcher was 'vague' according to this bug filed - https://github.com/google/guice/issues/640
So the fix for my issue was to have a custom Matcher as follows:
bindInterceptor(
       
Matchers.any(),
       
new AbstractMatcher<Method>() {
           
@Override
           
public boolean matches(Method method) {
               
return method.isAnnotationPresent(InterceptThis.class) && !method.isSynthetic();
           
}
       
},
       
new TestMethodInterceptor(getProvider(Counter.class)));

Hope it helps others here.

-Rishabh
Reply all
Reply to author
Forward
0 new messages