13 Replies Latest reply on Dec 15, 2009 5:21 PM by Nick Belaevski

    Problem with rerendering input form

    Benjamin Seyinbour Expert

      Environment:
      richfaces-ui-3.3.2.SR1
      Liferay-5.2.3
      mojarra-1.2
      Jboss-5.1.0

      My use case:

      I have a number of fields in a form to create, read, and update a database table. Some of these fields are 'required' and others are 'optional'. Initially, I want to display only the 'required' fields and let the User decide if he/she wants to enter data in the 'optional' fields too.

      A checkbox component is provided if the User wishes to display the whole fields i.e., both the required and optional fields. When the User checks the checkbox, the form should 'immediatly' re-render the form, displaying all the fields; and when the User unchecks the checkbox, the form should 'immediately' re-render the form displaying only the required fields.

      Please see part of the implementation code below. So far, the code is not stable: sometimes it works and other times it doesn't. I wonder if anyone has a suggestion or better way of implementing the above use case.

      [Not Shown]
      In the baking beans, how the ui components' 'render' value are re/set -- based on the value of the checkbox. This part of the code works fine.

      Thanks in advance.

      JSF:

      :
      <h:selectBooleanCheckbox id="documentSelectBooleanCheckbox"
      binding="#{backing_newGenre.documentSelectBooleanCheckbox}"
      value="#{backing_newGenre.formBean.allDocumentFields}"style="margin-right:2px">
      <f:selectItem id="documentShowSelectItem" itemValue="false" itemLabel="#{genreMsg['label.optional.field.show']}" />
      <f:selectItem id="documentHideSelectItem" itemValue="true" itemLabel="#{genreMsg['label.optional.field.hide']}" />
      
      <!---
      <a4j:support id="documentOptionalFieldsSupport"
      event="onclick"
      ajaxSingle="true"
      ignoreDupResponses="true"
      immediate="true"
      limitToList="true"
      actionListener="#{backing_newGenre.dataProfileOptionalFieldClicked}"
      reRender="documentRegion"/>
      -->
      <a4j:support id="documentOptionalFieldsSupport2"
      event="onchange"
      ajaxSingle="true"
      ignoreDupResponses="true"
      immediate="true"
      limitToList="true"
      valueChangeListener="#{backing_newGenre.dataProfileOptionalFieldChange}"
      reRender="documentRegion"/>
      
      </h:selectBooleanCheckbox>
      :
      


      :
      <a4j:region id="documentRegion"
      ajaxRendered="true"
      selfRendered="true">
      
      <a4j:outputPanel id="documentOutputPanel"
      layout="block" ajaxRendered="true">
      
      <h:panelGrid id="documentPanelGrid"
      binding="#{backing_newGenre.documentPanelGrid}"
      columns="3"
      columnClasses="cssFormFieldLabel, cssFormFieldInput, cssFormFieldMsg"
      border="0">
      
      <! THE FORM FIELDS LABEL/INPUT BOX GOES HERE -->
      :
      :
      :
      <h:panelGrid>
      </a4j:outputPanel>
      </a4j:region>
      :
      



      JSF Backing bean:
      /*
      * Method to set or reset optional fields to render
      * @param event
      */
      
      public void dataProfileOptionalFieldChange(javax.faces.event.ValueChangeEvent event){
      
      dataProfileToggleFields = ! dataProfileToggleFields;
      getSessionBean().setAttribute("dataProfileToggleFields", new Boolean(dataProfileToggleFields));
      
      }
      
      public void dataProfileOptionalFieldClicked(javax.faces.event.ActionEvent actionEvent){
      
      dataProfileToggleFields = ! dataProfileToggleFields;
      getSessionBean().setAttribute("dataProfileToggleFields", new Boolean(dataProfileToggleFields));
      
      }
      


        • 1. Re: Problem with rerendering input form
          Nick Belaevski Master

          Hi,

          Please clarify: what's exactly not working? Any generated Faces messages or errors/warnings in a4j:log?

          • 2. Re: Problem with rerendering input form
            Benjamin Seyinbour Expert

            Nbelaevski, thanks for your response.

            >> what's exactly not working?

            Ans:

            When I check the selectBooleanCheckbox, the following happens:
            1.server log shows the dataProfileToggleFields new value, such as 'true' or 'false'.
            2.server log shows processing to the RENDER RESPONSE phase

            But the the number of fields on the form remains the same when it should increase by the number of optional fields.

            Note:

            The value of dataProfileToggleFields is store in another managed bean, 'SessionBean' (hence the getSessionBean() method). This saved value is read on re-render; the value is then used to decide whether to render an optional field or not. All required fields should always be rendered.

            • 4. Re: Problem with rerendering input form
              Benjamin Seyinbour Expert

              nbelaevski, thanks for your pointer.

              I have never used "a4:log" before and I tried it on your hint, but the data output is overwhelming, and it is difficult to analyze the data to make sense of it. Beside, the information I see is not very different from the ones from my own custom phaselistener which I use for debuging. So I shall not be using a4:log for now.

              Anyway, the problem is with combining "h:selectBooleanCheckbox" and "a4j:support". The lines of code I gave above does no work. Here is one that works:

              <a4j:outputPanel id="documentOutputPanel"
               layout="block"
               ajaxRendered="true">
              :
              :
              <h:selectBooleanCheckbox id="documentSelectBooleanCheckbox"
              binding="#{backing_newMember.documentSelectBooleanCheckbox}"
              valueChangeListener="#{backing_newMember.documentOptionalFieldChange}"
              immediate="true"
              onclick="submit()"
              style="margin-right:2px">
              
              <f:selectItem id="documentShowSelectItem" itemValue="false" itemLabel="#{memberMsg['label.optional.field.show']}" />
              <f:selectItem id="documentHideSelectItem" itemValue="true" itemLabel="#{memberMsg['label.optional.field.hide']}" />
              
              <a4j:support id="documentOptionalFieldsSupport2"
              event="onclick"
              reRender="documentOutputPanel"/>
              
              </h:selectBooleanCheckbox>
              :
              :
              </a4j:outputPanel>
              


              Adding 'onclick="submit()"' is particularly useful, but I thought this was equivalent to using:
              <a4j:support event="onclick">



              • 5. Re: Problem with rerendering input form
                Ilya Shaikovsky Master

                numerous places which I can't understand.. seems you trying to add everything to just make it working :)

                immediate="true"
                binding="#{backing_newMember.documentSelectBooleanCheckbox}"

                does this really need?
                <a4j:region ajaxRendered="true"


                region has no such property.

                reRender="documentOutputPanel"

                that was ok in first snippet and why you changed it with pointer to region which has no DOM representation ?

                backing_newGenre
                this should be request scoped in order to be used in binding. And I'm not seeing where you defined conditional rendering for optional data but rendering opposite to binding should be pointed to session scoped bean. So if all the properties in backing_newGenre - will not works.

                And so on.. I suggest you to simplify your sample as much as possible and do not try to add attributes in order just to add something usefull.

                I have never used "a4:log" before and I tried it on your hint, but the data output is overwhelming, and it is difficult to analyze the data to make sense of it. Beside, the information I see is not very different from the ones from my own custom phaselistener which I use for debuging.


                phaseListener shows server side processing log. And a4j:log contains client side ajax request processing log. So them are fully opposite.

                • 6. Re: Problem with rerendering input form
                  Benjamin Seyinbour Expert

                  I am not sure what you are trying to explain. The code now works. And my solution is here to help others who might find themselves in similar situation.

                  immediate="true"
                  binding="#{backing_newMember.documentSelectBooleanCheckbox}"


                  As a rule, I always use "binding" in my jsf to facilitate 'backing bean' processing of the ui components.

                  does this really need?
                  <a4j:region ajaxRendered="true"


                  Yes

                  1. reRender="documentOutputPanel
                  region has no such property


                  See
                  <a4j:outputPanel id="documentOutputPanel" <-----------------------
                   layout="block"
                   ajaxRendered="true">



                  backing_newGenre
                  this should be request scoped in order to be used in binding .

                  It is in request scope, but there is nothing in the jsf-1-2-fr-spec that says only request scoped backing bean can use binding. Anyway, it is not relevant to the issue. And, I have solved the problem and it has to do with using "h:selectBooleanCheckbox" and "a4j:support"-- after many permutations, this was my findings.

                  And so on.. I suggest you to simplify your sample as much as possible and do not try to add attributes in order just to add something usefull.


                  Thanks for the advice, but we don't do NTH anyway, we work to our gui specs. and design.

                  • 7. Re: Problem with rerendering input form
                    Nick Belaevski Master

                    It is in request scope, but there is nothing in the jsf-1-2-fr-spec that says only request scoped backing bean can use binding.

                    JSF components are not designed for multi-threaded processing (as said in spec.), so putting them into session exposes them for multi-threaded access, causing various issues.

                    • 8. Re: Problem with rerendering input form
                      Nick Belaevski Master

                      Here is one that works:

                      <a4j:outputPanel id="documentOutputPanel"
                       layout="block"
                       ajaxRendered="true">
                      :
                      :
                      <h:selectBooleanCheckbox id="documentSelectBooleanCheckbox"
                      binding="#{backing_newMember.documentSelectBooleanCheckbox}"
                      valueChangeListener="#{backing_newMember.documentOptionalFieldChange}"
                      immediate="true"
                      onclick="submit()"
                      style="margin-right:2px">
                       
                      <f:selectItem id="documentShowSelectItem" itemValue="false" itemLabel="#{memberMsg['label.optional.field.show']}" />
                      <f:selectItem id="documentHideSelectItem" itemValue="true" itemLabel="#{memberMsg['label.optional.field.hide']}" />
                       
                      <a4j:support id="documentOptionalFieldsSupport2"
                      event="onclick"
                      reRender="documentOutputPanel"/>
                       
                      </h:selectBooleanCheckbox>
                      :
                      :
                      </a4j:outputPanel>
                      


                      Adding 'onclick="submit()"' is particularly useful, but I thought this was equivalent to using:
                      <a4j:support event="onclick">

                      No, it's not equivalent and onclick="submit()" is not necessary at all in this case.

                      • 9. Re: Problem with rerendering input form
                        Benjamin Seyinbour Expert

                        nbelaevski wrote:

                         

                        It is in request scope, but there is nothing in the jsf-1-2-fr-spec that says only request scoped backing bean can use binding.

                        JSF components are not designed for multi-threaded processing (as said in spec.), so putting them into session exposes them for multi-threaded access, causing various issues.

                         

                        Yes, but I still stand by my earlier statement:”there is nothing in the jsf-1-2-fr-spec that says only request scoped backing bean can use binding”.

                        • 10. Re: Problem with rerendering input form
                          Nick Belaevski Master

                          I'll quote JSF spec.:

                          It is strongly recommend that application developers place managed beans that are pointed at by component binding expressions in

                          “request” scope. This is because placing it in session or application scope would require thread-safety, since

                          UIComponent instances depends on running inside of a single thread. There are also potentially negative impacts on

                          memory management when placing a component binding in “session” scope.

                          Practically this means that issues caused by session-scoped or application-scoped bound components (e.g. duplicate id exceptions) are treated like bad programming practice and any posts to project JIRA with such will be rejected.

                          • 11. Re: Problem with rerendering input form
                            Benjamin Seyinbour Expert

                            nbelaevski wrote:

                             

                            "Practically this means that issues caused by session-scoped or application-scoped bound components (e.g. duplicate id exceptions) are treated like bad programming practice and any posts to project JIRA with such will be rejected."

                             

                            nbelaevski,

                             

                            Well, whether a developer chooses to use request, session, or application scope is down to their gui specs and what is feasible according to the jsf specs and richfaces -- if they use richfaces.

                             

                            Richfaces JIRA may well reject post of what you call “bad programming practices” but Richfaces is not the jsf specs, and richfaces and its JIRA  is not the center of the jsf universe. Beside richfaces-ui-3.3.2 own samples give some example uses of managed beans in session scope.

                             

                            It is specification that drives implementation: if a developer cannot implement his specification in  Richfaces, there are other options such as Trinidad, ICEfaces, Mojarra, and even Tomahawk to choose from. So a  "duplicate id" or “bad programming practices” in the world of richfaces may well not be an issue or bad programming practices in the other worlds. What is most important  is the developer's use case and specifications.

                             

                            BTW, if "duplicate id" is a sign of “bad programming practices” then the richfaces development team stand accused for programming richfaces to generate “duplicate ids” in the absence of the developer component id entries.

                             

                            Indeed your comment contradicts the whole spirit of the JIRA: If we all did the safest things, then the JIRA might well be redundant, and there might be little or no feedback to the richfaces development team to improve richfaces as a product.

                            • 12. Re: Problem with rerendering input form
                              Ilya Shaikovsky Master

                              You didn't fully realized Nick's post.. We do not tell you how to develop.. And do not trying to limit JSF spec by adding our "best practice" suggestion..

                              But for this particular case:

                               

                              The problems which will appears with session scoped bindings - similar for any third parties you mentioned and for standard JSF components without any framework.. Just try to google for "JSF and session scoped binding problems" and you will find them all. And duplicate Id's problem was mentioned just as most frequent one and the problem was first time found earlier than RichFaces became available for public.

                               

                              So you could stand on the point that some things not restricted - but it doesn't means that these points should be used.

                               

                              As for demo - the samples are isolated and the problems which occurs in reall application just will not occur in the particular cases - thats why them was skipped. But I'll add a task to remove them.

                              • 13. Re: Problem with rerendering input form
                                Nick Belaevski Master

                                Ilya,

                                 

                                Thanks for clarification!

                                 

                                Benjamin,

                                 

                                Making JSF (standard RI or RF) components bound to session-scoped beans is a potentially dangerous operation (for several resons already mentioned), that's why I call it "bad practise", and that's all about bean scopes what I meant to say. I didn't mean that usage of session beans is prohibited or discouraged at all. Also note: JSF specification doesn't require that components are thread-safe, and base UI classes in JSF are not thread-safe either. RF uses these base classes, so the same limitation is true for RF as well. If specification changes in this point, we'll follow its requirements.