ICEfaces
  1. ICEfaces
  2. ICE-9146

textAreaEntry submittedValue is getting lost by the drop-down execute

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 3.2
    • Fix Version/s: 4.0
    • Component/s: ACE-Components
    • Labels:
      None
    • Environment:
      *
    • Assignee Priority:
      P1

      Description

      From QA:

      textAreaEntry
      > Overview / Label Position / Indicator Text (After a validation message is generated on the page by clearing text from the required field, changing the label position from the drop-down renders the old input text from the required field at the same time with the validation error message - is this an issue?).
      1. screenshot-01.png
        51 kB
      2. screenshot-02.png
        199 kB
      3. screenshot-03.png
        249 kB
      4. screenshot-04.png
        222 kB

        Issue Links

          Activity

          Hide
          yip.ng added a comment - - edited

          The submittedValue is getting lost by the drop-down execute?

          – Mark

          Show
          yip.ng added a comment - - edited The submittedValue is getting lost by the drop-down execute? – Mark
          Hide
          yip.ng added a comment -

          Re-render value determined by org.icefaces.ace.util.ComponentUtils#getStringValueToRender (PrimeFaces util?). Seems in the code it does make an attempt to look for submitted value, but somehow submitted value is not chosen.

          Show
          yip.ng added a comment - Re-render value determined by org.icefaces.ace.util.ComponentUtils#getStringValueToRender (PrimeFaces util?). Seems in the code it does make an attempt to look for submitted value, but somehow submitted value is not chosen.
          Hide
          yip.ng added a comment - - edited

          The code looks correct, can you determine if submittedValue is somehow getting cleared, and if so why?

          – Mark

          Show
          yip.ng added a comment - - edited The code looks correct, can you determine if submittedValue is somehow getting cleared, and if so why? – Mark
          Hide
          yip.ng added a comment -
          Show
          yip.ng added a comment - See screenshot-01.png .
          Hide
          yip.ng added a comment - - edited

          Tried immediate="true", as suggested by Mark. No difference.

          Show
          yip.ng added a comment - - edited Tried immediate="true", as suggested by Mark. No difference.
          Hide
          yip.ng added a comment - - edited

          Replaced <ace:textAreaEntry> with <h:inputTextarea>. Same result. See screenshot-02.png. Therefore, inherent JSF behavior?

          Show
          yip.ng added a comment - - edited Replaced <ace:textAreaEntry> with <h:inputTextarea>. Same result. See screenshot-02.png . Therefore, inherent JSF behavior?
          Hide
          Mark Collette added a comment -

          I noticed similar behaviour in the singleSubmit tutorial, if one fills in the fields and then attempts to clear all the fields, then the previously cleared field will revert to re-filled.

          Show
          Mark Collette added a comment - I noticed similar behaviour in the singleSubmit tutorial, if one fills in the fields and then attempts to clear all the fields, then the previously cleared field will revert to re-filled.
          Hide
          Deryk Sinotte added a comment -

          There seems to be some history with singleSubmit and values reverting to older inputs in this case http://jira.icesoft.org/browse/ICE-8403. However, it was closed as not being reproducible. I've pared down the test to this JSF-only f:ajax powered form and removed icefaces.jar:

          <h:form id="frm">
              <f:ajax event="blur">
                  <h:panelGrid columns="3">
                      <h:outputLabel for="name" value="Name:"/>
                      <h:inputText id="name" value="#{personBean.name}" required="true" maxlength="50"/>
                      <h:message id="nameMsg" for="name"/>
                  
                      <h:outputLabel for="age" value="Age:"/>
                      <h:inputText id="age" value="#{personBean.age}" required="true"
                                   size="2" maxlength="2">
                          <f:validateLongRange minimum="1" maximum="99"/>
                      </h:inputText>
                      <h:message id="ageMsg" for="age"/>
                  
                  </h:panelGrid>
              
                  <h:commandButton id="submitId" value="Submit" actionListener="#{personBean.submitButton}"/>
              </f:ajax>	
          </h:form>

          And compared the behaviour to an ICEfaces-powered singleSubmit form:

          <h:form id="frm">
          <icecore:singleSubmit/>
                 <h:panelGrid columns="3">
                      <h:outputLabel for="name" value="Name:"/>
                      <h:inputText id="name" value="#{personBean.name}" required="true" maxlength="50"/>
                      <h:message id="nameMsg" for="name"/>
                  
                      <h:outputLabel for="age" value="Age:"/>
                      <h:inputText id="age" value="#{personBean.age}" required="true"
                                   size="2" maxlength="2">
                          <f:validateLongRange minimum="1" maximum="99"/>
                      </h:inputText>
                      <h:message id="ageMsg" for="age"/>
                  
                  </h:panelGrid>
              
                  <h:commandButton id="submitId" value="Submit" actionListener="#{personBean.submitButton}"/>
          </h:form>

          So far the behaviour between the two is not entirely consistent:

          The ICEfaces version with the singleSubmit form shows the behaviour we are concerned about where it puts back in the old value when I clear out a field and trigger validation. The JSF-only version doesn't have the problem. It submits on blur but it's not triggering the validation when blurring; only when clicking the Submit button.

          My guess is that when the field is cleared, the validation failure prevents the cleared field value from being set resulting in the next response returning the field to it's previous value. In other words:

          1. First, frm.name=Deryk is submitted
          2. then, frm.age=29 is submitted
          3. then, frm.age=0 is submitted but detected as invalid so 0 is not set
          4. then, frm.name=Elvis is submitted and the resulting response sets frm.age to 29

          I presume that this problem is relatively unique to ICEfaces + singleSubmit + validation.

          Show
          Deryk Sinotte added a comment - There seems to be some history with singleSubmit and values reverting to older inputs in this case http://jira.icesoft.org/browse/ICE-8403 . However, it was closed as not being reproducible. I've pared down the test to this JSF-only f:ajax powered form and removed icefaces.jar: <h:form id= "frm" > <f:ajax event= "blur" > <h:panelGrid columns= "3" > <h:outputLabel for= "name" value= "Name:" /> <h:inputText id= "name" value= "#{personBean.name}" required= "true" maxlength= "50" /> <h:message id= "nameMsg" for= "name" /> <h:outputLabel for= "age" value= "Age:" /> <h:inputText id= "age" value= "#{personBean.age}" required= "true" size= "2" maxlength= "2" > <f:validateLongRange minimum= "1" maximum= "99" /> </h:inputText> <h:message id= "ageMsg" for= "age" /> </h:panelGrid> <h:commandButton id= "submitId" value= "Submit" actionListener= "#{personBean.submitButton}" /> </f:ajax> </h:form> And compared the behaviour to an ICEfaces-powered singleSubmit form: <h:form id= "frm" > <icecore:singleSubmit/> <h:panelGrid columns= "3" > <h:outputLabel for= "name" value= "Name:" /> <h:inputText id= "name" value= "#{personBean.name}" required= "true" maxlength= "50" /> <h:message id= "nameMsg" for= "name" /> <h:outputLabel for= "age" value= "Age:" /> <h:inputText id= "age" value= "#{personBean.age}" required= "true" size= "2" maxlength= "2" > <f:validateLongRange minimum= "1" maximum= "99" /> </h:inputText> <h:message id= "ageMsg" for= "age" /> </h:panelGrid> <h:commandButton id= "submitId" value= "Submit" actionListener= "#{personBean.submitButton}" /> </h:form> So far the behaviour between the two is not entirely consistent: The ICEfaces version with the singleSubmit form shows the behaviour we are concerned about where it puts back in the old value when I clear out a field and trigger validation. The JSF-only version doesn't have the problem. It submits on blur but it's not triggering the validation when blurring; only when clicking the Submit button. My guess is that when the field is cleared, the validation failure prevents the cleared field value from being set resulting in the next response returning the field to it's previous value. In other words: First, frm.name=Deryk is submitted then, frm.age=29 is submitted then, frm.age=0 is submitted but detected as invalid so 0 is not set then, frm.name=Elvis is submitted and the resulting response sets frm.age to 29 I presume that this problem is relatively unique to ICEfaces + singleSubmit + validation.
          Hide
          Deryk Sinotte added a comment -

          So i tweaked the f:ajax test a bit and added in MyFaces. I tested a matrix of:

          • ICEfaces using <icecore:singleSubmit/>
          • stock JSF using <f:ajax event="blur" execute="@this" render="@form"> (using render="@all" causes ViewRoot updates which have a different effect)

          against

          • Mojarra
          • MyFaces

          The result is that the problem only occurs when using Mojarra. The inclusion of ICEfaces is irrelevant and the problem doesn't manifest on MyFaces in either scenario. So it looks to be a Mojarra specific bug/behaviour. There may be a couple of cases that are related:

          https://java.net/jira/browse/JAVASERVERFACES-838
          https://java.net/jira/browse/JAVASERVERFACES-2264

          Show
          Deryk Sinotte added a comment - So i tweaked the f:ajax test a bit and added in MyFaces. I tested a matrix of: ICEfaces using <icecore:singleSubmit/> stock JSF using <f:ajax event="blur" execute="@this" render="@form"> (using render="@all" causes ViewRoot updates which have a different effect) against Mojarra MyFaces The result is that the problem only occurs when using Mojarra. The inclusion of ICEfaces is irrelevant and the problem doesn't manifest on MyFaces in either scenario. So it looks to be a Mojarra specific bug/behaviour. There may be a couple of cases that are related: https://java.net/jira/browse/JAVASERVERFACES-838 https://java.net/jira/browse/JAVASERVERFACES-2264
          Hide
          Deryk Sinotte added a comment - - edited

          One thing I found that changes the behaviour is:

          <context-param>
              <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
              <param-value>true</param-value>
          </context-param>

          When I add that to the test case, it modifies what happens:

          1. First, frm.name=Deryk is submitted
          2. then, frm.age=29 is submitted
          3. then, frm.age=0 is submitted but detected as invalid so 0 is not set - at this point the previous value of 29 is immediately restored
          4. then, frm.name=Elvis is submitted and frm.age remains 29

          From looking at the code, I believe that this section in UIInput.validate() is the secret sauce:

          // If non-null, an instanceof String, and we're configured to treat
          // zero-length Strings as null:
          //   call setSubmittedValue(null)
          if ((considerEmptyStringNull(context)
               && submittedValue instanceof String 
               && ((String) submittedValue).length() == 0)) {
              setSubmittedValue(null);
              submittedValue = null;
          }

          Because if this isn't executed, then later in the same method:

          // If our value is valid, store the new value, erase the
          // "submitted" value, and emit a ValueChangeEvent if appropriate
          if (isValid()) {
              Object previous = getValue();
              setValue(newValue);
              setSubmittedValue(null);
              if (compareValues(previous, newValue)) {
                  queueEvent(new ValueChangeEvent(this, previous, newValue));
              }
          }

          So the bottom line looks to be, when validation fails, and empty strings are not treated as NULL values (i.e. the context parameter is false, which is the default) then setSubmittedValue(null) is never called, leaving the old value in the component.

          Show
          Deryk Sinotte added a comment - - edited One thing I found that changes the behaviour is: <context-param> <param-name> javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL </param-name> <param-value> true </param-value> </context-param> When I add that to the test case, it modifies what happens: First, frm.name=Deryk is submitted then, frm.age=29 is submitted then, frm.age=0 is submitted but detected as invalid so 0 is not set - at this point the previous value of 29 is immediately restored then, frm.name=Elvis is submitted and frm.age remains 29 From looking at the code, I believe that this section in UIInput.validate() is the secret sauce: // If non- null , an instanceof String , and we're configured to treat // zero-length Strings as null : // call setSubmittedValue( null ) if ((considerEmptyStringNull(context) && submittedValue instanceof String && (( String ) submittedValue).length() == 0)) { setSubmittedValue( null ); submittedValue = null ; } Because if this isn't executed, then later in the same method: // If our value is valid, store the new value, erase the // "submitted" value, and emit a ValueChangeEvent if appropriate if (isValid()) { Object previous = getValue(); setValue(newValue); setSubmittedValue( null ); if (compareValues(previous, newValue)) { queueEvent( new ValueChangeEvent( this , previous, newValue)); } } So the bottom line looks to be, when validation fails, and empty strings are not treated as NULL values (i.e. the context parameter is false, which is the default) then setSubmittedValue(null) is never called, leaving the old value in the component.
          Hide
          Deryk Sinotte added a comment -

          Upon searching for references to INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL, I came across some blogs and JIRAs that help explain what is going on:

          http://stackoverflow.com/questions/3933786/jsf-2-bean-validation-validation-failed-empty-values-are-replaced-with-las

          So setting that parameter can introduce a different set of issues. The blog also suggests a patch to the HtmlBasicRenderer.getCurrentValue() method from this:

          if (component instanceof UIInput) {
              Object submittedValue = ((UIInput) component).getSubmittedValue();
              if (submittedValue != null) {
                  // value may not be a String...
                  return submittedValue.toString();
              }
          }

          to this:

          if (component instanceof UIInput && !((UIInput) component).isValid()) {
              Object submittedValue = ((UIInput) component).getSubmittedValue();
              if (submittedValue != null) {
                  // value may not be a String...
                  return submittedValue.toString();
              } else {
                  return null;
              }
          }

          It also references another JIRA that was opened (but I can't verify at the moment as the JSF site is down):

          http://java.net/jira/browse/JAVASERVERFACES-2262

          Show
          Deryk Sinotte added a comment - Upon searching for references to INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL, I came across some blogs and JIRAs that help explain what is going on: http://stackoverflow.com/questions/3933786/jsf-2-bean-validation-validation-failed-empty-values-are-replaced-with-las So setting that parameter can introduce a different set of issues. The blog also suggests a patch to the HtmlBasicRenderer.getCurrentValue() method from this: if (component instanceof UIInput) { Object submittedValue = ((UIInput) component).getSubmittedValue(); if (submittedValue != null ) { // value may not be a String ... return submittedValue.toString(); } } to this: if (component instanceof UIInput && !((UIInput) component).isValid()) { Object submittedValue = ((UIInput) component).getSubmittedValue(); if (submittedValue != null ) { // value may not be a String ... return submittedValue.toString(); } else { return null ; } } It also references another JIRA that was opened (but I can't verify at the moment as the JSF site is down): http://java.net/jira/browse/JAVASERVERFACES-2262
          Hide
          Deryk Sinotte added a comment -

          The blog also states that, if you are using PrimeFaces, this should be fixed via ComponentUtils#getValueToRender() method. Going back to Yip's original analysis, he noted that he figures that the code should be able to handle this.

          However, this particular code block won't be hit for stock components (which is what I was testing against). The code should be exercised for our ACE components. I took a quick look at the latest version of ComponentUtils in the PrimeFaces source tree and found that it's been significantly changed and improved since we forked it - including the logic for fixing this problem that the blog refers to. Perhaps someone on the Component team could look at the improvements in ComponentUtils to see if they can be ported forward to our version to resolve this.

          The JIRAs around this appear to remain open. Additionally, there is an open spec issue:

          https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-939

          Show
          Deryk Sinotte added a comment - The blog also states that, if you are using PrimeFaces, this should be fixed via ComponentUtils#getValueToRender() method. Going back to Yip's original analysis, he noted that he figures that the code should be able to handle this. However, this particular code block won't be hit for stock components (which is what I was testing against). The code should be exercised for our ACE components. I took a quick look at the latest version of ComponentUtils in the PrimeFaces source tree and found that it's been significantly changed and improved since we forked it - including the logic for fixing this problem that the blog refers to. Perhaps someone on the Component team could look at the improvements in ComponentUtils to see if they can be ported forward to our version to resolve this. The JIRAs around this appear to remain open. Additionally, there is an open spec issue: https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-939
          Hide
          yip.ng added a comment - - edited

          Doesn't work, not even after making an exact copy of the whole latest Primefaces methods (v. 3.5). All the fixes work only when component does both execute and render. The problem in this case is when component is rendered (by some other component) without execute. The submitted value from the last execute is simply lost. See screenshot for Primefaces code and more detailed annotations.

          Show
          yip.ng added a comment - - edited Doesn't work, not even after making an exact copy of the whole latest Primefaces methods (v. 3.5). All the fixes work only when component does both execute and render. The problem in this case is when component is rendered (by some other component) without execute. The submitted value from the last execute is simply lost. See screenshot for Primefaces code and more detailed annotations.
          Hide
          yip.ng added a comment -

          Suggestion from Mark: try putting components in separate columns of a table.

          Working. See screenshot for the test case.

          Show
          yip.ng added a comment - Suggestion from Mark: try putting components in separate columns of a table. Working. See screenshot for the test case.
          Hide
          yip.ng added a comment -

          [2013-05-16 4:28:05 PM] Mark Collette: ICE-9279 : Propagate submittedValues between lifecycles
          http://jira.icesoft.org/browse/ICE-9279

          Show
          yip.ng added a comment - [2013-05-16 4:28:05 PM] Mark Collette: ICE-9279 : Propagate submittedValues between lifecycles http://jira.icesoft.org/browse/ICE-9279
          Hide
          Arturo Zambrano added a comment -

          The same issue is seen with ace:textEntry and ace:maskedEntry.

          Show
          Arturo Zambrano added a comment - The same issue is seen with ace:textEntry and ace:maskedEntry.
          Hide
          Arturo Zambrano added a comment -

          Committed fix to 4.0 trunk at revision 41497. This fix was applied to ace:textEntry, ace:textAreaEntry and ace:maskedEntry. This issue has already been seen in ace:autoCompleteEntry (ICE-9722). The fix consists in checking if the component is valid or not before determining what value to render. If it's valid, proceed normally. If it's invalid, render the submitted (invalid) value.

          Show
          Arturo Zambrano added a comment - Committed fix to 4.0 trunk at revision 41497. This fix was applied to ace:textEntry, ace:textAreaEntry and ace:maskedEntry. This issue has already been seen in ace:autoCompleteEntry ( ICE-9722 ). The fix consists in checking if the component is valid or not before determining what value to render. If it's valid, proceed normally. If it's invalid, render the submitted (invalid) value.
          Hide
          Ken Fyten added a comment -

          This change is causing several serious regression failures:

          1. autoCompleteEntry/ comboBox/ selectMenu/ simpleSelectOneMenu:
          > Indicator Text: this demo is not functional after trying to disable the "Required" indicator, or after changing the Indicator position.
          Also, the "Documentation" drop-down is rendered below the component page name after interacting with this demo.
          Unable also to leave this page afterwards, must open a new browser window to be able to navigate to other demos.

          2. dataTable
          > Find: demo is not functional; after entering a search string and clicking "Find Next", characters disappear from search query text entry, there are no search results.
          Also, the "Documentation" drop-down is rendered below the component page name after interacting with this demo.
          Unable also to leave this page afterwards, must open a new browser window to be able to navigate to other demos.

          Show
          Ken Fyten added a comment - This change is causing several serious regression failures: 1. autoCompleteEntry/ comboBox/ selectMenu/ simpleSelectOneMenu: > Indicator Text: this demo is not functional after trying to disable the "Required" indicator, or after changing the Indicator position. Also, the "Documentation" drop-down is rendered below the component page name after interacting with this demo. Unable also to leave this page afterwards, must open a new browser window to be able to navigate to other demos. 2. dataTable > Find: demo is not functional; after entering a search string and clicking "Find Next", characters disappear from search query text entry, there are no search results. Also, the "Documentation" drop-down is rendered below the component page name after interacting with this demo. Unable also to leave this page afterwards, must open a new browser window to be able to navigate to other demos.
          Hide
          Arturo Zambrano added a comment -

          The last two issues above are also caused by ICE-9953, as explained in a comment in ICE-10080.

          Show
          Arturo Zambrano added a comment - The last two issues above are also caused by ICE-9953 , as explained in a comment in ICE-10080 .

            People

            • Assignee:
              Arturo Zambrano
              Reporter:
              yip.ng
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: