【问题标题】:Jersey: Injection works in resource method, but not for a EJB attributeJersey:注入在资源方法中有效,但不适用于 EJB 属性
【发布时间】:2011-10-31 15:17:51
【问题描述】:

我有一个自定义 InjectionProvider,它从 SecurityContext 中检索 User 对象并使其可用。自定义 ResourceFilter 执行 HTTP 基本身份验证,创建 SecurityContext 并使用 Principal 填充它。这是基于this suggestion

当我从资源方法访问它时,它按预期工作:

@Stateless
@Path("foo")
public class FooResource {

  @GET
  @ResourceFilters(value = {UserAuthenticationFilter.class})
  public Response get(@Context User user) {
    return Response.ok().entity(user).build();
  }
}

但是,当我尝试将对象作为属性/字段注入 EJB 时,会引发异常,即使我可以在日志中看到 InjectionProvider 被调用:

@Stateless
@Path("foo")
public class FooResource {

  @Context
  private User user;

  @GET
  @ResourceFilters(value = {UserAuthenticationFilter.class})
  public Response get() {
    return Response.ok().entity(user).build();
  }
}

异常奇怪:

[#|2011-10-31T13:35:47.691+0000|警告|glassfish3.1.1|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=18;_ThreadName=Thread-3;| StandardWrapperValve[Gateway Servlet]: PWC1406: Servlet.service() for servlet Gateway Servlet 抛出异常 javax.ejb.CreateException:无法创建无状态 EJB 在 com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:534) 在 com.sun.ejb.containers.StatelessSessionContainer.access$000(StatelessSessionContainer.java:95) 在 com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:724) 在 com.sun.ejb.containers.util.pool.NonBlockingPool.getObject(NonBlockingPool.java:247) 在 com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:449) 在 com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:2528) 在 com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1895) 在 com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212) 在 com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88) 在 $Proxy166.get(未知来源) …… 引起:com.sun.jersey.spi.inject.Errors$ErrorMessagesException 在 com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170) 在 com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:136) 在 com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:199) 在 com.sun.jersey.server.impl.application.WebApplicationImpl$ComponentProcessorFactoryImpl.get(WebApplicationImpl.java:499) 在 com.sun.jersey.server.impl.ejb.EJBInjectionInterceptor.get(EJBInjectionInterceptor.java:104) 在 com.sun.jersey.server.impl.ejb.EJBInjectionInterceptor.init(EJBInjectionInterceptor.java:71) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCallback(SystemInterceptorProxy.java:133) 在 com.sun.ejb.containers.interceptors.SystemInterceptorProxy.init(SystemInterceptorProxy.java:120) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 com.sun.ejb.containers.interceptors.CallbackInterceptor.intercept(InterceptorManager.java:964) 在 com.sun.ejb.containers.interceptors.CallbackChainImpl.invokeNext(CallbackChainImpl.java:65) 在 com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:393) 在 com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:376) 在 com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:526) ... 55 更多

我做错了什么?

EDIT:刚刚注意到,在抛出异常之前,server.log中报错:

[#|2011-10-31T15:33:01.854+0000|SEVERE|glassfish3.1.1|com.sun.jersey.spi.inject.Errors|_ThreadID=18;_ThreadName=Thread-3;|以下错误和警告有使用资源和/或提供程序类检测到: 严重:缺少字段的依赖项:private com.skalio.bonusapp.core.User com.skalio.bonusapp.gateway.FooResource.user|#]

【问题讨论】:

    标签: java dependency-injection jersey


    【解决方案1】:

    这是由于范围不匹配造成的。您正在尝试将请求范围内的事物注入到非请求范围内的 bean 中。那是行不通的。

    【讨论】:

    • 好的,我明白了。资源本身不是请求范围的,但方法调用显然是。谢谢。不过还有其他方法吗?或者在每个(相关)方法调用中注入用户实际上是一个很好的模式吗?
    • 普通资源是请求范围的 - 但无状态 EJB 资源不是。您可以尝试的一个想法是使 User 对象成为一个单例(实现单例注入提供程序),它利用 ThreadLocals 为给定上下文提供其属性的正确值。或者您可以使用带有 getUser() 方法的 UserInfo 对象,该方法返回给定线程的正确用户(使用 ThreadLocals),然后您将注入它。您可以使用 ContainerRequestFilter 为给定线程设置该对象的值,并使用 ContainerResponseFilter 在处理请求后对其进行清理。
    猜你喜欢
    • 1970-01-01
    • 2014-02-20
    • 2015-11-03
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多