Why am I getting a WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped exception?

戏子无情 提交于 2020-01-24 13:53:26

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!