问题
I've looked at other questions relating to this error on the site but most of them are either about SessionScope or are unanswered. The only possibly helpful one is No active contexts for scope type javax.enterprise.context.RequestScoped when invoking a bean from a thread but it's not in the context I have.
I'm running a JAX-RS endpoint on Wildfly 10.1 (Java ee 7). Looks something like this:
@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);
});
}
}
I added the try-catch only because of this problem, it's not generally there. Order
is
@Stateful
@RequestScoped
public class Order {
private Item item;
// setter and getter
}
Order is RequestScoped because when it's being used/processed it goes through a sort of chain of responsibility (several Stateless beans that inject the Order and change it in sequence). Anyway the question is not about the design but about the error.
The line order.setItem(item);
throws the exception:
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)
I tried to annotate the ServerResource class with @Stateless
or RequestScope
(@Stateless vs @RequestScoped) but it didn't matter.
Why do I get this error and how do I get my code working?
回答1:
In CDI, contexts do not propagate to other threads and if you glance at spec, there are scattered notions of contexts being tied to thread. And the Bean stores ("maps" which hold beans for context) are implemented by ThreadLocal
so it just won't work.
There is no way around this using existing contexts - the only option is to define your custom scope/context which will handle context propagation across threads.
EDIT: Note that there is now a JIRA ticket created which considers adding something like this functionality to Weld.
回答2:
You can join the context but I think you understand it wrong. The server has it's own thread pool. Therefore each request is by default asynchronous (Every user request create new thread).
ContextControl ctxCtrl = (ContextControl) BeanProvider.getContextualReference(ContextControl.class, new Annotation[0]);
ctxCtrl.startContext(RequestScoped.class);
try{
//...
} finally {
ctxCtrl.stopContext(RequestScoped.class);
}
来源:https://stackoverflow.com/questions/46529534/why-am-i-getting-a-weld-001303-no-active-contexts-for-scope-type-javax-enterpri