3 Replies Latest reply on May 5, 2009 6:27 PM by gonorrhea

    Conversation after lookup lost

    sandman202

      I have an edit screen (PhoneEdit.xhtml) and on the screen there is a lookup to the user listing(UzerList.xhtml) to select the user. On the screen there are 4 fields: number, extension, type and user. If I enter data on the fields and then click on the select user button to select the user, once I come back to the PhoneEdit.xhtml screen all of the other data is lost.


      PhoneEdit.xhtml


      <ui:define name="body">
               
          <h:form id="phone" styleClass="edit">
      
               <rich:panel>
                  <f:facet name="header">#{phoneHome.managed ? 'Edit' : 'Add'} Phone</f:facet>            
      
                     <s:decorate id="typeField" template="/layout/edit.xhtml">
                          <ui:define name="label">Type</ui:define>
                          <h:selectOneMenu id="type" 
                                           value="#{phoneHome.instance.type}" 
                                       required="true">
                               <s:selectItems var="_type" value="#{phoneTypeCategories}"
                                    label="#{_type.label}" noSelectionLabel="-- Select --"/>
                               <s:convertEnum/>
                               <a4j:support event="onblur" reRender="typeField" bypassUpdates="true" ajaxSingle="true"/>
                          </h:selectOneMenu>
                     </s:decorate>
                          
                  <s:decorate id="numberField" template="/layout/edit.xhtml">
                      <ui:define name="label">Number</ui:define>
                      <h:inputText id="number" 
                              required="true"
                                value="#{phoneHome.instance.phoneNumber}">
                          <a4j:support event="onblur" reRender="numberField" bypassUpdates="true" ajaxSingle="true"/>                          
                      </h:inputText>                          
                  </s:decorate>
                              
                  <s:decorate id="extField" template="/layout/display.xhtml">
                      <ui:define name="label">Ext</ui:define>
                      <h:inputText id="ext"
                                value="#{phoneHome.instance.ext}">
                          <a4j:support event="onblur" reRender="extField" bypassUpdates="true" ajaxSingle="true"/>                          
                      </h:inputText>
                  </s:decorate>
                         
                  <div style="clear:both">
                      <span class="required">*</span> 
                      required fields
                  </div>
                  
              </rich:panel>
      
              <div class="actionButtons">
                  <h:commandButton id="save" 
                                value="Save" 
                               action="#{phoneHome.persist}"
                             disabled="#{!phoneHome.wired}"
                             rendered="#{!phoneHome.managed}"/>                   
                  <h:commandButton id="update" 
                                value="Save" 
                               action="#{phoneHome.update}"
                             rendered="#{phoneHome.managed}"/>                  
                  <h:commandButton id="delete" 
                                value="Delete" 
                               action="#{phoneHome.remove}"
                            immediate="true"
                             rendered="#{phoneHome.managed}"/>                  
                  <s:button propagation="end"              
                                     id="done"
                                  value="Done"
                                   view="/role/admin/Phone.xhtml"
                               rendered="#{phoneHome.managed}"/>
                  <s:button propagation="end"
                                         id="cancel" 
                                  value="Cancel"
                                   view="#{empty phoneFrom ? '/role/admin/PhoneList' : phoneFrom}.xhtml"
                               rendered="#{!phoneHome.managed}"/>                         
              </div>
                               
               
              
          </h:form>
             
          
      <rich:tabPanel switchType="ajax">   
          <rich:tab label="User *" labelClass="required">
          <div class="association" id="uzerParent">   
              <h:outputText value="There is no user associated with this phone." 
                         rendered="#{phoneHome.instance.uzer == null}"/>
              
              <rich:dataTable var="_uzer" 
                         value="#{phoneHome.instance.uzer}" 
                      rendered="#{phoneHome.instance.uzer != null}"
                    rowClasses="rvgRowOne,rvgRowTwo"
                            id="uzerTable">
                  <h:column>
                      <f:facet name="header">id</f:facet>
                      #{_uzer.id}
                  </h:column>
                  <h:column>
                      <f:facet name="header">name</f:facet>
                      #{_uzer.name}
                  </h:column>
                  <h:column>
                      <f:facet name="header">email</f:facet>
                      #{_uzer.email}
                  </h:column>
                  <h:column>
                      <f:facet name="header">action</f:facet>
                      <s:link view="/role/admin/Uzer.xhtml" id="viewUzer" value="View" propagation="none">
                          <f:param name="uzerId" value="#{_uzer.id}"/>
                          <f:param name="uzerFrom" value="/role/admin/PhoneEdit"/>
                      </s:link>
                  </h:column>
              </rich:dataTable>
              
              <div class="actionButtons">
                  <ui:remove>
                  <!-- pg 404 -->
                   <h:commandButton value="Select Uzer" action="selectUzer"/>
                   </ui:remove>
                   
                  <s:button value="Select User"
                             view="/role/admin/UzerList.xhtml">
                      <f:param name="from" value="/role/admin/PhoneEdit"/>
                  </s:button>
              </div>
                             
          </div>
          </rich:tab>
      </rich:tabPanel>      
      </ui:define>
      



      PhoneEdit.page.xml


      <page xmlns="http://jboss.com/products/seam/pages"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.0.xsd"
            no-conversation-view-id="/role/admin/PhoneList.xhtml"
            login-required="true">
            
         <begin-conversation join="true" />
         
         <action execute="#{phoneHome.wire}"/>
         
         <param name="phoneFrom"/>
         <param name="phoneId" value="#{phoneHome.phoneId}"/>
         <param name="uzerFrom"/>
         <param name="uzerId" value="#{uzerHome.uzerId}"/>
      
      
      
         <navigation from-action="#{phoneHome.persist}">
             <end-conversation/>
             <redirect view-id="/role/admin/Phone.xhtml"/>
         </navigation>
         
         <navigation from-action="#{phoneHome.update}">
             <end-conversation/>
             <redirect view-id="/role/admin/Phone.xhtml"/>
         </navigation>
         
           <navigation from-action="#{phoneHome.remove}">
                <rule if-outcome="removed">
                     <end-conversation/>
                     <redirect view-id="/role/admin/PhoneList.xhtml"/>
                </rule>
           </navigation>
         
      </page>
      



      PhoneHome.java


      @Name("phoneHome")
      public class PhoneHome extends EntityHome<Phone>
      {
           private static final long serialVersionUID = 808288839702541761L;
           
           @In(create = true)
           private UzerHome uzerHome;
               
           public void setPhoneId(Long id) {
                setId(id);
           }
      
           public Long getPhoneId() {
                return (Long) getId();
           }
           
           
           @Override
           protected Phone createInstance() {
                Phone phone = new Phone();
                return phone;
           }
           
           /**
            * Add the phone to the phones collection on uzer so that
            * it is reflected in the UI immediately. Once the conversation ends
            * the collection will be refreshed, but before then the new phone
            * won't be visible.
            */
           @Override
           public String persist() {
                String result = super.persist();
                getInstance().getUzer().getPhones().add(getInstance());
                return result;
           }     
           
           public void wire() {
                getInstance();
                Uzer uzer = uzerHome.getDefinedInstance();
                if (uzer != null) {
                     getInstance().setUzer(uzer);
                }
           }     
      
           public boolean isWired() {
                if (getInstance().getUzer() == null) {
                     return false;
                }
                return true;
           }     
           
           public Phone getDefinedInstance() {
                return isIdDefined() ? getInstance() : null;
           }
      
           @Factory(value = "phoneTypeCategories", scope = ScopeType.CONVERSATION)
           public PhoneType[] getPhoneTypeCategories() {
                return PhoneType.values();
           }
      }
      



      Could someone please tell me what I am missing or doing wrong?


      Thanks,
      Scott

        • 1. Re: Conversation after lookup lost
          gonorrhea

          EntityHome class extends Home class which is demarcated with @Scope(value=CONVERSATION).  I don't see any @Begin or @End annotations in your PhoneHome class.  I don't usually use SAF API, but in Seam, generally speaking, there is always a temporary conversation.  If you use @Begin, then the temp conversation will get promoted to LRC.


          Do you have a LRC going in this use case? If you have debug enabled (this is default), you can check by navigating to /debug.seam page.  If there is no LRC, that may explain the behavior you're seeing.


          The SAF is a little too complicated for me to mentally digest so I usually stick with writing my custom facelets and business components after revengr the schema...



          • 2. Re: Conversation after lookup lost
            sandman202

            Arbi, thanks for your input. I might be heading down that path as the software develops. The format I am using is similar to that in Seam in Action, with a few enhancements with sorting columns on tabs.


            I did figure out what my problem was. I had to change...


            <a4j:support event="onblur" reRender="numberField" bypassUpdates="true" ajaxSingle="true"/>
            



            to


            <a4j:support event="onblur" reRender="numberField" ajaxSingle="true"/>                          
            



            to allow the updates to take place on the backing bean.


            • 3. Re: Conversation after lookup lost
              gonorrhea

              Yes, bypassUpdates="true" is used typically when performing live validation (e.g. event="onblur") and will skip the Update Model Values phase (setter methods) and Invoke Application phase, skipping to Render Response even if validation passes.  This is used typically as a performance optimization and the setter methods get called when user submits the form.


              Good catch.