2015-06-03 24 views
2

我正在編寫一個在Tomcat上運行的CDI應用程序。我使用Tomcat 7.0.62和 Weld 2.2.12.Final作爲CDI實現。我在沒有JSF的情況下使用CDI。包含啓用CDI的Servlet因ContextNotActiveException失敗:WELD-001303:

該應用程序由不啓用CDI的調度程序servlet組成。 調度程序包含啓用CDI的servlet的輸出以創建頁面。

當調度程序servlet和CDI servlet都在同一個web應用程序中時, 工作正常。不過,我需要CDI servlet在不同的web應用程序中,所以我做了一個跨環境包含。當我執行跨環境包含時,CDI servlet 會生成輸出,直到它嘗試訪問@RequestScoped bean。豆 訪問失敗,出現以下異常:

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:708) 
    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) 
... 

我試圖激活CDI的調度程序servlet的爲好,但它似乎並不 任何區別。

在我看來,像包含CDI servlet的CDI servlet的請求上下文沒有正確設置 ,而不是直接接收請求 。

我已經搜索過這個網站,也通過谷歌,但還沒有找到匹配的 問題/解決方案。我發現我應用於調度程序servlet的tomcat上下文設置'fireRequestListenersOnForwards =「true」' ,但這沒有什麼不同。

這是一個配置問題嗎?任何人都可以提供關於如何解決這個問題的線索嗎?

我將不勝感激!


背景資料:

有問題的實際應用是大的,所以我凝結下來獲得 到破碎的精髓。結果,我有兩個戰爭檔案。第一個war文件 包含CDI servlet和調度程序(在我稱之爲includer的代碼中)servlet。第二個war文件僅包含 調度程序servlet。

的CDI的Servlet

的CDI的Servlet有以下內容在其META_INF目錄中的context.xml文件:

<?xml version="1.0" encoding="UTF-8"?> 
<Context> 
    <Resource name="BeanManager" 
     auth="Container" 
     type="javax.enterprise.inject.spi.BeanManager" 
     factory="org.jboss.weld.resources.ManagerObjectFactory" /> 
</Context> 

的CDI servlet的web.xml文件中包含行:

<listener> 
    <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> 
</listener> 

<resource-env-ref> 
    <resource-env-ref-name>BeanManager</resource-env-ref-name> 
    <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type> 
</resource-env-ref> 

CDI Servlet WEB-INF目錄包含一個beans.xml文件。

的CDI的servlet自舉豆執行通過使用BeanManager獲得 通過JNDI查找(這是工作):

BeanManager bm = null; 
try { 
    InitialContext context = new InitialContext(); 

    try { 
     // "regular" naming 
     bm = (BeanManager) context.lookup("java:comp/BeanManager"); 
    } catch(NameNotFoundException e) { 
     // try again with Tomcat naming 
     bm = (BeanManager) context.lookup("java:comp/env/BeanManager"); 
    } 
} catch (Exception e) {} 

if (bm == null) { 
    writer.write("Couldn't look up the bean manager"); 
} else { 
    Set<Bean<?>> beans = bm.getBeans(EnclosingBean.class); 
    @SuppressWarnings("unchecked") 
    Bean<EnclosingBean> bean = (Bean<EnclosingBean>) bm.resolve(beans); 
    if (bean == null) { 
     writer.write("Couldn't get the bean"); 
    } else { 
     EnclosingBean eb = (EnclosingBean) bm.getReference(bean, bean.getBeanClass(), bm.createCreationalContext(bean)); 
     writer.write("finally here we are. Name is: "); 
     writer.write(eb.getName()); 
    } 
} 

的包入(分派)的Servlet

的包入servlet有一個在其META-INF目錄中的context.xml文件:

<?xml version="1.0" encoding="UTF-8"?> 
<Context 
    path="/ExternalIncluderServlet" 
    docBase="ExternalIncluderServlet.war" 
    crossContext="true" 
    fireRequestListenersOnForwards="true"> 

    <Resource name="BeanManager" 
     auth="Container" 
     type="javax.enterprise.inject.spi.BeanManager" 
     factory="org.jboss.weld.resources.ManagerObjectFactory" /> 
</Context> 

該inclu DER servlet查找的CDI的servlet上下文並獲得 的RequestDispatcher如下(本作品):

