Get rid of org.jboss.weld.context.NonexistentConversationException, when a query-string parameter named cid is appended to the URL

和自甴很熟 提交于 2019-12-29 08:57:31

问题


Take a simple CDI (it could also be a JSF managed bean) bean as follows.

import java.io.Serializable;    
import javax.inject.Named;
import javax.faces.view.ViewScoped;

@Named
@ViewScoped
public class TestManagedBean implements Serializable
{
    private static final long serialVersionUID=1L;

    public TestManagedBean() {}
}

If this bean is accessed by an XHTML page with a query-string parameter named cid which is needed for a @ConversationScoped CDI managed bean (which may accidently/deliberately be appended by end-users too), an exception looking something like the following is thrown.

Severe:   Error Rendering View[/Test.xhtml]
org.jboss.weld.context.NonexistentConversationException: WELD-000321: No conversation found to restore for id 1
    at org.jboss.weld.context.AbstractConversationContext.initialize(AbstractConversationContext.java:259)
    at org.jboss.weld.context.http.LazyHttpConversationContextImpl.initialize(LazyHttpConversationContextImpl.java:68)
    at org.jboss.weld.context.http.LazyHttpConversationContextImpl.checkContextInitialized(LazyHttpConversationContextImpl.java:93)
    at org.jboss.weld.context.AbstractConversationContext.getCurrentConversation(AbstractConversationContext.java:445)
    at org.jboss.weld.jsf.ConversationAwareViewHandler.getActionURL(ConversationAwareViewHandler.java:111)
    at com.sun.faces.renderkit.html_basic.FormRenderer.getActionStr(FormRenderer.java:250)
    at com.sun.faces.renderkit.html_basic.FormRenderer.encodeBegin(FormRenderer.java:143)
    at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:864)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1854)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:456)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
    at java.lang.Thread.run(Thread.java:745)

Warning:   StandardWrapperValve[Faces Servlet]: Servlet.service() for servlet Faces Servlet threw exception
org.jboss.weld.context.NonexistentConversationException: WELD-000321: No conversation found to restore for id 1
    at org.jboss.weld.context.AbstractConversationContext.initialize(AbstractConversationContext.java:259)
    at org.jboss.weld.context.http.LazyHttpConversationContextImpl.initialize(LazyHttpConversationContextImpl.java:68)
    at org.jboss.weld.context.http.LazyHttpConversationContextImpl.checkContextInitialized(LazyHttpConversationContextImpl.java:93)
    at org.jboss.weld.context.AbstractConversationContext.getCurrentConversation(AbstractConversationContext.java:445)
    at org.jboss.weld.jsf.ConversationAwareViewHandler.getActionURL(ConversationAwareViewHandler.java:111)
    at com.sun.faces.renderkit.html_basic.FormRenderer.getActionStr(FormRenderer.java:250)
    at com.sun.faces.renderkit.html_basic.FormRenderer.encodeBegin(FormRenderer.java:143)
    at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:864)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1854)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:456)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
    at java.lang.Thread.run(Thread.java:745)

Can this exception be avoided anyway even though a parameter named cid is appended to the URL?


回答1:


This is specific to Weld (the implementation), not to CDI (the API). There's in the current Weld 2.2.x version no simple nor native way to disable it. Weld however allows you changing the request parameter name cid to something else via HttpConversationContext#setParameterName(). You could set it to e.g. an java.util.UUID value during application's startup.

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ApplicationScoped;
import org.jboss.weld.context.http.HttpConversationContext;

@ManagedBean(eager=true)
@ApplicationScoped
public class Application {

    @Inject
    private HttpConversationContext conversationContext;

    @PostConstruct
    public void init() {
        hideConversationScope();
    }

    /**
     * "Hide" conversation scope by replacing its default "cid" parameter name
     * by something unpredictable.
     */
    private void hideConversationScope() {
        conversationContext.setParameterName(UUID.randomUUID().toString());
    }

}

Unfortunately, CDI doesn't have any equivalent for eager=true. Alternative is, if you've EJB at hands:

import javax.ejb.Startup;
import javax.ejb.Singleton;

@Startup
@Singleton
public class Application {

(you might want to add @TransactionAttribute(NOT_SUPPORTED) to turn off unnecessary DB transaction management around it)

Or, if you've OmniFaces at hands:

import org.omnifaces.cdi.Startup;

@Startup
public class Application {



回答2:


There's a race condition in AbstractConversationContext when create first conversation scope if it's the first request of one session. Suppose such scenario

  1. User requests a jsf page
  2. weld creates a conversations map in the AbstractConversationContext.associate()
  3. Because it is the first request, there's no session. Weld keep this map in request
  4. A conversation scoped bean is created and put to the map.
  5. In somewhere, a session is created
  6. In the render phase, server sends partial response back. The page need some jsf resource, eg, jsf2 ajax or jsf resource
  7. Browser requests the new jsf resource
  8. At this time The first request has not finished. So it doesn't reach dissociate() and doesn't put conversations map in the session.
  9. Meanwhile The second request reach associate(). There's no conversations map in the session, and the session is existing. It puts its new map! <====
  10. Then, even the first request reach dissociate(), because there's already a map, it doesn't put its owner anymore. <====

A quick and dirty fix is always create session before associate(). However, it's better to merge the map in the dissociate()

Please see :

https://issues.jboss.org/browse/WELD-1418

WELD-1500 issue




回答3:


In the case of a servlet or other context supporting the web.xml context-param, you could set WELD_CONTEXT_ID_KEY as currently noted in the latest Weld documentation on supported environments:

<context-param>
   <param-name>WELD_CONTEXT_ID_KEY</param-name>
   <param-value>customValue</param-value>
</context-param>


来源:https://stackoverflow.com/questions/26744743/get-rid-of-org-jboss-weld-context-nonexistentconversationexception-when-a-query

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