2013-10-28 45 views
3

我有吉斯工作检票[V6]应用[V3] - 我使用依赖注入库经营权,现在我想把它花费到使用的会话范围的服务(一个每个用户的会话)。我已阅读官方文档,各种博客文章和问题,但我不确定我是否使用了正确的方法。吉斯和Wicket:使用SessionScoped注射

我有两个问题: 1.我用正确的方法? 2.我是否需要特别的东西来对依赖于SessionScoped注入的类运行TestNG测试?

我的设置: web.xml中:

<filter> 
    <filter-name>guiceFilter</filter-name> 
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> 
</filter>  
<filter-mapping> 
    <filter-name>guiceFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
<listener> 
    <listener-class>com.xxx.CustomServletConfig</listener-class> 

MyApplication的初始化:

@Override 
protected void init() 
{ 
    super.init(); 
    getResourceSettings().setResourcePollFrequency(null); 
    getMarkupSettings().setStripWicketTags(true); 
    getDebugSettings().setDevelopmentUtilitiesEnabled(true); 
    GuiceComponentInjector injector = new GuiceComponentInjector(this, new WebModule(), new GuiceModule());; 
} 

CustomServletConfig:

public class CustomServletConfig extends GuiceServletContextListener { 

    @Override 
    protected Injector getInjector() { 
     return Guice.createInjector(new GuiceModule(), new WebModule()); 
    } 

WebModule:

public static class WebModule extends ServletModule { 

    @Override 
    protected void configureServlets() { 
     bind(WebApplication.class).toProvider(WicketGuiceAppProvider.class).asEagerSingleton(); 

     bind(IUserService.class).to(UserService.class).in(ServletScopes.SESSION); 

     Map<String, String> params = new HashMap<String, String>();  
     params.put(WicketFilter.FILTER_MAPPING_PARAM, "/*"); 

     filter("/*").through(WicketGuiceFilter.class, params); 
    } 
} 

在示例中的网页我有:

@Inject 
IUserService userService 

... 

userService.doSomething 

在userService.doSomething单元测试过程中我得到吉斯OutOfScopeException,指着我的绑定中的servlet:在定制供应商,COM 错误。 google.inject.OutOfScopeException?:无法访问作用域对象。我们目前不在HTTP Servlet请求中,或者您可能忘记应用com.google.inject.servlet.GuiceFilter?作为这个请求的一个servlet过滤器。

我的配置是否正常,我需要以不同的方式运行单元测试(我简单地使用WicketTester启动我的应用程序),还是我的设计有问题?

+1

您可以添加单元测试代码吗?你在服务器上试过了吗? – mrak

回答

3

这是很常见的故障。

ServletScopesRequestScopes中的所有实体都应作为Providers传入。

所以,你的代码应该是:

@Inject 
Provider<IUserService> userServiceProvider 

public IUserService getUserService() { 
    userServiceProvider.get(); 
} 

为什么会这样?一切都很好,只要你在Stage.DEVELOPMENT中使用它,并且父类不是急切地创建的。如果您将您的父类绑定为asEagerSingleton或切换到Stage.PRODUCTION,那么您的类将在启动时开始快速创建。否则,只有在访问它们时(很可能在第一次请求期间)才会以懒惰的方式创建它们。

还有你的问题涉及到的场景。您的WebApplication在启动时急切地初始化。然后,Guice试图注入所有的子依赖关系,并发现IUserService这是在SessionScope中的字段注入。问题是你目前不在GuiceFilter中,并且没有请求,所以Guice无法确定当前会话或创建新会话。所以这些范围无法达到。您目前在您的ContextListener中,并且您的应用程序正在急切地实例化。一切都可能是罚款,如果你只使用Singleton代替asEagerSingleton因为延迟加载的。

无论如何,将Session和Request范围对象作为提供者传递是最佳实践。您可以详细了解Providers hereScopes here (there is also nice table with eager vs. lazy loading comparsion)