【问题标题】:WebSocket endpoint and CDI injection: No active contexts for scope RequestScopedWebSocket 端点和 CDI 注入:范围 RequestScoped 没有活动上下文
【发布时间】:2017-02-24 14:13:58
【问题描述】:

我想在我的 Java EE 7 WebSocket 端点中注入一个 @RequestScoped CDI bean。

但是我收到错误WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped。

我做错了什么,为什么不可能?

@Named
@RequestScoped
public class Storage {

}

我在端点@Inject是这样的:

@ServerEndpoint("/serverpush")
public class ContratoEndpoint {

    @Inject
    private Storage storage;

}

我得到以下堆栈跟踪:

org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
    at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:689)
    at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:90)
    at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:165)
    at org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)
    at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)

【问题讨论】:

    标签: java cdi weld java-websocket


    【解决方案1】:

    正如@John 提到的,RequestContext 在 WebSocket 方法中不活动。除了使用 Deltaspike(这是一个不错的选择),您还可以编写自己的拦截器来激活/停用焊接 RequestContext。

    当您使用 Wildfly 时,您可以使用 Weld 作为提供的依赖项:

    <dependency>
        <groupId>org.jboss.weld</groupId>
        <artifactId>weld-core</artifactId>
        <version>2.2.12.Final</version>
        <scope>provided</scope>
    </dependency>
    

    然后你可以定义一个InterceptorBinding @RequestContextOperation :

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import javax.interceptor.InterceptorBinding;
    
    @InterceptorBinding
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD, ElementType.TYPE })
    public @interface RequestContextOperation
    {
    
    }
    

    以及我们激活/停用RequestContext的相应RequestContextInterceptor:

    import javax.inject.Inject;
    import javax.interceptor.AroundInvoke;
    import javax.interceptor.Interceptor;
    import javax.interceptor.InvocationContext;
    
    import org.jboss.weld.context.RequestContext;
    import org.jboss.weld.context.unbound.Unbound;
    
    @Interceptor
    @RequestContextOperation
    public class RequestContextInterceptor {
    
        /** The RequestContext */
        @Inject
        @Unbound
        private RequestContext m_requestContext;
    
        /**
         * 
         * @param p_invocationContext
         * @return
         * @throws Exception
         */
        @AroundInvoke
        public Object activateRequestContext(final InvocationContext p_invocationContext) throws Exception {
            try {
                m_requestContext.activate();
                return p_invocationContext.proceed();
            } finally {
                m_requestContext.invalidate();
                m_requestContext.deactivate();
            }
        }
    }
    

    然后您可以在您的类或特定方法上使用 @RequestContextOperation 注释:

    @ServerEndpoint("/serverpush")
    public class ContratoEndpoint {
    
        @Inject
        private Storage storage;
    
        @OnMessage
        @RequestContextOperation
        public String handleMessage(String message){
    
            // Here the @RequestScoped bean is valid thanks to the @RequestContextOperation InterceptorBinding
            storage.yourMethod();
            ....
        }
    
    }
    

    【讨论】:

    • @BonanzaOne @Rouliboy 虽然这是一个很好的方法,但我会首先尝试Weld 中已经存在的方法。如果您设置对 Weld API 的依赖,您可以使用预定义的拦截器绑定 @ActivateRequestContext 来注释您的方法/类,这正是您所寻求的。您可以在Weld Doc 中阅读更多相关信息。虽然这最初是为 SE 环境设计的,但它应该在 EE 中同样适用。
    • @Siliarus :我不知道这个,谢谢你的信息!
    【解决方案2】:

    WebSockets 不会为其方法调用初始化请求范围上下文。您可以使用deltaspike context control 手动启动方法调用的请求上下文。

    【讨论】:

    • 我正在使用 WildFly,有没有没有外部依赖的解决方案?
    • 因为它的 apache 许可,使用源代码应该不是问题github.com/apache/deltaspike/blob/master/deltaspike/cdictrl/… 你可能不需要所有这些复杂性
    • @BonanzaOne :我使用 WildFly 服务器的一部分 Weld 更新了我的答案。
    猜你喜欢
    • 2014-06-02
    • 1970-01-01
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    • 2013-05-06
    相关资源
    最近更新 更多