6 Replies Latest reply on Oct 3, 2008 4:25 PM by Damian Harvey

    Form values not updated if using Ajax validation

    Bolke de Bruin Newbie

      Hi,


      I am experiencing an issue which seems related to these (...) posts,
      but isn't entirely the same as far as I can determine.


      The issue is that when I change a form field that is subsequentlty validated by an Ajax request
      (see below for the xhtml code) and then select a different item that updates the entire form (thus without saving anything),
      the form fields that were change don't update.


      For the snippet below this means that when I change the value of chemical.un, wait for the validation, and then change
      the overall chemical value (ie. select a different chemical), the value I have changed doesn't update (ie. 1005 stays 1005 instead of becoming 1020 after selecting a different item).


      It seems like a jsf-lifecycle issue to me, but I might be entirely wrong. I would like to invalidate the model somehow, but don't know how to do it. But on the otherhand I might misunderstand the issue. Does anyone have an idea?


      Thanks


      <s:decorate id="chemicalUn" template="/layout/edit.xhtml">
           <h:inputText value="#{chemical.un}" required="true">
           <a:support event="onblur" reRender="chemicalUn" bypassUpdates="true" eventsQueue="queue" ajaxSingle="true">
                <s:conversationId/> 
           </a:support>
      </s:decorate>
      



      
      import java.util.ArrayList;
      import java.util.Date;
      import java.util.Iterator;
      import java.util.List;
      import java.util.Locale;
      import javax.ejb.Remove;
      import javax.ejb.Stateful;
      import javax.faces.application.FacesMessage;
      import javax.persistence.EntityManager;
      
      import nl.chainsoftware.chemix.model.Chemical;
      import nl.chainsoftware.chemix.model.ChemicalOverride;
      import nl.chainsoftware.chemix.model.Compatibility;
      import nl.chainsoftware.chemix.model.Material;
      import nl.chainsoftware.chemix.model.TankgroupChemicalException;
      import nl.chainsoftware.chemix.model.Translation;
      import nl.chainsoftware.chemix.model.User;
      import nl.chainsoftware.chemix.model.notes.ChemicalNote;
      import nl.chainsoftware.chemix.model.notes.ChemicalNoteConnector;
      import nl.chainsoftware.chemix.util.ListLocaleSelector;
      import nl.chainsoftware.chemix.util.NoteSelectItem;
      
      import org.jboss.seam.annotations.Begin;
      import org.jboss.seam.annotations.End;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.In;
      import org.jboss.seam.annotations.Logger;
      import org.jboss.seam.annotations.Out;
      import org.jboss.seam.annotations.security.Restrict;
      import org.jboss.seam.core.Events;
      import org.jboss.seam.annotations.Factory;
      
      import org.jboss.seam.log.Log;
      import org.jboss.seam.faces.FacesMessages;
      
      @Stateful
      @Name("chemicalManager")
      @Restrict("#{identity.loggedIn}")
      public class ChemicalManagerBean implements ChemicalManager {
           
          @Logger 
          private Log log;
           
          @In 
          FacesMessages facesMessages;
          
          @In(create=true)
          ListLocaleSelector listLocaleSelector;
          
          @In
          private EntityManager entityManager;
          
          @In(create=true)
          @Out
          private Chemical chemical;
                
          @In
           private Events events;    
          
          @In
          private User currentUser;
          
          @In(create=true)
          @Out
          private List<NoteSelectItem> notes;
          
          @In(required=false)
          @Out(required=false)
          private ChemicalOverride override;
          
          @Begin(join=true)
           public void select(Chemical selectedChemical) {
                log.info("ChemicalManager.select() called with chemical id: " + selectedChemical.getId());
                
                chemical = selectedChemical;
                
                checkLanguages();
                findNotes();
                
                facesMessages.addFromResourceBundle("#{messages['chemical.selected']}");
                
                log.info("ChemicalManager.select() exited with chemical id: " + selectedChemical.getId());
      
           }
      }
      


        • 2. Re: Form values not updated if using Ajax validation
          Damian Harvey Apprentice

          Show the rest of your page code. What changes the chemical?

          • 3. Re: Form values not updated if using Ajax validation
            Bolke de Bruin Newbie

            (I am including everything one by one as I have difficulties submitting)


            This is the full code (xhtml pages, javabean)


            This show a list of chemicals and allows to select one of them to refresh/reload the form in the middle.


            <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                                  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                 xmlns:s="http://jboss.com/products/seam/taglib"
                 xmlns:ui="http://java.sun.com/jsf/facelets"
                 xmlns:f="http://java.sun.com/jsf/core"
                 xmlns:h="http://java.sun.com/jsf/html"
                 xmlns:a="http://richfaces.org/a4j"
                 xmlns:rich="http://richfaces.org/rich"
                 xmlns:chemix="http://www.chainsoftware.nl/chemix"
                 template="layout/template.xhtml">
            
                 <ui:define name="left">
                      <rich:panel id="leftSideMenu">
                           <f:facet name="header">
                                #{messages.Chemical}
                           </f:facet>
                           <h:graphicImage value="/img/chemical.jpg" width="100%" />
                           <rich:spacer height="20px" />
                           <s:link view="/overrideListManager.xhtml" value="#{messages['overrideList.manager']}" /> <br />
                           <s:link view="/removalListManager.xhtml" value="#{messages['removalList.manager']}" />
                      </rich:panel>
                 </ui:define>
            
                 <ui:define name="body">
                      <rich:effect name="showTrans" for="translationsHolder" type="Appear" />
                      <rich:effect name="hideTrans" for="translationsHolder" type="Fade" />
                      <a:outputPanel id="chemicaldetail">
                           <ui:include src="detail/chemicalDetail.xhtml" />
                      </a:outputPanel>
                 </ui:define>
            
                 <ui:define name="right">
                      <a:form id="chemicallist">
                           <div id="itemList">
                                <ui:repeat value="#{chemicals}" var="c">
                                     <div class="item" id="item-#{c.id}">
                                               <div class="un">#{c.un} - </div>
                                               <div class="chemicalName">
                                                    <a:commandLink reRender="chemicaldetail" action="#{chemicalManager.select(c)}" onclick="highlightItem(this); " eventsQueue="queue" ajaxSingle="true" oncomplete="setEventHandlers();">
                                                         <chemix:translation language="#{localeSelector.language}" value="#{c.translations}" />
                                                    </a:commandLink>
                                               </div>               
                                     </div>
                                </ui:repeat>
                           </div>
                      </a:form>
                 </ui:define>
                 
            </ui:composition>
            




            • 4. Re: Form values not updated if using Ajax validation
              Bolke de Bruin Newbie

              The form


              <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                                    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
              <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                   xmlns:s="http://jboss.com/products/seam/taglib"
                   xmlns:ui="http://java.sun.com/jsf/facelets"
                   xmlns:f="http://java.sun.com/jsf/core"
                   xmlns:h="http://java.sun.com/jsf/html"
                   xmlns:a="http://richfaces.org/a4j"
                   xmlns:c="http://java.sun.com/jstl/core"
                   xmlns:rich="http://richfaces.org/rich"
                   xmlns:chemix="http://www.chainsoftware.nl/chemix">
              
                        <script language="javascript">
                        var translations_show = false;
                        
                        function translations() {
                             if (!translations_show) {
                                  showTrans({duration:0.7});
                                  translations_show = true;
                             } else { 
                                  hideTrans();
                                  translations_show = false;
                             }
                             
                             return false;
                        }
                        </script>
                        
                        <h:form id="chemicalForm" name="chemicalForm">
                             
                        <div class="messages">
                             <rich:messages globalOnly="true" errorClass="errorMessage" infoClass="infoMessage"/>
                        </div>
                                         
                        <s:validateAll>
                             
                          <chemix:actionButtons oncomplete="setHighlightedItem(#{chemical.id})" backingBean="#{chemicalManager}" searchPage="/chemicalManager.xhtml" reRender="chemicaldetail,chemicallist">
                               <chemix:dropDownMenu>
                                  <chemix:dropDownMenuItem enabled="false">#{messages['dropDownMenu.moreActions']}</chemix:dropDownMenuItem>               
                                  <chemix:dropDownMenuItem>
                                       <a:commandLink
                                            ajaxSingle="true"
                                            eventsQueue="queue"
                                            reRender="chemicaldetail,chemicallist"
                                      action="#{chemicalManager.remove}"
                                      rendered="#{chemicalManager.managed}"
                                      onclick="if(!confirm('#{messages['sureToRemoveThisItem']}')){return false;}"
                                      oncomplete="clearForm('#chemicalForm');">
                                      #{messages['chemical.delete']} 
                                  </a:commandLink>
                                  </chemix:dropDownMenuItem>
                                  <chemix:dropDownMenuItem>
                                        <a:commandLink 
                                            ajaxSingle="true" 
                                            eventsQueue="queue"
                                            reRender="chemicaldetail"
                                            action="#{chemicalManager.copy}" 
                                            rendered="#{chemicalManager.managed}">
                                            #{messages['chemical.makeCopy']} 
                                       </a:commandLink>
                                  </chemix:dropDownMenuItem>
                                  <chemix:dropDownMenuItem enabled="false">#{messages['overrideList.addOverrideToLists']}</chemix:dropDownMenuItem>
                                  <ui:repeat value="#{overrideLists}" var="list">
                                       <chemix:dropDownMenuItem>
                                             <a:commandLink 
                                                 ajaxSingle="true" 
                                                 eventsQueue="queue"
                                                 reRender="chemicaldetail"
                                                 action="#{chemicalOverrideManager.addOverrideToList(list, chemical)}" 
                                                 rendered="#{chemicalManager.managed}">
                                                 @#{list.name} 
                                            </a:commandLink>
                                       </chemix:dropDownMenuItem>
                                  </ui:repeat>
                             </chemix:dropDownMenu>
                        </chemix:actionButtons>     
                                  
                        <rich:tabPanel switchType="client">
                        <rich:tab label="#{messages['chemical.details']}">
                        
                        <table cellpadding="0" cellspacing="1" border="0" class="properties" styleClass="chemicalProperties" width="100%">
                             <col width="250px" />
                             <col />
                             <tbody>
                             
                                  <tr>
                                       <td>#{messages['chemical.un']}</td>
                                       <td>
                                            <s:decorate id="chemicalUn" template="/layout/edit.xhtml">
                                            <h:inputText value="#{chemical.un}" required="true">
                                                 <a:support event="onblur" reRender="chemicalUn" bypassUpdates="true" eventsQueue="queue" ajaxSingle="true">
                                                      <s:conversationId/> 
                                                 </a:support>
                                            </h:inputText>
                                            </s:decorate>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.name']}</td>
                                       <td>
                                            <a href="#" onclick="translations();">
                                                 <h:graphicImage value="img/edit-add.png" style="border: none"/>
                                            </a>
                                            <chemix:translation language="#{listLocaleSelector.language}" value="#{chemical.translations}" />
                                            <div id="translationsHolder" style="display:none">
                                            <a:outputPanel id="translations" styleClass="translations" layout="block">
                                                 <table width="100%" border="0">
                                                 <ui:repeat value="#{chemical.translations}" var="translation">
                                                      <tr>
                                                           <td>#{translation.language}:</td>
                                                           <td><h:inputTextarea value="#{translation.name}" cols="60" rows="5" /></td>
                                                      </tr>
                                                 </ui:repeat>
                                                 </table>
                                            </a:outputPanel>
                                            </div>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.class']}</td>
                                       <td>
                                            <s:decorate id="chemicalClassification" template="/layout/edit.xhtml">
                                            <h:inputText value="#{chemical.classification}" required="true">
                                                 <a:support event="onblur" reRender="chemicalClassification" bypassUpdates="true" eventsQueue="queue" ajaxSingle="true">
                                                      <s:conversationId/> 
                                                 </a:support>
                                            </h:inputText>
                                            </s:decorate>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.classificationCode']}</td>
                                       <td>
                                            <s:decorate id="chemicalClassificationCode" template="/layout/edit.xhtml">
                                            <h:inputText value="#{chemical.classificationCode}" required="true">
                                                 <a:support event="onblur" reRender="chemicalClassificationCode" bypassUpdates="true" eventsQueue="queue" ajaxSingle="true">
                                                      <s:conversationId/> 
                                                 </a:support>
                                            </h:inputText>
                                            </s:decorate>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.packingGroup']}</td>
                                       <td>
                                            <s:decorate id="chemicalPackageGroup" template="/layout/edit.xhtml">
                                            <h:inputText value="#{chemical.packageGroup}">
                                                 <a:support event="onblur" reRender="chemicalPackageGroup" bypassUpdates="true" eventsQueue="queue" ajaxSingle="true">
                                                      <s:conversationId/> 
                                                 </a:support>
                                            </h:inputText>
                                            </s:decorate>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.dangers']}</td>
                                       <td>
                                            <h:selectManyCheckbox value="#{chemical.dangers}" layout="pageDirection">
                                                 <s:selectItems value="#{enumLists.dangers}" var="danger" label="#{danger.code}"/>
                                                 <s:convertEnum />
                                            </h:selectManyCheckbox>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.tankerType']}</td>
                                       <td>
                                            <h:selectOneMenu value="#{chemical.tankType}">
                                                 <s:selectItems value="#{enumLists.tankTypes}" var="type" label="#{type}" />
                                                  <s:convertEnum />
                                          </h:selectOneMenu>
                                     </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.tankCondition']}</td>
                                       <td>
                                            <h:selectOneMenu value="#{chemical.tankCondition}">
                                                 <s:selectItems value="#{enumLists.conditions}" var="c" label="#{messages[c.key]}" />
                                                 <s:convertEnum />
                                          </h:selectOneMenu>                              
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.hullType']}</td>
                                       <td>
                                            <h:selectOneMenu value="#{chemical.hullType}">
                                                 <s:selectItems value="#{enumLists.hullTypes}" var="dev" label="#{messages[dev.key]}" />
                                                 <s:convertEnum />
                                          </h:selectOneMenu>                              
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.tankEquipment']}</td>
                                       <td>
                                            <h:selectOneMenu value="#{chemical.tankEquipment}">
                                                 <s:selectItems value="#{enumLists.tankEquipment}" var="e" label="#{messages[e.key]}" noSelectionLabel="#{messages['notAvailable']}" />
                                                 <s:convertEnum />
                                          </h:selectOneMenu>                              
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.relievePressure']}</td>
                                       <td>
                                            <s:decorate id="chemicalRelievePressure" template="/layout/edit.xhtml">
                                            <h:inputText value="#{chemical.relievePressure}" required="true">
                                                 <a:support event="onblur" reRender="chemicalRelievePressure" bypassUpdates="true" eventsQueue="queue" ajaxSingle="true">
                                                      <s:conversationId/> 
                                                 </a:support>
                                            </h:inputText>
                                            </s:decorate>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.maxFillRate']}</td>
                                       <td>
                                            <s:decorate id="chemicalMaxFillRate" template="/layout/edit.xhtml">
                                            <h:inputText value="#{chemical.maxFillRate}" required="true">
                                                 <a:support event="onblur" reRender="chemicalMaxFillRate" bypassUpdates="true" eventsQueue="queue" ajaxSingle="true">
                                                      <s:conversationId/> 
                                                 </a:support>
                                            </h:inputText>
                                            </s:decorate>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.densityAt20C']}</td>
                                       <td>
                                            <s:decorate id="chemicalDensity" template="/layout/edit.xhtml">
                                            <h:inputText value="#{chemical.density}" required="true">
                                                 <a:support event="onblur" reRender="chemicalDensity" bypassUpdates="true" eventsQueue="queue" ajaxSingle="true">
                                                      <s:conversationId/> 
                                                 </a:support>
                                            </h:inputText>
                                            </s:decorate>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.samplingDevice']}</td>
                                       <td>
                                            <h:selectOneMenu value="#{chemical.samplingDevice}">
                                                 <s:selectItems value="#{enumLists.samplingDevices}" var="dev" label="#{messages[dev.key]}" />
                                                 <s:convertEnum />
                                          </h:selectOneMenu>                              
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.allowUnderdeckPumproom']}</td>
                                       <td><h:selectBooleanCheckbox value="#{chemical.allowPumpRoom}" /></td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.temperatureClass']}</td>
                                       <td>
                                            <h:selectOneMenu value="#{chemical.temperatureClass}">
                                                 <s:selectItems value="#{enumLists.temperatureClasses}" var="class" label="#{class}" noSelectionLabel="No temperature class"/>
                                                  <s:convertEnum />
                                          </h:selectOneMenu>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.explosionGroups']}</td>
                                       <td>
                                            <h:selectOneMenu value="#{chemical.explosionGroup}">
                                                 <s:selectItems value="#{enumLists.explosionGroups}" var="group" label="#{group}" noSelectionLabel="No explosion group"/>
                                                  <s:convertEnum />
                                          </h:selectOneMenu>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.explosionProtectionRequired']}</td>
                                       <td><h:selectBooleanCheckbox value="#{chemical.explosionProtection}" /></td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.requiredEquipment']}</td>
                                       <td>
                                            <h:selectManyCheckbox value="#{chemical.equipment}">
                                                 <s:selectItems value="#{enumLists.equipment}" var="item" label="#{item}"/>
                                                 <s:convertEnum />
                                            </h:selectManyCheckbox>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.nrBlueLights']}</td>
                                       <td>
                                            <s:decorate id="chemicalBlueLights" template="/layout/edit.xhtml">
                                            <h:inputText value="#{chemical.bluelights}" required="true">
                                                 <a:support event="onblur" reRender="chemicalBlueLights" bypassUpdates="true" eventsQueue="queue" ajaxSingle="true">
                                                      <s:conversationId/> 
                                                 </a:support>
                                            </h:inputText>
                                            </s:decorate>
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.useOverrideOnly']}</td>
                                       <td>
                                            <h:selectBooleanCheckbox value="#{chemical.overrideOnly}" />
                                       </td>
                                  </tr>
                                  <tr>
                                       <td>#{messages['chemical.hasMultiplePositions']}</td>
                                       <td>
                                            <h:selectBooleanCheckbox value="#{chemical.multiplePositions}" />
                                       </td>
                                  </tr>                    
                                  
                             </tbody>
                        </table>
                        </rich:tab>
                        <rich:tab label="#{messages['chemical.compatibility']}">
                        <table cellpadding="0" cellspacing="1" border="0" class="properties">
                             <tbody>
                                  <ui:repeat value="#{chemical.compatibility}" var="c">
                                  <tr>
                                       <td>#{c.material.commonName}</td>
                                       <td>
                                            <h:selectOneMenu value="#{c.compatibilityStatus}">
                                                 <s:selectItems value="#{enumLists.status}" var="z" label="#{messages[z.key]}" />
                                                 <s:convertEnum />
                                          </h:selectOneMenu>                              
                                       </td>
                                  </tr>
                                  </ui:repeat>
                             </tbody>
                        </table>
                        </rich:tab>
                        <rich:tab label="#{messages['chemical.notes']}">
                             <ui:repeat value="#{notes}" var="note">
                                  <div class="chemicalNote">
                                       <div class="chemicalNoteCheckbox"><h:selectBooleanCheckbox value="#{note.selected}" onclick="changeTFstatus(this);" /></div> 
                                       <div class="chemicalNoteLabel">#{note.label}</div>
                                       <div class="chemicalNoteTxT"><h:inputText value="#{note.extra}" disabled="#{!note.selected}" /></div>
                                  </div>
                             </ui:repeat>
                        </rich:tab>
                        <rich:tab label="#{messages['chemical.internalNotes']}">
                             <h:inputTextarea value="#{chemical.internalNote}" cols="100" rows="20"/>
                        </rich:tab>          
                        <c:if test="${!empty chemical.overrides}">
                             <rich:tab label="#{messages['chemical.overrides']}">
                                  <div id="chemicalOverridesTab">
                                  </div>
                             </rich:tab>          
                        </c:if>
                        </rich:tabPanel>
                        </s:validateAll>
                        </h:form>
                        
                        <ui:include src="/detail/editOverridePanel.xhtml" >
                           <ui:param name="refresh" value="chemicaldetail"/>
                        </ui:include>
              
                        <c:if test="${!empty chemical.overrides}">
                                  <script type="text/javascript" language="javascript">
                                       var names = [
                                            "#{messages['overrideList.name']}",
                                            "#{messages['chemical.un']}",
                                            "#{messages['chemical.name']}",
                                            "#{messages['chemical.class']}",
                                            "#{messages['chemical.classificationCode']}",
                                            "#{messages['chemical.packingGroup']}",
                                            "#{messages['chemical.dangers']}",
                                            "#{messages['chemical.tankerType']}",
                                            "#{messages['chemical.tankCondition']}",
                                            "#{messages['chemical.hullType']}",
                                            "#{messages['chemical.tankEquipment']}",
                                            "#{messages['chemical.tankCondition']}",
                                            "#{messages['chemical.hullType']}",
                                            "#{messages['chemical.tankEquipment']}",
                                            "#{messages['chemical.relievePressure']}",
                                            "#{messages['chemical.maxFillRate']}",
                                            "#{messages['chemical.densityAt20C']}",
                                            "#{messages['chemical.samplingDevice']}",
                                            "#{messages['chemical.allowUnderdeckPumproom']}",
                                            "#{messages['chemical.temperatureClass']}",
                                            "#{messages['chemical.explosionGroups']}",
                                            "#{messages['chemical.explosionProtectionRequired']}",
                                            "#{messages['chemical.requiredEquipment']}",
                                            "#{messages['chemical.nrBlueLights']}"
                                       ];
                                       
                                       var table_data = [
                                       <ui:repeat value="#{chemical.overrides}" var="orl">
                                            "#{orl.overrideList.name}",
                                            "#{orl.un}",
                                            "<chemix:translation language="#{listLocaleSelector.language}" value="#{orl.translations}" />",
                                            "#{orl.classification}",
                                            "#{orl.classificationCode}",
                                            "#{orl.packageGroup}",
                                            "#{orl.dangers}",
                                            "#{orl.tankType}",
                                            "#{orl.tankCondition}",
                                            "#{orl.hullType}",
                                            "#{orl.tankEquipment}",
                                            "#{orl.relievePressure}",
                                            "#{orl.maxFillRate}",
                                            "#{orl.density}",
                                            "#{orl.samplingDevice}",
                                            "#{orl.allowPumpRoom}",
                                            "#{orl.temperatureClass}",
                                            "#{orl.explosionGroup}",
                                            "#{orl.explosionProtection}",
                                            "#{orl.equipment}",
                                            "#{orl.bluelights}"
                                       </ui:repeat>
                                       ];
                                  </script>
                        </c:if>
                        
              </ui:composition>
              



              • 5. Re: Form values not updated if using Ajax validation
                Bolke de Bruin Newbie

                The javabean


                package nl.chainsoftware.chemix.session;
                
                import java.util.ArrayList;
                import java.util.Date;
                import java.util.Iterator;
                import java.util.List;
                import java.util.Locale;
                import javax.ejb.Remove;
                import javax.ejb.Stateful;
                import javax.faces.application.FacesMessage;
                import javax.persistence.EntityManager;
                
                import nl.chainsoftware.chemix.model.Chemical;
                import nl.chainsoftware.chemix.model.ChemicalOverride;
                import nl.chainsoftware.chemix.model.Compatibility;
                import nl.chainsoftware.chemix.model.Material;
                import nl.chainsoftware.chemix.model.TankgroupChemicalException;
                import nl.chainsoftware.chemix.model.Translation;
                import nl.chainsoftware.chemix.model.User;
                import nl.chainsoftware.chemix.model.notes.ChemicalNote;
                import nl.chainsoftware.chemix.model.notes.ChemicalNoteConnector;
                import nl.chainsoftware.chemix.util.ListLocaleSelector;
                import nl.chainsoftware.chemix.util.NoteSelectItem;
                
                import org.jboss.seam.annotations.Begin;
                import org.jboss.seam.annotations.End;
                import org.jboss.seam.annotations.Name;
                import org.jboss.seam.annotations.In;
                import org.jboss.seam.annotations.Logger;
                import org.jboss.seam.annotations.Out;
                import org.jboss.seam.annotations.security.Restrict;
                import org.jboss.seam.core.Events;
                import org.jboss.seam.annotations.Factory;
                
                import org.jboss.seam.log.Log;
                import org.jboss.seam.faces.FacesMessages;
                
                @Stateful
                @Name("chemicalManager")
                @Restrict("#{identity.loggedIn}")
                public class ChemicalManagerBean implements ChemicalManager {
                     
                    @Logger 
                    private Log log;
                     
                    @In 
                    FacesMessages facesMessages;
                    
                    @In(create=true)
                    ListLocaleSelector listLocaleSelector;
                    
                    @In
                    private EntityManager entityManager;
                    
                    @In(create=true)
                    @Out
                    private Chemical chemical;
                          
                    @In
                     private Events events;    
                    
                    @In
                    private User currentUser;
                    
                    @In(create=true)
                    @Out
                    private List<NoteSelectItem> notes;
                    
                    @In(required=false)
                    @Out(required=false)
                    private ChemicalOverride override;
                    
                    @Begin(join=true)
                     public void select(Chemical selectedChemical) {
                          log.info("ChemicalManager.select() called with chemical id: " + selectedChemical.getId());
                          
                          chemical = selectedChemical;
                          
                          checkLanguages();
                          findNotes();
                          
                          facesMessages.addFromResourceBundle("#{messages['chemical.selected']}");
                          
                          log.info("ChemicalManager.select() exited with chemical id: " + selectedChemical.getId());
                
                     }
                
                    @End
                     public void persist() {
                         chemical.setUpdated(new Date());
                         chemical.setUpdatedby(currentUser);
                         
                         try {
                              setNotes();
                              entityManager.persist(chemical);
                              
                              facesMessages.addFromResourceBundle("#{messages['chemical.created']}");
                              log.info("Chemical created");
                         } catch (Exception e) {
                               log.fatal("Could not create chemical (" + chemical.getId() + ") " + e);
                               facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "#{messages['chemical.notCreated']}");        
                         }
                          
                          events.raiseTransactionSuccessEvent("chemicalsUpdated");
                     }
                     
                     @SuppressWarnings("unchecked")
                     @End(beforeRedirect=true)
                     public void remove() {
                          log.info("chemicalManager.remove() called with chemical id: " + chemical.getId());
                          
                          try {
                               /* This is necessary otherwise a remove fails with "deleted entity passed to persist"
                                * Should be move to one (material, chemical or compatibility) of the entities */
                               List<Compatibility> comps = chemical.getCompatibility();
                               for (Compatibility c : comps) {
                                    Material m = c.getMaterial();
                                    m.getCompatibilities().remove(c);
                               }
                               
                               List<TankgroupChemicalException> exceptions = entityManager.createQuery("from TankgroupChemicalException where chemical.id = :id").setParameter("id", chemical.getId()).getResultList();
                               for (TankgroupChemicalException e : exceptions) {
                                    entityManager.remove(e);
                               }
                               entityManager.remove(chemical);
                               entityManager.flush();
                
                               createChemical();
                               
                               facesMessages.addFromResourceBundle("#{messages['chemical.removed']}");
                               log.info("Chemical removed");
                          } catch (Exception e) {
                               log.fatal("Could not remove chemical (" + chemical.getId() + ") " + e);
                               facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "#{messages['chemical.notRemoved']}");          
                          }
                          
                          events.raiseTransactionSuccessEvent("chemicalsUpdated");
                     }
                     
                     /**
                      * Checks the chemical for available languages and adds one if necessary
                      */
                     private void checkLanguages() {
                          if (chemical == null)
                               return;
                          
                          List<Translation> translations = chemical.getTranslations();
                          
                          Iterator<Locale> locales = listLocaleSelector.getListLocales();
                          while (locales.hasNext()) {
                               Locale locale = locales.next();
                               if (!hasLanguage(locale.getLanguage())) {
                                    Translation t = new Translation(locale.getLanguage(), new String());
                                    t.setChemical(chemical);
                                    t.setUpdated(new Date());
                                    t.setUpdatedby(currentUser);
                                    translations.add(t);
                               }
                          }
                     }
                     
                     public boolean isManaged() {
                          if (chemical == null) 
                               return false;
                          
                          if (!entityManager.contains(chemical))
                               return false;
                          
                          return true;
                     }
                     
                     @Remove
                     public void destroy() {}
                
                     private boolean hasLanguage(String language) {
                          if (chemical.getTranslations() == null)
                               return false;
                          
                          for (Translation t : chemical.getTranslations()) {
                               if (t.getLanguage().equals(language))
                                    return true;
                          }
                          
                          return false;
                     }
                
                     public void build() {
                          // TODO Auto-generated method stub
                          
                     }
                
                     public void update() {
                          log.info("Saving chemical " + chemical.getId() + " (" + chemical.getUn() + ")");
                          
                          try {
                               setNotes();
                               entityManager.persist(chemical);
                               facesMessages.addFromResourceBundle("#{messages['chemical.updated']}");
                               log.info("Chemical saved");
                          } catch (Exception e) {
                               log.fatal("Could not save chemical (" + chemical.getId() + ") " + e);
                               facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "#{messages['chemical.notUpdated']}");
                               
                               revert();               
                          }
                          events.raiseTransactionSuccessEvent("chemicalsUpdated");          
                     }
                     
                     private void revert() {
                          chemical = entityManager.find(Chemical.class, chemical.getId());
                     }
                     
                     @Factory("chemical")
                     @SuppressWarnings("unchecked")
                     public Chemical createChemical() {
                          log.info("Creating new chemical");
                          
                          chemical = new Chemical();
                          
                          List<Compatibility> compatibilityList = new ArrayList<Compatibility>();
                          List<Material> materials = entityManager.createQuery("from Material").getResultList();
                          
                          for (Material material : materials) {
                               Compatibility c = new Compatibility(chemical, material);
                               compatibilityList.add(c);
                          }
                          chemical.setCompatibility(compatibilityList);
                          
                          List<Translation> translations = new ArrayList<Translation>();
                          
                         Iterator<Locale> locales = listLocaleSelector.getListLocales();
                         while ( locales.hasNext() ) {
                              Locale locale = locales.next();
                              Translation t = new Translation();
                              t.setLanguage(locale.getLanguage());
                              t.setChemical(chemical);
                              t.setUpdated(new Date());
                              t.setUpdatedby(currentUser);
                              translations.add(t);
                         }
                          chemical.setTranslations(translations);
                          
                          return chemical;
                     }
                     
                     /**
                      * do a deep copy of a chemical
                      */
                     public void copy() {
                          Chemical copy = new Chemical();
                          
                          copy.setAllowPumpRoom(chemical.isAllowPumpRoom());
                          copy.setBluelights(chemical.getBluelights());
                          copy.setClassification(chemical.getClassification());
                          copy.setClassificationCode("[copy]" + chemical.getClassificationCode());
                          copy.setDensity(chemical.getDensity());
                          
                          // TODO: check if this does not raise an issue with the chemical being copied
                          copy.setExplosionGroup(chemical.getExplosionGroup());
                          copy.setExplosionProtection(chemical.isExplosionProtection());
                          copy.setHullType(chemical.getHullType());
                          copy.setInternalNote(chemical.getInternalNote());
                          copy.setMaxFillRate(chemical.getMaxFillRate());
                          copy.setPackageGroup(chemical.getPackageGroup());
                          copy.setRelievePressure(chemical.getRelievePressure());
                          copy.setTankCondition(chemical.getTankCondition());
                          copy.setTemperatureClass(chemical.getTemperatureClass());
                          copy.setTankType(chemical.getTankType());
                          copy.setSamplingDevice(chemical.getSamplingDevice());
                          copy.setUn(chemical.getUn());
                          copy.setUpdated(new Date());
                          copy.setUpdatedby(currentUser);
                          
                          List<Translation> translations = new ArrayList<Translation>();
                          for (Translation t : chemical.getTranslations()) {
                               Translation tc = new Translation();
                               tc.setChemical(copy);
                               tc.setLanguage(t.getLanguage());
                               tc.setName("[copy]" + t.getName());
                               tc.setUpdated(new Date());
                               tc.setUpdatedby(currentUser);
                               translations.add(tc);
                          }
                          copy.setTranslations(translations);
                          
                          List<Compatibility> compatibilities = new ArrayList<Compatibility>();
                          for (Compatibility c : chemical.getCompatibility()) {
                               Compatibility cc = new Compatibility();
                               cc.setChemical(copy);
                               cc.setCompatibilityStatus(c.getCompatibilityStatus());
                               cc.setListName(c.getListName());
                               cc.setMaterial(c.getMaterial());
                               cc.setNote(c.getNote());
                               cc.setUpdated(new Date());
                               compatibilities.add(cc);
                          }
                          copy.setCompatibility(compatibilities);
                          
                          List<ChemicalNoteConnector> connectors = new ArrayList<ChemicalNoteConnector>();
                          for (ChemicalNoteConnector c : chemical.getNotes()) {
                               ChemicalNoteConnector connector = new ChemicalNoteConnector();
                               connector.setChemical(copy);
                               connector.setChemicalNote(c.getChemicalNote());
                               connector.setExtra(c.getExtra());
                               connectors.add(connector);
                          }
                          copy.setNotes(connectors);
                          
                          chemical = copy;
                     }
                     
                     @Factory("notes")
                     @SuppressWarnings("unchecked")
                     public List<NoteSelectItem> findNotes() {
                          if (chemical == null)
                               return null;
                          
                          List<ChemicalNoteConnector> connectedNotes;
                          if (entityManager.contains(chemical)) {
                               connectedNotes = 
                                    entityManager.createQuery("from ChemicalNoteConnector cnn where cnn.chemical = :chemical")
                                    .setParameter("chemical", chemical)
                                    .getResultList();
                          } else {
                               connectedNotes = new ArrayList<ChemicalNoteConnector>();
                          }
                          
                          List<ChemicalNote> notesList = entityManager.createQuery("from ChemicalNote c order by c.number asc").getResultList();
                          
                          List<NoteSelectItem> items = new ArrayList<NoteSelectItem>();
                          for (ChemicalNote n : notesList) {
                               NoteSelectItem item = new NoteSelectItem();
                               item.setLabel(Integer.toString(n.getNumber()));
                               item.setValue(n);
                               for (ChemicalNoteConnector cnn : connectedNotes) {
                                    if (cnn.getChemicalNote().getNumber() == n.getNumber()) {
                                         item.setSelected(true);
                                         item.setExtra(cnn.getExtra());
                                         break;
                                    }     
                               }
                               items.add(item);
                          }
                          
                          notes = items;
                          
                          return notes;
                     }
                     
                     private void setNotes() {
                          log.info("chemicalManager.setNotes called");
                          
                          if (entityManager.contains(chemical)) {
                               for (ChemicalNoteConnector nc : chemical.getNotes()) {
                                    nc.getChemicalNote().getChemicals().remove(nc);
                                    entityManager.remove(nc);
                               }
                               chemical.setNotes(null);
                               entityManager.flush();
                          }
                          
                          List<ChemicalNoteConnector> connectors = new ArrayList<ChemicalNoteConnector>();
                          for (NoteSelectItem item : notes) {
                               if (!item.isSelected())
                                    continue;
                               log.info("Adding connector: " + item.getLabel() + " extra: " + item.getExtra());
                               ChemicalNoteConnector connector = new ChemicalNoteConnector();
                               connector.setChemical(chemical);
                               connector.setChemicalNote((ChemicalNote) item.getValue());
                               connector.setExtra(item.getExtra());
                               
                               connectors.add(connector);
                          }
                          chemical.setNotes(connectors);
                     }
                     
                     public void getOverrideFromList(ChemicalOverride override) {
                          if (override == null) {
                               log.warn("getOverrideFromList: got null");
                               return;
                          }
                          
                          this.override = override;
                     }
                
                }
                



                • 6. Re: Form values not updated if using Ajax validation
                  Damian Harvey Apprentice

                  Ouch. It's nicer for everyone involved if you can cut your problem down to a smaller size and then we can work on it. Why not try cutting it down to the basics (ie one very simple bean and one simple page) and see if you can reproduce? Then once proven/fixed you can build it back into your actual code.


                  Are you saying that the none of the chemical values are updating when you select a new chemical or just that a few aren't updating?


                  If the former then try removing the @Factory("chemical") and just referring to the chemical as #{chemicalManager.chemical} in your page. See if that helps.


                  If the latter then you'll need to look into using <a4j:region> (often inputTexts don't reRender well without the use of regions)


                  Cheers,


                  Damian.