ICEfaces
  1. ICEfaces
  2. ICE-1418

Required attribute valueBinding unset when using partialSubmit

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.5.3
    • Fix Version/s: 1.6DR#3, 1.6
    • Component/s: ICE-Components
    • Labels:
      None
    • Environment:
      any

      Description

      When the attribute "partialSubmit" of an UIInput or UICommand is true, ICEFaces
      modifies all the others inputText components and their required property is set
      to FALSE.

      I think that there's a problem when the required attribute contains a ValueBinding.

      Consider the following example:

       

            <ice:commandButton action="#{testBean.togglePopup}" value="Partial Submit"
      partialSubmit="true"/>

            <ice:commandButton action="#{testBean.togglePopup}" value="Standard Submit" />

            <ice:inputText required="#{testBean.required}"/>

       

      After the a partial submit cycle, ICEFaces assigns TRUE to the required
      attribute of the previously modified components.This is not
      correct because if the required attribute contains a value-binding then that
      value-binding is lost and the expression is not evaluated any more.
      1. ReceiveSendUpdates.java
        6 kB
        Philip Breau
      2. SiaBlockingServlet.java
        25 kB
        Philip Breau

        Issue Links

          Activity

          Philip Breau created issue -
          Philip Breau made changes -
          Field Original Value New Value
          Support Case References https://www.icesoft.ca:4443/supportilla/show_bug.cgi?id=4030
          Support Customer Ref. #s 725
          Hide
          Philip Breau added a comment -

          developed a patch which should solve this problem.
          The BlockingServlet is the patch for ICEFaces 1.5.x and ReceiveSendUpdates is for ICEFaces 1.6.0.

          Show
          Philip Breau added a comment - developed a patch which should solve this problem. The BlockingServlet is the patch for ICEFaces 1.5.x and ReceiveSendUpdates is for ICEFaces 1.6.0.
          Hide
          Philip Breau added a comment -

          patch for 1.6

          Show
          Philip Breau added a comment - patch for 1.6
          Philip Breau made changes -
          Attachment ReceiveSendUpdates.java [ 10365 ]
          Hide
          Philip Breau added a comment -

          patch for 1.5.3

          Show
          Philip Breau added a comment - patch for 1.5.3
          Philip Breau made changes -
          Attachment SiaBlockingServlet.java [ 10366 ]
          Philip Breau made changes -
          Assignee Ted Goddard [ ted.goddard ]
          Philip Breau made changes -
          Fix Version/s 1.6DR#3 [ 10050 ]
          Hide
          Philip Breau added a comment -

          relevant changes to ReceiveSendUpdates:

          — ReceiveSendUpdates_updated.java 2007-04-11 09:05:43.000000000 -0600
          @@ -56,49 +56,63 @@
          }
          }

          private void renderCyclePartial(FacesContext context,
          UIComponent component) {
          synchronized (context)

          { - List alteredRequiredComponents = - setRequiredFalseInFormContaining(component); + Map<UIInput,ValueBinding> alteredRequiredComponents = + setRequiredFalseInFormContaining(component); com.icesoft.util.SeamUtilities.removeSeamDebugPhaseListener(lifecycle); lifecycle.execute(context); lifecycle.render(context); setRequiredTrue(alteredRequiredComponents); }

          }

          • private void setRequiredTrue(List requiredComponents) {
          • Iterator i = requiredComponents.iterator();
            + private void setRequiredTrue(Map<UIInput,ValueBinding> requiredComponents)
            Unknown macro: {+ Iterator<Entry<UIInput, ValueBinding>> i = requiredComponents.entrySet().iterator();+ UIInput next = null; while (i.hasNext()) { - next = (UIInput) i.next(); - ((UIInput) next).setRequired(true); + Entry<UIInput, ValueBinding> entry = i.next(); + next = entry.getKey(); + ValueBinding valueBinding = entry.getValue(); + if(valueBinding==null) + next.setRequired(true); + else + next.setValueBinding("required", valueBinding); } }
          • private List setRequiredFalseInFormContaining(UIComponent component) {
          • List alteredComponents = new ArrayList();
            + private Map<UIInput,ValueBinding> setRequiredFalseInFormContaining(UIComponent component) { + Map<UIInput,ValueBinding> alteredComponents = new HashMap<UIInput,ValueBinding>(); UIComponent form = getContainingForm(component); setRequiredFalseOnAllChildrenExceptOne(form, component, alteredComponents); return alteredComponents; }

          private void setRequiredFalseOnAllChildrenExceptOne(UIComponent parent,
          UIComponent componentToAvoid,

          • List alteredComponents) {
            + Map<UIInput,ValueBinding> alteredComponents) {
            int length = parent.getChildCount();
            UIComponent next = null;
            for (int i = 0; i < length; i++) {
            next = (UIComponent) parent.getChildren().get;
            if (next instanceof UIInput && next != componentToAvoid) {
          • if (((UIInput) next).isRequired()) {
          • ((UIInput) next).setRequired(false);
          • alteredComponents.add(next);
            + UIInput input = (UIInput) next;
            + if (input.isRequired()) {
            + ValueBinding valueBinding = input.getValueBinding("required");
            + if(valueBinding==null)
            + input.setRequired(false);
            + else
            Unknown macro: {+ ValueBinding falseValueBinding = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{false}");+ input.setValueBinding("required", falseValueBinding);+ }

            +
            + alteredComponents.put(input,valueBinding);
            }
            }
            setRequiredFalseOnAllChildrenExceptOne(next, componentToAvoid,
            alteredComponents);
            }
            }
            @@ -113,9 +127,7 @@
            break;
            }
            parent = parent.getParent();
            }
            return (UIForm) parent;
            }
            -
            -
            }

          Show
          Philip Breau added a comment - relevant changes to ReceiveSendUpdates: — ReceiveSendUpdates_updated.java 2007-04-11 09:05:43.000000000 -0600 @@ -56,49 +56,63 @@ } } private void renderCyclePartial(FacesContext context, UIComponent component) { synchronized (context) { - List alteredRequiredComponents = - setRequiredFalseInFormContaining(component); + Map<UIInput,ValueBinding> alteredRequiredComponents = + setRequiredFalseInFormContaining(component); com.icesoft.util.SeamUtilities.removeSeamDebugPhaseListener(lifecycle); lifecycle.execute(context); lifecycle.render(context); setRequiredTrue(alteredRequiredComponents); } } private void setRequiredTrue(List requiredComponents) { Iterator i = requiredComponents.iterator(); + private void setRequiredTrue(Map<UIInput,ValueBinding> requiredComponents) Unknown macro: {+ Iterator<Entry<UIInput, ValueBinding>> i = requiredComponents.entrySet().iterator();+ UIInput next = null; while (i.hasNext()) { - next = (UIInput) i.next(); - ((UIInput) next).setRequired(true); + Entry<UIInput, ValueBinding> entry = i.next(); + next = entry.getKey(); + ValueBinding valueBinding = entry.getValue(); + if(valueBinding==null) + next.setRequired(true); + else + next.setValueBinding("required", valueBinding); } } private List setRequiredFalseInFormContaining(UIComponent component) { List alteredComponents = new ArrayList(); + private Map<UIInput,ValueBinding> setRequiredFalseInFormContaining(UIComponent component) { + Map<UIInput,ValueBinding> alteredComponents = new HashMap<UIInput,ValueBinding>(); UIComponent form = getContainingForm(component); setRequiredFalseOnAllChildrenExceptOne(form, component, alteredComponents); return alteredComponents; } private void setRequiredFalseOnAllChildrenExceptOne(UIComponent parent, UIComponent componentToAvoid, List alteredComponents) { + Map<UIInput,ValueBinding> alteredComponents) { int length = parent.getChildCount(); UIComponent next = null; for (int i = 0; i < length; i++) { next = (UIComponent) parent.getChildren().get ; if (next instanceof UIInput && next != componentToAvoid) { if (((UIInput) next).isRequired()) { ((UIInput) next).setRequired(false); alteredComponents.add(next); + UIInput input = (UIInput) next; + if (input.isRequired()) { + ValueBinding valueBinding = input.getValueBinding("required"); + if(valueBinding==null) + input.setRequired(false); + else Unknown macro: {+ ValueBinding falseValueBinding = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{false}");+ input.setValueBinding("required", falseValueBinding);+ } + + alteredComponents.put(input,valueBinding); } } setRequiredFalseOnAllChildrenExceptOne(next, componentToAvoid, alteredComponents); } } @@ -113,9 +127,7 @@ break; } parent = parent.getParent(); } return (UIForm) parent; } - - }
          Hide
          Ted Goddard added a comment -

          We'll have to modify this fix a bit so that it doesn't require generics (that would break 1.4 compatibility), but overall it looks good.

          Show
          Ted Goddard added a comment - We'll have to modify this fix a bit so that it doesn't require generics (that would break 1.4 compatibility), but overall it looks good.
          Hide
          Ted Goddard added a comment -

          Is it necessary to create the #

          {false} valueBinding, or is it enough to call setRequired(false) and simply restore any previous valueBinding? It should be possible to create #{false}

          or #

          {true}

          once and use it for all components.

          The following syntax

          if (conditional)

          { function(); }

          else

          { otherFunction(); }

          is preferred over

          if (conditional)
          function();
          else
          otherFunction();

          as the second form is fragile under code maintenance.

          Show
          Ted Goddard added a comment - Is it necessary to create the # {false} valueBinding, or is it enough to call setRequired(false) and simply restore any previous valueBinding? It should be possible to create #{false} or # {true} once and use it for all components. The following syntax if (conditional) { function(); } else { otherFunction(); } is preferred over if (conditional) function(); else otherFunction(); as the second form is fragile under code maintenance.
          Hide
          Claudio Tasso added a comment -

          Hi, I'm the patch author.
          I think it's necessary create the #

          {false}

          valueBinding.
          In fact, after the constant value is set ( using setRequired(false)), assigning a valueBinding has no effect and it's not possible assigning a valueBinding any more.
          Please, look at the javax.faces.component.UIInput code:

          -------------------------------------------------------------------
          public void setRequired(boolean required)

          { this.required = required; this.requiredSet = true; }

          public boolean isRequired() {

          if (this.requiredSet)

          { return (this.required); }
          ValueBinding vb = getValueBinding("required");
          if (vb != null) { return (Boolean.TRUE.equals(vb.getValue(getFacesContext()))); } else { return (this.required); }

          }
          ------------------------------------------------------

          As you can see, after the setRequired() method is called, the property "requiredSet" is set and the subsequent calls to isRequired() ignore the valueBinding.

          Show
          Claudio Tasso added a comment - Hi, I'm the patch author. I think it's necessary create the # {false} valueBinding. In fact, after the constant value is set ( using setRequired(false)), assigning a valueBinding has no effect and it's not possible assigning a valueBinding any more. Please, look at the javax.faces.component.UIInput code: ------------------------------------------------------------------- public void setRequired(boolean required) { this.required = required; this.requiredSet = true; } public boolean isRequired() { if (this.requiredSet) { return (this.required); } ValueBinding vb = getValueBinding("required"); if (vb != null) { return (Boolean.TRUE.equals(vb.getValue(getFacesContext()))); } else { return (this.required); } } ------------------------------------------------------ As you can see, after the setRequired() method is called, the property "requiredSet" is set and the subsequent calls to isRequired() ignore the valueBinding.
          Repository Revision Date User Message
          ICEsoft Public SVN Repository #13520 Thu Apr 12 12:30:51 MDT 2007 ted.goddard restoring ValueBindings to components during partialSubmit (ICE-1418)
          Files Changed
          Commit graph MODIFY /icefaces/trunk/icefaces/core/src/com/icesoft/faces/webapp/http/core/ReceiveSendUpdates.java
          Hide
          Ted Goddard added a comment -

          I see what you mean about #

          {false}

          .

          Thanks for your contribution. A modification of the provided fix has been checked in and should propagate to the public repository later today.

          Show
          Ted Goddard added a comment - I see what you mean about # {false} . Thanks for your contribution. A modification of the provided fix has been checked in and should propagate to the public repository later today.
          Ted Goddard made changes -
          Status Open [ 1 ] Resolved [ 5 ]
          Resolution Fixed [ 1 ]
          Hide
          Philip Breau added a comment -

          The required attribute is not working when contained in a UIData component. Please see https://www.icesoft.ca:4443/supportilla/show_bug.cgi?id=4030 for more details.

          Show
          Philip Breau added a comment - The required attribute is not working when contained in a UIData component. Please see https://www.icesoft.ca:4443/supportilla/show_bug.cgi?id=4030 for more details.
          Philip Breau made changes -
          Resolution Fixed [ 1 ]
          Status Resolved [ 5 ] Reopened [ 4 ]
          Hide
          Ted Goddard added a comment -

          The proposed change in the suportilla case is a major re-work of this part of the implementation so will require some consideration.

          Show
          Ted Goddard added a comment - The proposed change in the suportilla case is a major re-work of this part of the implementation so will require some consideration.
          Hide
          Claudio Tasso added a comment -

          I'll be glad to talk about it, if you like. We've already made in our enviroment and it works fine (untill now, of course ).

          Show
          Claudio Tasso added a comment - I'll be glad to talk about it, if you like. We've already made in our enviroment and it works fine (untill now, of course ).
          Ken Fyten made changes -
          Assignee Ted Goddard [ ted.goddard ] Ken Fyten [ ken.fyten ]
          Ken Fyten made changes -
          Link This issue blocks ICE-1654 [ ICE-1654 ]
          Hide
          Ken Fyten added a comment -

          Marking this fixed for the non-UIData component cases.

          There is a follow-up issue for the UIData components: ICE-1654.

          Show
          Ken Fyten added a comment - Marking this fixed for the non-UIData component cases. There is a follow-up issue for the UIData components: ICE-1654 .
          Ken Fyten made changes -
          Status Reopened [ 4 ] Resolved [ 5 ]
          Resolution Fixed [ 1 ]
          Ken Fyten made changes -
          Fix Version/s 1.6 [ 10031 ]
          Ken Fyten made changes -
          Status Resolved [ 5 ] Closed [ 6 ]
          Assignee Ken Fyten [ ken.fyten ]

            People

            • Assignee:
              Unassigned
              Reporter:
              Philip Breau
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: