当前位置: 首页 > 知识库问答 >
问题:

包含的启用CDI的Servlet出现以下故障:ContextNotActiveException:Weld-001303:

丘智志
2023-03-14
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的请求上下文没有正确设置,而不是直接接收请求。

我已经搜索了这个网站,也通过谷歌,但没有找到匹配的问题/解决方案。我找到了一个tomcat上下文设置'FirerEquestListenerSonForwards=“true”',并将其应用到dispatcher servlet中,但这并没有什么不同。

这是配置问题吗?有人能提供如何解决这个问题的线索吗?

有这个问题的实际应用是很大的,所以我把它浓缩到断线的本质。结果,我有两个war文件。第一个war文件包含CDI servlet和dispatcher(在代码中我称之为includer)servlet。第二个war文件只包含dispatcher 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>
<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>
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());
   }
}
<?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>
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);
   }
}

结果:

当我使用浏览器通过URI:localhost:8080/simplecdiservlet/cdiservlet直接访问CDI servlet时,我会得到预期的输出:

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

如果我通过与CDI servlet位于同一web应用程序中的dispatcher 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 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: 
                           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

共有1个答案

蓬意致
2023-03-14

哇哦!在一个好朋友的帮助下,我拿到了!

要使此工作,您需要配置一个特殊的焊接跨上下文过滤器。您可以通过向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上试用了它,到目前为止还不错。

 类似资料:
  • 问题内容: 我刚刚重新安装了Apache服务器2.2。一切正常。当我进入本地主机时,我得到:“有效!” 我刚刚安装了mySQL5.5,当我转到localhost:3306时,我变得很乱: J 5.5.22 ‘ 4[LM {D〜p ÿ÷! € 6[I = 4 / +,9z {| mysql_native_password。! #08S01Got数据包出现故障 我在互联网上看到很多用户遇到类似问题的帖

  • 我能够使用Publish/SubscribeRabbitMQ Java教程创建扇出交换,任何连接的使用者都将收到一个消息的副本。我想在连接任何使用者之前创建交换和绑定,而不是动态/编程地声明交换和绑定。我已经通过RabbitMQ管理控制台完成了这一点。然而,由于某种原因,我的消费者以循环方式接收消息,而不是全部接收消息的副本。我错过了什么?下面是一些代码片段: 发布者: 消费者: ...在Rabb

  • Cadence是一个容错的有状态代码平台。cadence如何在各种故障情况下处理故障?

  • 我刚刚启动硒网格集线器时遇到麻烦。我正在使用以下命令: java-jar selenium-server-standalone-2.25.0。jar-角色中心 我收到以下消息:2012年7月25日下午1:26:26。openqa。网格硒。GridLauncher主要信息:启动selenium网格服务器 ...但它永远不会过去,只是挂起4444没有反应。 我的问题是:1.这是启动集线器的正确方式吗?

  • 在创建spring maven rest WebService时,我得到了以下错误。当我使用postman测试OCBC api上的post请求时,它工作得很好。但是当我试图为citi执行post请求时,我得到了以下错误:servlet.service()for servlet[dispatcherServlet]上下文中的path[]抛出异常[request processing Failed;嵌

  • 本文向大家介绍使用脚本实现故障时自动重启Apache,包括了使用脚本实现故障时自动重启Apache的使用技巧和注意事项,需要的朋友参考一下 最近不知道为什么博客总是莫名其妙地挂掉, 重启Apache就好了,我也懒得去研究到底是哪里出了问题。 只是每次都需要手工SSH上去重启Apache,有点麻烦。 而且有时候在夜里挂掉,一晚上博客就都不能访问了。 后来终于忍无可忍,写了一段脚本来做这件事,代码如下