9 Replies Latest reply on Apr 25, 2012 2:05 PM by bleathem

    Lifecycle problem - Page being rebuilt on every ajax request

    gwate

      Hey guys,

       

      this is my first post here, and have been trying to figure out this life cycle problem.

       

      The basic problem is that everytime something needs to be submitted or calls for a ajax request, it seems to do a full page reload and rebuilding the view from the ground up again, which cancels any ajax calls. I have also noted that it WILL execute ajax requests up to the Onclick events, anything past that (ondombefore, onsubmit, oncomplete) will not be called and the page is rerendered.

       

      I have dealt with this issue with the Rich:popuppanel, but by using FacesContext.getCurrentInstance().getRenderResponse() in select parts of the code i could by pass the problem, however with a a4j:commandButton, i cannot be so lucky since i am trying to create a popup window based on the current data the user has entered.

       

      Here is my Jsf code

       

      <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:a4j="http://richfaces.org/a4j"
          xmlns:rich="http://richfaces.org/rich" xmlns:c="http://java.sun.com/jsp/jstl/core"
          xmlns:t="http://myfaces.apache.org/tomahawk"
          template="../cmstemplate.xhtml">
      
          <ui:define name="main">
              <h:form id="recordData">
                  <table width="100%" cellpadding="0" cellspacing="0">
                      <tr>
                          <td>
                              <h2>
                                  <h:outputText value="#{msg.dataeditor_pageheader}"/>
                              </h2>
                          </td>
                          <td>
                              <div class="edit-module-div">
                                  <!-- Adding a Cancel button -->
                                  <h:commandButton id="cancel-button-top" styleClass="btn"
                                      action="#{moduleDataEditAction.cancel}" 
                                      value="#{msg.moduleeditor_btn_cancel}"
                                      immediate="true">
                                  </h:commandButton>
                               </div>
                          </td>
                      </tr>
                  </table>
                  <!--  do not change the name of this form OR any panels ! -->
                  <h:panelGroup id="outerPanel" layout="block"
                      styleClass="block-container client-tools-edit-module">
      
                          <h:outputText value="#{moduleDataEditAction.module.name}" style="font-weight:bold"/>
      
                      <h:panelGroup id="leftPanel" layout="block">
                      </h:panelGroup>
                      <br class="clear-both" />
      
                  </h:panelGroup>
      
                     <h:panelGroup id="location-selection" layout="block"
                      rendered="#{moduleDataEditAction.renderLocationSelector}">
      
                  <div class="underline-header-link">
                      <a4j:commandLink id="selectAll" action="#{moduleListViewAction.dummyAction}" 
                              execute="@this" bypassUpdates="true" limitRender="true" styleClass="btn-text">
                          <h:outputText value="#{msg.clienttools_selectall}" />    
                      </a4j:commandLink>
                      <!--
                          This JQueary statement will select all checkboxes within
                          the class "underline-header-link" (referenced by the <div>
                          tag above).
                      -->
                      <rich:jQuery selector="#location-selection #selectAll" timing="domready" 
                              query="click(function(){
                              jQuery('.blocks-location-tags input:checkbox').attr('checked','checked');
                      });"/>
      
                      <a4j:commandLink id="deSelectAll" action="#{moduleListViewAction.dummyAction}" 
                              execute="@this" bypassUpdates="true" limitRender="true" styleClass="btn-text">
                          <h:outputText value="#{msg.clienttools_deselectall}" />    
                      </a4j:commandLink>
                      <!--
                          This JQueary statement will deselect all checkboxes within
                          the class "underline-header-link" (referenced by the <div>
                          tag above).
                      -->
                      <rich:jQuery selector="#location-selection #deSelectAll" timing="domready" 
                              query="click(function(event){
                          event.preventDefault();
                          jQuery('.blocks-location-tags input:checkbox').removeAttr('checked');
                      });"/>
                  </div>
                  <div class="blocks-location-tags">
                      <t:selectManyCheckbox id="locations" layout="pageDirection" layoutWidth="3"
                          value="#{moduleDataEditAction.recordLocationsCurrentRecord}">
                          <f:selectItems value="#{locationTagBean.selectItemsModuleRecordLocations}" />
                      </t:selectManyCheckbox>
                  </div>
                  <br class="clear-both" />            
                  </h:panelGroup>
      
                  <ui:include src="editActionItem_include.xhtml"/>
      
                  <h:commandButton id="cancel-button-bottom" styleClass="btn"
                      action="#{moduleDataEditAction.cancel}" 
                      value="#{msg.moduleeditor_btn_cancel}"
                      immediate="true">
                  </h:commandButton>
      
                  <br class="clear-both" />
              </h:form>
              <t:saveState value="#{moduleDataEditAction}"/>
              <h:outputText id="subComponentBuilder" binding="#{moduleDataEditAction.subComponents}" />
              <!--                initialise the media library bean -->
              <h:outputText id="dummy3" binding="#{mediaAction.dummy}" />
      
      
      
      </ui:define>
      
      </ui:composition>
      

       

      The editActionItem_include.xhtml which contains the buttons are as follows:

       

       

      <ui:component xmlns="http://www.w3.org/1999/xhtml"
         xmlns:h="http://java.sun.com/jsf/html"
         xmlns:a4j="http://richfaces.org/a4j"
         xmlns:rich="http://richfaces.org/rich"
         xmlns:f="http://java.sun.com/jsf/core"
         xmlns:ui="http://java.sun.com/jsf/facelets">
      
                      <a4j:commandButton id="btn-preview" styleClass="btn"
                          rendered="#{moduleDataEditAction.renderPreviewButton}"
                          action="#{moduleDataEditAction.preparePreviewLink}"
                          value="#{msg.moduleeditor_btn_preview}"
                          render="previewLink"
                          oncomplete="openNewWindow(document.getElementById('recordData:previewLink').value); return false;">
                      </a4j:commandButton>
      
                      <!-- This will disable the preview button -->
                      <h:commandButton id="btn-preview-disabled" styleClass="btn-disabled"
                          value="#{msg.moduleeditor_btn_preview}"
                          rendered="#{!moduleDataEditAction.renderPreviewButton}">
                      </h:commandButton>
                      <h:inputHidden id="previewLink" value="#{moduleDataEditAction.previewLink}"/>
      
                      <h:commandButton id="btn-publish" styleClass="btn"
                          action="#{moduleDataEditAction.saveAsPublish}" 
                          value="#{msg.moduleeditor_btn_publish}"
                          rendered="#{moduleDataEditAction.renderPublishButton}">
                      </h:commandButton>
      
                      <h:commandButton id="btn-publish-disabled" styleClass="btn-disabled"
                          value="#{msg.moduleeditor_btn_publish}"
                          rendered="#{!moduleDataEditAction.renderPublishButton}">
                      </h:commandButton>
      
                      <h:commandButton id="btn-save-draft" styleClass="btn"
                          action="#{moduleDataEditAction.saveAsDraft}" 
                          rendered="#{moduleDataEditAction.renderSaveDraftButton}"
                          value="#{msg.moduleeditor_btn_save_draft}">
                      </h:commandButton>
      
                      <h:commandButton id="btn-save-disabled" styleClass="btn-disabled"
                          value="#{msg.moduleeditor_btn_save_draft}"
                          rendered="#{!moduleDataEditAction.renderSaveDraftButton}">
                      </h:commandButton>
      
                      <h:commandButton id="btn-save-template" styleClass="btn"
                          action="#{moduleDataEditAction.saveAsTemplate}" 
                          value="#{msg.moduleeditor_btn_save_template}"
                          rendered="#{moduleDataEditAction.renderTemplateButton}">
                      </h:commandButton>
      
                      <h:commandButton id="btn-save-template-disabled" styleClass="btn-disabled"
                          value="#{msg.moduleeditor_btn_save_template}"
                          rendered="#{!moduleDataEditAction.renderTemplateButton}">
                      </h:commandButton>
      
      </ui:component>                        
      

       

      It seems on each request that the bindings are rebuilt and forces the page refresh, however the action method is being hit:

              <h:outputText id="subComponentBuilder" binding="#{moduleDataEditAction.subComponents}" />

              <!--                initialise the media library bean -->

              <h:outputText id="dummy3" binding="#{mediaAction.dummy}" />

       

      I am using a session scope, Richfaces 4 with myfaces 2.1.2, and spring 3 to manage my beans.

       

      The action method for the the a4j:commandButton id="btn-preview" is as follows:

               

       

      /**
       * Build the string for the adSmart link.
       */
      public void preparePreviewLink() {
          retrieveFieldValues();
          String s = moduleEditorService.getSmartString(currentRecordId, currentModuleData);
          StringBuilder sb = new StringBuilder();
          AssetPreview assetPreview = getAssetPreview();
      
          try {
              sb.append(PropertiesUtils.getProperty("smartad_server_url"));
      sb.append("?assetId=");
      sb.append(assetPreview.getAssetId());
      sb.append("&smartStr=");
          sb.append(s);
          setPreviewLink(sb.toString());
      } catch (CMSException e) {
          addGlobalMessage("dataeditor_preview_url_error",FacesMessage.SEVERITY_ERROR);
      logError(String.format("(User %s) Preview URL could not be determined! Make sure parameter 'smartad_server_url' in CMS.properties is present!",
                      getCurrentUser().getUsername()),e);
          }
          reloadView();
      }
      

       

      This worked fine in richfaces 3.3.3, and this seems like the only lifecycle issue that effects my whole project, which is contained on just this page.

      Any suggestions would be great!

        • 1. Re: Lifecycle problem - Page being rebuilt on every ajax request
          akaine

          Have you tried to set @ViewScoped annotation to the managed bean, I had similar problem with session/request scoped beans.

          • 2. Re: Lifecycle problem - Page being rebuilt on every ajax request
            gwate

            Well i use spring security to manage all my beans, so i do not use the @scoped annotation. Also ViewScoped is not actually implemented in spring 3 yet, but i have tried creating a custom scope to match the ViewScoped managed bean annotation. However since the other beans are request and sessions scopes it throughs an error saying it cannot retreive the view

            • 3. Re: Lifecycle problem - Page being rebuilt on every ajax request
              bleathem

              Hi Robert,

               

              This is a lot of code to digest - it's possible you've found a bug, but we need to isolate the errant behavior to come up with a fix.

               

              Could you provide:

              1. The simplest possible code that duplicates the problem you observe in your application.  Preferably something we can run ourselves locally.
              2. In the context of this example code, a description of what behaviour you expect
              3. A description of the incorrect behaviour you observe

               

              If you provide this, it's quite likely we can get to the heart of the problem.

               

              Cheers,

              Brian Leathem

              • 4. Re: Lifecycle problem - Page being rebuilt on every ajax request
                gwate

                Hey Brian,

                 

                I apperciate the response, and i do apologize for the my response time. I attached a quick sample project of a simple richfaces popuppanel, which basically will render based on what drop down is picked. Due to the life cycle issue, on each ajax request it will rebuild the page from square one again and again (with the orginal values and all except the most recent selection in the drop down you selected).

                 

                What i expect:

                on each ajax request i expect the backing bean to be saved since the execute=@this

                 

                Incorrect behaviour i noticed:

                The backing bean seems to be updated, however on the next render/execute it will default back to the orginal loaded value. I noticed the full page is rebuilt from ground up on each request. Also i noticed if you use the buttons, it does a full page request and doesnt take any events after the onclick event.

                • 5. Re: Lifecycle problem - Page being rebuilt on every ajax request
                  bleathem

                  Hi Robert,

                   

                  This sounds to me like the issue RF-11389 [1], do you agree?

                  https://issues.jboss.org/browse/RF-11389

                   

                  I'll take a look at the test app, and see if there is a new issue to be filed.

                   

                  Brian

                  • 6. Re: Lifecycle problem - Page being rebuilt on every ajax request
                    gwate

                    Hello again Brian,

                     

                    I would say its quite similar, however i noticed that we do not use a viewscope as it is not included in spring security, so we use a sessionscope. Also i noticed we dont not encas the popuppanel in an a4j:outputPanel.

                     

                    As for the example, i did tear out the spring, hibernate, etc. All it is, is richfaces 4 (Also been tried with the latest richfaces 4.1 M2, you can switch the jars as you like), along with Myfaces 2.1.2 (also tried with the straight JSF 2.0 jars). However the same issues still happened which lead me to believe its a JSF 2.0 spec issue or richfaces, but the ticket you linked does seem to relate, as it seems to enter a preRenderView method.

                     

                    Cheers,

                     

                    -Rob

                    • 7. Re: Lifecycle problem - Page being rebuilt on every ajax request
                      bleathem

                      Robert - were you able to find a resolution to this issue?

                      • 8. Re: Lifecycle problem - Page being rebuilt on every ajax request
                        gwate

                        Hello Brian,

                         

                        I actually haven't worked on this issue in quite some time and I can't clearly remember the whole process we did, however we did a bit of a hack by disabling certain views with FacesContext.getCurrentInstance().getRenderResponse() in the binding, and on various requests kill the ajax request and update specific components and not changing the ajax behavior to a full page submit instead. I also handed it off to a collegue to finish at the time who is no longer with us, but we should be revisiting this issue to implement a cleaner non-hacky solution, heck it might also be possible by upgrading to the newest rich faces (as we are still use 4.1) will fix it! Once we do I will post the solution here

                        • 9. Re: Lifecycle problem - Page being rebuilt on every ajax request
                          bleathem

                          Sure, keep us posted.  what you were trying to do should work without a lot of hassle, so do post back with any quirks you come across.