2012-01-03 128 views
2

我想通過由Guice創建的Vaadin應用程序實例注入攔截器。 我已經按照在Vaadin Wiki和 在Guice Wiki上攔截DI的documenation爲Vaadin - 吉斯一體化的文檔:Guice:在ServletModule中注入攔截器

public class RecruitmentServletConfig extends GuiceServletContextListener { 

    @Override 
    protected Injector getInjector() { 

     ServletModule servletModule = new ServletModule() { 

      @Override 
      protected void configureServlets() { 
       ... 
       bind(Application.class).to(RecruitmentApplication.class).in(ServletScopes.SESSION); 
       SecurityGuard securityGuard = new SecurityGuard(); 
       requestInjection(securityGuard); 
       bindInterceptor(Matchers.subclassesOf(CustomComponent.class), Matchers.annotatedWith(AllowedRoles.class), securityGuard); 
      } 
     }; 
     return Guice.createInjector(servletModule); 
    } 
} 

的保全攔截:

public class SecurityGuard implements MethodInterceptor { 
    @Inject private Application application; 

    public Object invoke(MethodInvocation invocation) throws Throwable { 
     AllowedRoles allowedRoles = invocation.getMethod().getAnnotation(AllowedRoles.class); 
     if (((User) application.getUser()).hasRole(allowedRoles.value())) { 
      return invocation.proceed(); 
     } else { 
      return null; 
     } 
} 

不過,我得到一個OutOfScopeException在服務器啓動時:

SEVERE: Exception sending context initialized event to listener instance of class de.embl.eicat.recruit.ioc.RecruitmentServletConfig 
com.google.inject.CreationException: Guice creation errors: 
1) Error in custom provider, com.google.inject.OutOfScopeException: Cannot access scoped object. Either we are not currently inside an HTTP Servlet request, or you may have forgotten to apply com.google.inject.servlet.GuiceFilter as a servlet filter for this request. 
at recruit.ioc.RecruitmentServletConfig$1.configureServlets(RecruitmentServletConfig.java:86) 
+0

注:應用實例需要對方法被調用在每個新用戶會話(因此。在(ServletScopes.SESSION)然而,該配置()/ configureServlets()被創建服務器在創建任何用戶會話之前啓動,我想解釋一下OutOfScopeException。這是真的,應該在哪裏調用requestInjection(securityGuard)? – 2012-01-03 14:12:11

回答

3

如果包裝您的ApplicationProvider?上Application.class範圍

public class SecurityGuard implements MethodInterceptor { 
    @Inject private Provider<Application> application; 

    public Object invoke(MethodInvocation invocation) throws Throwable { 
     AllowedRoles allowedRoles = invocation.getMethod().getAnnotation(AllowedRoles.class); 
     if (((User) application.get().getUser()).hasRole(allowedRoles.value())) { 
      return invocation.proceed(); 
     } else { 
      return null; 
     } 
} 
+0

是的,這很好,Eiden!非常感謝! – 2012-01-04 09:13:58

+0

這是正確的解決方案。一個提供者而不是直接引用,Guice將每次調用提供者*應用程序需要時,而不是試圖在前面完成。假設提供者將在* vaadin會話回調期間被調用*,它將成功地通過拉動應用程序來自會話範圍,其中已經設置在堆棧上。 – 2012-01-05 14:39:59