为啥我会收到 WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped 异常?

Posted

技术标签:

【中文标题】为啥我会收到 WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped 异常?【英文标题】:Why am I getting a WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped exception?为什么我会收到 WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped 异常? 【发布时间】:2018-03-13 18:17:11 【问题描述】:

我在网站上查看了与此错误相关的其他问题,但其中大多数问题要么与 SessionScope 有关,要么未得到解答。唯一可能有用的是No active contexts for scope type javax.enterprise.context.RequestScoped when invoking a bean from a thread,但它不在我的上下文中。

我在 Wildfly 10.1 (Java ee 7) 上运行 JAX-RS 端点。看起来像这样:

@Path("")
public class ServerResource 

    @Inject
    Order order;

    @Resource
    ManagedExecutorService mes;

    @PUT
    @Path("/prepareOrder")
    public void prepareOrder(@Suspended AsyncResponse response) 
        mes.execute(() ->  
            try 
                Item item = new Item(); // JPA entity
                order.setItem(item); // line 71
                // call a service to save the order data (like item) to the DB
             catch (Exception e) 
                e.printStackTrace();
                response.resume(false);
            
            response.resume(true);
        );
    

我添加 try-catch 只是因为这个问题,它通常不存在。 Order

@Stateful
@RequestScoped
public class Order 
    private Item item;
    // setter and getter

Order 是 RequestScoped,因为当它被使用/处理时,它会经历一种责任链(几个无状态 bean 注入 Order 并按顺序更改它)。无论如何,问题不在于设计,而在于错误。

order.setItem(item); 行抛出异常:

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)
at com.a.b.Order$Proxy$_$$_WeldClientProxy.setItem(Unknown Source)
at com.a.c.ServerResource.lambda$0(ServerResource.java:71)
at org.jboss.as.ee.concurrent.ControlPointUtils$ControlledRunnable.run(ControlPointUtils.java:105)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.glassfish.enterprise.concurrent.internal.ManagedFutureTask.run(ManagedFutureTask.java:141)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
at org.glassfish.enterprise.concurrent.ManagedThreadFactoryImpl$ManagedThread.run(ManagedThreadFactoryImpl.java:250)

我尝试使用 @StatelessRequestScope (@Stateless vs @RequestScoped) 来注释 ServerResource 类,但这没关系。

为什么会出现此错误以及如何让我的代码正常工作?

【问题讨论】:

不确定,但是否需要混合 CDI 注释 (RequestScoped) 和 EJB 注释 (Stateless / Stateful)?也许您的 Order 只能是 CDI beanEJB bean 取决于您的设计 @Al1 我删除了@Stateful 并没有区别。 这是因为请求绑定到处理请求的服务器线程。当您切换线程时,将无法再访问该请求上下文。所以你不能从不同的线程访问“请求范围”的东西。 @peeskillet 所以它可以与同步响应一起工作,对吧?我怎样才能让它以异步方式工作? @peeskillet 我不明白这有什么帮助。我有无状态 bean,例如处理需要该请求的 Order 对象的持久性的服务。使用单例如何解决问题? 【参考方案1】:

您可以加入上下文,但我认为您理解错误。服务器有它自己的线程池。因此,默认情况下每个请求都是异步的(每个用户请求都创建新线程)。

ContextControl ctxCtrl = (ContextControl) BeanProvider.getContextualReference(ContextControl.class, new Annotation[0]);
ctxCtrl.startContext(RequestScoped.class);
try
//...
 finally 
 ctxCtrl.stopContext(RequestScoped.class);

【讨论】:

如果请求是同步的,那么RequestScope没有问题,那我理解错了什么? 异步创建该请求的原因不止一个。因为它默认不会阻塞其他请求。【参考方案2】:

在 CDI 中,上下文不会传播到其他线程,如果您看一下规范,就会发现上下文与线程相关联的零散概念。而 Bean 存储(保存 bean 的上下文的“映射”)是由 ThreadLocal 实现的,所以它不会工作。

使用现有上下文无法解决此问题 - 唯一的选择是定义您的自定义范围/上下文,它将处理跨线程的上下文传播。

编辑:请注意,现在创建了一个 JIRA ticket,它考虑向 Weld 添加类似此功能的功能。

【讨论】:

以上是关于为啥我会收到 WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped 异常?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我会收到 `invalid_request`:`no client authentication mechanism provided` 的 400 响应?

为啥我会收到 ConcurrentModificationException?

为啥我会收到 CancelledKeyException?

为啥我会收到此错误

为啥我会收到这个 TypeError?

为啥我会收到序列化错误?