为什么我会收到 WELD-001303:范围类型 javax.enterprise.context.RequestScoped 异常没有活动上下文?
Why am I getting a WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped exception?
我在网站上查看了与此错误相关的其他问题,但其中大部分要么与 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,因为当它被 used/processed 时,它会经历一种责任链(几个注入 Order 并按顺序更改它的无状态 bean)。无论如何,问题不在于设计,而在于错误。
第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[=13=](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)
我尝试用 @Stateless
或 RequestScope
(@Stateless vs @RequestScoped) 注释 ServerResource class 但没关系。
为什么会出现此错误以及如何让我的代码正常工作?
你可以加入上下文,但我认为你理解错了。服务器有自己的线程池。因此每个请求默认都是异步的(每个用户请求创建新线程)。
ContextControl ctxCtrl = (ContextControl) BeanProvider.getContextualReference(ContextControl.class, new Annotation[0]);
ctxCtrl.startContext(RequestScoped.class);
try{
//...
} finally {
ctxCtrl.stopContext(RequestScoped.class);
}
在 CDI 中,上下文不会传播到其他线程,如果您浏览一下规范,就会发现上下文与线程相关联的概念很分散。 Bean 存储("maps" 为上下文保存 bean)由 ThreadLocal
实现,所以它不会工作。
没有办法使用现有的上下文来解决这个问题 - 唯一的选择是定义您的自定义 scope/context,它将处理跨线程的上下文传播。
编辑: 请注意,现在创建了一个 JIRA ticket,它考虑向 Weld 添加类似的功能。
我在网站上查看了与此错误相关的其他问题,但其中大部分要么与 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,因为当它被 used/processed 时,它会经历一种责任链(几个注入 Order 并按顺序更改它的无状态 bean)。无论如何,问题不在于设计,而在于错误。
第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[=13=](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)
我尝试用 @Stateless
或 RequestScope
(@Stateless vs @RequestScoped) 注释 ServerResource class 但没关系。
为什么会出现此错误以及如何让我的代码正常工作?
你可以加入上下文,但我认为你理解错了。服务器有自己的线程池。因此每个请求默认都是异步的(每个用户请求创建新线程)。
ContextControl ctxCtrl = (ContextControl) BeanProvider.getContextualReference(ContextControl.class, new Annotation[0]);
ctxCtrl.startContext(RequestScoped.class);
try{
//...
} finally {
ctxCtrl.stopContext(RequestScoped.class);
}
在 CDI 中,上下文不会传播到其他线程,如果您浏览一下规范,就会发现上下文与线程相关联的概念很分散。 Bean 存储("maps" 为上下文保存 bean)由 ThreadLocal
实现,所以它不会工作。
没有办法使用现有的上下文来解决这个问题 - 唯一的选择是定义您的自定义 scope/context,它将处理跨线程的上下文传播。
编辑: 请注意,现在创建了一个 JIRA ticket,它考虑向 Weld 添加类似的功能。