ServletContext sc = request.getServletContext(); 
ServletContext extsc = sc.getContext("/SimpleCDIServlet"); 
if (extsc == null) { 
    writer.println("<p>Couldn't get the external context.</p>"); 
} else { 

    RequestDispatcher rd = extsc.getRequestDispatcher("/CDIServlet"); 
    if (rd == null) { 
     writer.println("<p>RequestDispatcher is null.</p>"); 
    } else { 
     writer.println("<p>Got the RequestDispatcher.</p>"); 
     rd.include(req, resp); 
    } 
} 

結果:

當我用瀏覽器直接通過訪問CDI的servlet URI:本地主機:8080/SimpleCDIServlet/CDIServlet我得到預期的輸出:

Simple CDI Servlet 
finally here we are. Name is: InjectedBean 

如果我通過位於相同的Web應用程序的調度程序servlet的訪問CDI的servlet CDI servlet,它也可以工作。 URI:/ SimpleCDIServlet/IncluderServlet,輸出:

Simple CDI Servlet Including Servlet 
Will now include the CDI servlet ... 
Got the RequestDispatcher. 
Simple CDI Servlet 
finally here we are. Name is: InjectedBean 

但如果我包括在不同的上下文中CDI的servlet,我不輸出獲得注入的bean的名字和異常上面提到的是在日誌中。 URI:/ ExternalIncluderServlet/IncluderServlet,輸出:

CDI Servlet Includer 

This servlet includes a CDI servlet in a different web app. It is not CDI enabled. 

Got the RequestDispatcher. 
Simple CDI Servlet 
finally here we are. Name is: 

注意,我不能使用一個請求分配器前進,而不是包括與原始 應用包括從其他幾個小服務程序輸出,而不是僅僅一個。並且開放 對每個包含的新HTTP請求效率不高,因爲請求數 將乘以包含的servlet的數量,並且除此之外,這將是相當難看的 。


更新: 我想這一點上Tomee 1.7.2,並在WebSphere Application Server V8.5。結果總結如下。

 
          WAS 8.5   Tomcat 7.0.62   Tomee 1.7.2 
          =======   =============   =========== 
CDI servlet direct access works    works     works 

Included by servlet   works    works     works   
    in same web app 

Included by servlet   works    broken     broken 
    in different web app 

我越思考這個,我越覺得它真的應該工作。您應該能夠 成功地使用請求分派器在Tomcat上包含啓用CDI的servlet的輸出。 我希望這裏的某個人能幫我弄清楚如何使它工作。

+0

什麼是...?你如何真正獲得你的CDIServlet生成的內容?其次:你能直接從瀏覽器(或HttpRequester工具)而不是通過前端控制器調用servlet嗎?這是否成功? – Gimby

+0

嗨Gimby,謝謝你的迴應。我擴展了代碼片段並添加了程序輸出文本。如果我直接訪問CDI servlet,它就可以工作。如果我通過位於與CDI portlet相同的Web應用程序的調度程序servlet訪問CDI servlet,它也可以工作。它失敗當我嘗試從不同的上下文中包含servlet時。 –

+0

好問題。實際上,當交叉環境包含完成時,CDI/Weld沒有機會初始化自己。這實際上並不令我感到奇怪,因爲在這種情況下,CDIServlet將不會涉及實際的HTTP請求,因此CDI偵聽器甚至可能不會觸發。技術解決方法:對第二個servlet執行HTTP請求,但我想知道是否有適當的解決方案。 – Gimby

回答

4

哇!在一位好朋友的幫助下,我明白了!

爲了使這項工作,你需要配置一個特殊的焊接跨上下文過濾器。通過將以下行添加到web.xml文件來配置過濾器。

<filter> 
    <filter-name>WeldCrossContextFilter</filter-name> 
    <filter-class>org.jboss.weld.servlet.WeldCrossContextFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>WeldCrossContextFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    <dispatcher>INCLUDE</dispatcher> 
    <dispatcher>FORWARD</dispatcher> 
    <dispatcher>ERROR</dispatcher> 
</filter-mapping> 

當我配置它時,CDI servlet的交叉上下文包含工作正常。 我在Tomcat 7.0.42和8.0.23上試用過,所以很好。

參見:

http://javadox.com/org.jboss.weld/weld-core-impl/2.2.4.Final/org/jboss/weld/servlet/WeldCrossContextFilter.html

我看了官方焊接文檔中的過濾器的參考,但無法 找到任何東西。無論如何,我希望這可能有助於某人。

相關問題