2017-02-24 40 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

相關問題