2 Replies Latest reply on May 22, 2008 4:02 PM by David Beaumont

    Error redirecting to natural conversation

    Duncan Stockdill Newbie

      I am trying to redirect to a natural conversation at the end of a business process (i.e. a conversation), but get the following error


      java.lang.IllegalStateException: conversation id evaluated to null: PartyView
      
              at org.jboss.seam.navigation.ELConversationIdParameter.getParameterValue(ELConversationIdParameter.java:71)
      
              at org.jboss.seam.navigation.ELConversationIdParameter.getConversationId(ELConversationIdParameter.java:63)
      
              at org.jboss.seam.faces.FacesManager.beforeRedirect(FacesManager.java:76)
      
              at org.jboss.seam.faces.FacesManager.redirect(FacesManager.java:167)
      
              at org.jboss.seam.faces.Navigator.redirect(Navigator.java:46)
      
      



      section from pages.xml doing the redirect is as follows:


          <navigation from-action="#{partyNew.save}">
      
              <rule if-outcome="true">
      
                  <end-conversation before-redirect="true"/>
      
                  <redirect view-id="/party/home.xhtml">
      
                      <param name="partyId" value="#{newParty.id}"/>
      
                  </redirect>
      
              </rule>
      
          </navigation> 



      The natural conversation is specified as


      <conversation name="PartyView" parameter-name="partyId" parameter-value="#{partyController.partyId}"/>



      And the page being started for the new conversation uses the following to start the conversation


      <param name="partyId" value="#{partyController.partyId}"/>
      
      <action execute="#{partyController.init}"/>
      
      <begin-conversation join="true" flush-mode="MANUAL"/>
      
      ...



      PartyController isn't in scope of the first conversation, but I don't see why it should need to be.  If I manually browse to the url passing in the id, then Seam automatically starts the new conversation using the given id as the conversation id - why shouldn't this behave in the same way on a redirect?  I have tried with and without before-redirect="true" on the end-conversation.

        • 1. Re: Error redirecting to natural conversation
          Pete Muir Master

          Yes, this should probably work.


          Can you file a JIRA issue, and attach reproduction steps or an example? Thanks!

          • 2. Re: Error redirecting to natural conversation
            David Beaumont Newbie

            Hello All,


            I am having a similar problem to this, but with only a single page. This page is an entity home page with the entity being selected based on a page parameter. I have set this page parameter to be the natural conversation id so that when a form is submitted on it, actions on the same SFSB are executed. This means if the user hits back and then visits the same page for a different object they will see that object and not the last one they looked at (I had problems with conversations continuing on out of the current page without natural conversations).


            The problem is that when I run the action methods approveCcr() or rejectCcr() in the SFSB below, the user is redirected back to the same page with the natural conversation parameter set, but an error page is shown. The exception is:


            14:42:59,289 ERROR [STDERR] May 22, 2008 2:42:59 PM com.sun.facelets.FaceletViewHandler handleRenderException
            SEVERE: Error Rendering View[/ccrs/ccr.xhtml]
            javax.el.ELException: /ccrs/ccr.xhtml: Error reading 'ccr' on type org.javassist.tmp.java.lang.Object_$$_javassist_2
                 at com.sun.facelets.compiler.TextInstruction.write(TextInstruction.java:48)
                 ...
            Caused by: javax.ejb.NoSuchEJBException: Could not find stateful bean: 3lcw53-2i0tx7-fgjd4rnj-1-fgje8ndc-g
                 at org.jboss.ejb3.cache.simple.SimpleStatefulCache.get(SimpleStatefulCache.java:390)
                 at org.jboss.ejb3.cache.simple.SimpleStatefulCache.get(SimpleStatefulCache.java:375)
                 at org.jboss.ejb3.stateful.StatefulInstanceInterceptor.invoke(StatefulInstanceInterceptor.java:61)
                 ...
            



            If I highlight the address in the browser and issue another get request, everything works fine and the object is freshly retrieved as desired its updated properties.


            These Ccr objects aren't created through the /ccrs/ccr.xhtml view - the form on this page is to add objects of another type to the Ccr.ccrAudits collection. If I don't try and end the conversation before showing the view again the Ccr being shown doesn't have the updated collection, though it is the correct Ccr. (I have tried forcing the object to be updated with entityManager.refresh(this.ccr) at the end of the requested action method but hibernate gives an exception something along the lines of 'session not open'.)


            Am I having the same problem as above (and can I help fix?) or have I created a different bug?


            Thanks!

            Dave


            /ccrs/ccr.xhtml


            <h1>CCR - #{ccrHome.ccr.title}</h1>
                 <p>Code: #{ccrHome.ccr.ccrCode}<br/>
                 Status: <h:outputText value="#{(ccrHome.ccr.completed eq true) ? ' Completed' : ' Open'}" /><br/>
                 Effective: #{ccrHome.ccr.effective}</p>
                 <h2>Audit Trail</h2>
                 <h:outputText value="No audit history exists." rendered="#{empty ccrHome.ccr.ccrAudits}" />
                 <ol>
                      <ui:repeat value="#{ccrHome.ccr.ccrAudits}" var="ccrAudit">
                           <li>#{ccrAudit.ccrAuditAction.name} by &#160;
                                <s:link value="#{ccrAudit.contact.name}" view="/contacts/contact.xhtml">
                                     <f:param name="contactId" value="#{ccrAudit.contact.id}" />
                                </s:link>
                            on #{ccrAudit.timeStamp}</li>
                      </ui:repeat>
                 </ol>
                 <h:form rendered="#{ccrHome.ccr.completed eq false}">
                      <fieldset>
                           <legend>Approve or Reject this CCR</legend>
                           <label for="ccrAuditDetails">Details</label>
                                <h:inputTextarea value="#{ccrHome.ccrAudit.details}" id="ccrAuditDetails" /><br/>
                      </fieldset>
                      <h:commandButton action="#{ccrHome.approveCcr}" value="Approve CCR" class="submit" conversationName="ccrHomePage">
                           <!--<s:conversationPropagation type="end" />-->
                      </h:commandButton>
                      <h:commandButton action="#{ccrHome.rejectCcr}" value="Reject CCR" class="submit" conversationName="ccrHomePage">
                           <!--<s:conversationPropagation type="end" />-->
                      </h:commandButton><br/>
                 </h:form>
            



            relevant pages.xml


            <conversation name="ccrHomePage" parameter-name="ccrId" parameter-value="#{ccrHome.ccr.id}" />
                 
                 <page view-id="/ccrs/ccr.xhtml" conversation="ccrHomePage">
                      <begin-conversation join="false" /> <!-- TODO Why is this needed? -->
                      <navigation>
                           <rule if-outcome="approved">
                                <redirect view-id="/ccrs/ccr.xhtml">
                                     <param name="ccrId" value="#{ccrHome.ccr.id}" />
                                </redirect>
                           </rule>
                           <rule if-outcome="rejected">
                                <redirect view-id="/ccrs/ccr.xhtml">
                                     <param name="ccrId" value="#{ccrHome.ccr.id}" />
                                </redirect>
                           </rule>
                      </navigation>
                 </page>
            



            CcrHomeBean.java


            @Stateful
            @Name("ccrHome")
            public class CcrHomeBean implements CcrHome {
                 
                 @PersistenceContext
                 EntityManager mudEntityManager;
                 
                 @RequestParameter
                 Integer ccrId;
                 Ccr ccr;
                 CcrAudit ccrAudit;
                 OrganisationName organisationName;
                 OrganisationName organisationNameOrig;
            
                 ... some getters/setters removed
                 
                 @Begin // ignore this, run from another page entirely.
                 public String newOrganisationNameChange() {
                      this.ccr.setCcrType(mudEntityManager.find(CcrType.class, 1));
                      this.organisationName.setOrganisation(this.organisationNameOrig.getOrganisation());
                      this.organisationName.setCcr(this.ccr);
                      return "confirm";
                 }
                 
                 @End
                 public String cancelCcr() {
                      return "cancelled";
                 }
            
                 @End(beforeRedirect=true)
                 public String confirmCcr() {
                      mudEntityManager.persist(this.ccr);
                      this.ccrAudit.setTimeStamp(new Date());
                      mudEntityManager.persist(this.ccrAudit);
                      mudEntityManager.persist(this.organisationName);
                      return "confirmed";
                 }
                 
                 @End(beforeRedirect=true)
                 public String approveCcr() {
                      this.ccr.setCompleted(true);
                      this.ccrAudit.setCcrAuditAction(mudEntityManager.find(CcrAuditAction.class, 5));
                      this.ccrAudit.setTimeStamp(new Date());
                      mudEntityManager.merge(this.ccr);
                      mudEntityManager.persist(this.ccrAudit);
                      return "approved";
                 }
                 
                 @End(beforeRedirect=true)
                 public String rejectCcr() {
                      this.ccrAudit.setCcrAuditAction(mudEntityManager.find(CcrAuditAction.class, 4));
                      this.ccrAudit.setTimeStamp(new Date());
                      mudEntityManager.persist(this.ccrAudit);
                      return "rejected";
                 }
                 
                 //@PostConstruct TODO - why doesn't this work?
                 @Create
                 public void initialize() {
                      if(this.ccrId==null) {
                           this.ccr = new Ccr();
                           this.ccr.setCompleted(false);
                           this.ccrAudit = new CcrAudit();
                           this.ccrAudit.setContact(mudEntityManager.find(Contact.class, 1));
                           this.ccrAudit.setCcrAuditAction(mudEntityManager.find(CcrAuditAction.class, 1));
                           this.ccrAudit.setCcr(this.ccr);
                           // TODO - line below needs to be generalised for different types of ccr
                           this.organisationName = new OrganisationName();
                      } else {
                           this.ccr = mudEntityManager.find(Ccr.class, this.ccrId);
                           // TODO - the next few lines are probably not the correct way of doing this - waste of objects.
                           // Should probably use @In(required=false) and set up the ccr relation at persist time.
                           if (!this.ccr.getCompleted()) {
                                // If the CCR is completed the GUI won't let them add changes or audit trail info anyway.
                                this.ccrAudit = new CcrAudit();
                                this.ccrAudit.setCcr(this.ccr);
                                this.ccrAudit.setContact(mudEntityManager.find(Contact.class, 1));
                           }
                      }
                 }
                 
                 @Remove
                 @Destroy
                 public void destroy() {}
            
            }
            



            Ccr.java


            @Entity
            @Table(name="ccrs")
            public class Ccr {
                 
                 private Integer id;
                 private String title;
                 private String ccrCode;
                 private Boolean completed;
                 private Date effective;
                 private CcrType ccrType;
                 private Collection<CcrAudit> ccrAudits;
            
                 @Id
                 @GeneratedValue
                 @Column(name="ccr_id")
                 public Integer getId() {return id;}
                 public void setId(Integer id) {this.id = id;}
                 
                 @Column(name="title")
                 public String getTitle() {return title;}
                 public void setTitle(String title) {this.title = title;}
                 
                 @Column(name="ccr_code")
                 public String getCcrCode() {return ccrCode;}
                 public void setCcrCode(String ccrCode) {this.ccrCode = ccrCode;}
                 
                 @Column(name="completed")
                 public Boolean getCompleted() {return completed;}
                 public void setCompleted(Boolean completed) {this.completed = completed;}
                 
                 @Column(name="effective")
                 public Date getEffective() {return effective;}
                 public void setEffective(Date effective) {this.effective = effective;}
                 
                 @ManyToOne
                 @JoinColumn(name="ccr_type_id",referencedColumnName="ccr_type_id")
                 public CcrType getCcrType() {return ccrType;}
                 public void setCcrType(CcrType ccrType) {this.ccrType = ccrType;}
                 
                 @OneToMany(mappedBy="ccr")
                 public Collection<CcrAudit> getCcrAudits() {return ccrAudits;}
                 public void setCcrAudits(Collection<CcrAudit> ccrAudits) {this.ccrAudits = ccrAudits;}
            
            }