6 Replies Latest reply on Nov 5, 2007 10:30 AM by greko

    Another conversation question ...

    greko

      Hi all !

      I have a screen displaying a list of devices. A device can be edited (from a button in the datatable)
      When a submit a find on my deviceList screen, I start a new conversation.
      When I edit a device, a create a nested conversation : once on my edit screen, I want to be able to go back to my previous search (aka the parent conversation).

      The problem :
      When a perform a save, on my edit screen, everything seems ok (faces message ok, entity updated). But then, when I click on my cancel/back button, to go back to my list, it is empty ... I mean, everything is still in the conversation (my search panel, even the rowCount of the list) but the list contains null elements ...

      Here is part of my code :

      pages.xml

      ...
       <page view-id="/parc_deviceList.xhtml" no-conversation-view-id="/parc_deviceList.xhtml">
       <description>Device Search (Results: #{deviceSearch.rowCount})</description>
       </page>
      ...
       <page view-id="/parc_deviceEdit.xhtml">
       <description>Edit Device</description>
       <param name="deviceId" value="#{deviceHome.deviceId}"/>
       <action execute="#{deviceHome.init}"/>
       <begin-conversation flush-mode="MANUAL" join="true"/>
       <navigation>
       <rule if-outcome="updated">
       <redirect view-id="/parc_deviceEdit.xhtml">
       </redirect>
       </rule>
       </navigation>
       </page>
      ...
      


      parc_deviceList.xhtml
      ...
       <h:commandLink id="find" styleClass="button"
       action="#{deviceSearch.find()}"
       tabindex="6">
       <s:conversationPropagation type="join" />
       <h:outputText styleClass="buttonLabel" value="#{messages['findButton']}"/>
       </h:commandLink>
      ...
       <h:dataTable id="deviceTable" var="d"
       value="#{devicesList}"
      ...
       <h:column>
       <f:facet name="header"> </f:facet>
      
       <s:link view="/parc_deviceEdit.xhtml" propagation="nest" title="#{messages['device.edit']}">
       <h:graphicImage value="/img/bt_mini_edit.gif" style="border:0; padding:2px;" />
       <f:param name="deviceId" value="#{d.id}"/>
       </s:link>
       </h:column>
      ...
      


      parc_deviceEdit.xhtml
       <h:form id="deviceEditForm">
       <div class="formFields wideLabels formBorder">
       <s:validateAll>
      ...
       </s:validateAll>
       </div>
      
       <div class="formControls wideLabels">
       <div class="entry">
       <div class="label"> </div>
       <div class="input">
       <h:commandLink id="update" styleClass="button"
       action="#{deviceHome.update}"
       tabindex="9">
       <span class="buttonLabel">#{messages['saveButton']}</span>
       </h:commandLink>
      
       <s:link id="cancel" styleClass="button" view="/parc_deviceList.xhtml"
       tabindex="9">
       <span class="buttonLabel">#{messages['cancelButton']}</span>
       </s:link>
       </div>
       </div>
       </div>
      
      


      DeviceHome.java
      @Name("deviceHome")
      @Scope(ScopeType.CONVERSATION)
      public class DeviceHome extends EntityHome<RTHDevice> {
      
       @Logger
       private Log logger;
      
      
       public Long getDeviceId() {
       return (Long)getId();
       }
      
       public void setDeviceId(Long deviceId) {
       setId(deviceId);
       }
      
       public void init() {
       logger.debug("DeviceHome.init()");
      
       if (isManaged()) {
       } else {
       }
       }
      
       public String persist() {
       logger.debug("DeviceHome.persist()");
       getInstance().setActive(0);
      
       return super.persist();
       }
      
       public String update() {
       logger.debug("DeviceHome.update()");
       return super.update();
       }
      }
      


      DeviceSearchAction.java
      @Stateful
      @Scope(ScopeType.CONVERSATION)
      @Name("deviceSearch")
      @Restrict("#{identity.loggedIn}")
      public class DeviceSearchAction implements DeviceSearch, Serializable {
      ...
       @DataModel
       List<RTHDevice> devicesList;
      ...
      


      I can't figure out why this happens.
      Could you help me a few ?

      I'm currently using seam 2.0.0.CR1 on JBoss 4.2.1.GA.

      Thanks for your help !

        • 1. Re: Another conversation question ...
          pmuir

          You've outjected a variable into conversation scope and as you are in the same conversation the original value is still there and not recreated.

          Try using an afterTransactionSuccess event as documented here http://docs.jboss.org/seam/2.0.0.CR3/reference/en/html/framework.html#d0e6304

          • 2. Re: Another conversation question ...
            greko

            Hi Pete !

            Thanks for your reply.

            I've updated my code so that I always stay in the same conversation (no more nested).

            I've also added this :

            DeviceSearchAction.java

             @Observer("org.jboss.seam.afterTransactionSuccess.RTHDevice")
             public void refreshDevices() {
             logger.debug("refreshDevices() method called.");
             queryDevices();
             }
            


            But I still have a problem : If I perform a submit on my edit screen, and the validation fails, my data is gone and not recreated. So if I click my cancel button, whithout finishing my transaction, I return to my previous list with empty data.
            Is there another event to observe ? Or should I refresh my data each time I return to my list ?

            Thanks a lot !

            • 3. Re: Another conversation question ...
              pmuir

              Given your app design, this would seem sensible.

              • 4. Re: Another conversation question ...
                greko

                That is what I thought.

                But what would be the best app design, given such a simple scenario ?
                I could use a session context, but my data will remain in the session, whereas a conversation will be automatically timeout-ed ...

                Am I right, or is my approch wrong ?

                • 5. Re: Another conversation question ...
                  pmuir

                  You should decide what scope makes sense for your application and make Seam do the right thing, not the other way around ;)

                  Session scope makes sense if you want the same result list to be displayed without the user hitting Search again whilst they are logged in. A nested conversation makes sense if you want to hold the list in a conversation and atomically edit entities.

                  • 6. Re: Another conversation question ...
                    greko

                    I agree with you Pete !
                    And actually, that's what I am trying to do.

                    I want my search->edit->back-to-search lifecycle to be managed with conversations.

                    I'm working on it, and the main problem is still the same : how to return to my parent conversation (the result list) without loosing data ...?