2017-02-24 70 views
0

我想在我的Java EE 7 WebSocket端点中注入一个@RequestScoped CDI bean。WebSocket端点和CDI注入:没有活动上下文范围RequestScoped

但是我收到错误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) 

回答

1

正如@约翰提到的,RequestContext在WebSocket方法中不活动。除了使用Deltaspike(这是一个很好的选择),你也可以编写你自己的拦截器来激活/关闭焊接RequestContext

由于使用的是Wildfly,可以使用焊接作为提供依赖性:

<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 
{ 

} 

和相应RequestContextInterceptor我们启动/不启动RequestContext

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(); 
     .... 
    } 

} 
+1

@BonanzaOne @Rouliboy虽然这是一个很好的方法,但我会首先尝试一个已经存在于Weld **中的**。如果你设置了对Weld API的依赖关系,那么你可以使用预定义的拦截器绑定“@ ActivateRequestContext”来注释你的方法/类,而这正是你所寻找的。您可以在[Weld Doc](http://docs.jboss.org/weld/reference/latest/en-US/html_single/#_request_context)中阅读更多内容。虽然这最初是为SE环境设计的,但它应该在EE中工作。 – Siliarus

+0

@Siliarus:我不知道这一点,谢谢你的信息! – Rouliboy

1

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

+0

我使用WildFly,无需外部依赖任何解决方案? – BonanzaOne

+0

因为它的apache许可,使用源代码不应该是一个问题https://github.com/apache/deltaspike/blob/master/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/ deltaspike/cdise/weld/WeldContextControl.java#L158您可能不需要所有这些复杂性 –

+0

@BonanzaOne:我使用Weld(它是WildFly服务器的一部分)更新了我的答案。 – Rouliboy

相关问题