2 Replies Latest reply on Nov 22, 2011 5:23 AM by Pawel Marks

    Missing conversation entry with Seam 2.0.1.GA

    Guillaume Jeudy Master

      Hi,


      I'm using JBoss AS 4.2.2.GA with Seam 2.0.1.GA. I'm having weird issues that I cannot reproduce and only QA can reproduce.


      Usecase: A nested conversation is started, the user tabs through the fields of a simple form without populating them, hits Cancel button and gets a Missing conversation entry exception.


      java.lang.IllegalStateException: missing conversation entry
           org.jboss.seam.core.Conversation.flush(Conversation.java:124)
           org.jboss.seam.core.Manager.flushConversationMetadata(Manager.java:888)
           org.jboss.seam.faces.FacesManager.prepareBackswitch(FacesManager.java:283)
           org.jboss.seam.jsf.SeamPhaseListener.beforeRenderResponse(SeamPhaseListener.java:475)
           org.jboss.seam.jsf.SeamPhaseListener.beforeServletPhase(SeamPhaseListener.java:144)
           org.jboss.seam.jsf.SeamPhaseListener.beforePhase(SeamPhaseListener.java:114)
           com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:222)
           com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:144)
           javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)
           org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
           org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
           org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
           org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85)
           org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
           org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
           org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:154)
           org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:260)
           org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:366)
           org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:493)
           org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:60)
           org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
           org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
           org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
           org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
           com.archinsurance.reference.web.filter.ProfilingFilter.doFilter(ProfilingFilter.java:43)
           org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
           org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
           jcifs.http.NtlmHttpFilter.doFilter(NtlmHttpFilter.java:125)
           org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
           org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
           org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
           org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
           org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
           org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
           org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
           org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
           org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
           org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
           org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
           org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
           org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
           org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
           org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
           org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
           org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
           java.lang.Thread.run(Thread.java:595)
      



      More details on the usecase:


      The conversation is started with:

      @Begin(nested=true)

      .


      The ajax-validated fields on the form are using this facelets fragment:


      <a4j:outputPanel id="outpane"> 
           <s:decorate id="decorate" template="decorateField.xhtml">
                <ui:define name="label">#{label}</ui:define>
                <h:inputText required="true" value="#{entityBean.fieldName}">
                     <a4j:support event="onblur" reRender="outpane" bypassUpdates="true" ajaxSingle="true" />
                </h:inputText>
           </s:decorate>
      </a4j:outputPanel>



      decorateField.xhtml:


      <ui:composition  xmlns="http://www.w3.org/1999/xhtml"
                       xmlns:ui="http://java.sun.com/jsf/facelets"
                       xmlns:h="http://java.sun.com/jsf/html"
                       xmlns:f="http://java.sun.com/jsf/core"
                       xmlns:s="http://jboss.com/products/seam/taglib">
                       
          <div class="entry">
              <s:label styleClass="label #{invalid?'errors':''}">
                  <ui:insert name="label" />
                  <s:span styleClass="required" rendered="#{required}">*</s:span>
              </s:label>
              <span class="input #{invalid?'errors':''}">
                  <s:validateAll>
                      <ui:insert/>
                  </s:validateAll>
              </span>
              <s:message id="errormessage" styleClass="errors"/>
          </div>
          
      </ui:composition>



      Since the input field is required=true then JSF validation cycle is short-circuited and doesn't even get to trigger the hibernate validation so I assume that my problem is not the same as the one described here.



      The cancel button ends the nested conversation and redirect to the parent conversation page using:


      <s:button action="#{conversation.endAndRedirect}" value="Cancel" />



      This is when the exception is thrown on the server-side. The most troubling thing is that only QA can reproduce the problem. The QA tester is located in the Philippines while the server is located in NY. I believe the only thing that would explain why I can't reproduce on my end is the connection latency. I looked at the source code and it does seem like there is an important TODO that is still not implemented in Seam 2.2.0.GA. Could that be the reason of the problems im having?


      Conversation.java
      
      //we need to flush this stuff asynchronously to handle 
      //nested and temporary conversations which have no
      //ConversationEntry
      
      



      My theory is that there could be an ajax request linked to the nested conversation still concurrently executing while i'm about to flush the conversation in the conversation cancel thread. For some reasons this could cause the exception to be thrown. Any insights from Seam experts appreciated.



      Thanks!
      -Guillaume