Announcement Announcement Module
Collapse
No announcement yet.
status.value returns String in spring:bind.... bug? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • status.value returns String in spring:bind.... bug?

    Hi

    In one of my beans, I return a Set of Longs. I use this set to populate a multiple select box.

    There appears to be an inconsistency or maybe a bug. At least something that was not documented so that I had to delve into Spring's code to understand it.

    I registered my Editor to the field, and it's been used correctly. When doing status.value I expected to get a Set, but I am getting a String. The BindStatus code used this:

    Code:
                                            this.value = this.errors.getFieldValue(this.expression);
    Which in turns uses this code from BindException.java

    Code:
            public Object getFieldValue(String field) {
                    FieldError fe = getFieldError(field);
                    String fixedField = fixedField(field);
                    // use rejected value in case of error, current bean property value else
                    Object value = (fe != null) ? fe.getRejectedValue() : getBeanWrapper().getPropertyValue(fixedField);
                    // apply custom editor, but not on binding failures like type mismatches
                    if (fe == null || !fe.isBindingFailure()) {
                            PropertyEditor customEditor = getCustomEditor(fixedField);
                            if (customEditor != null) {
                                    customEditor.setValue(value);
                                    return customEditor.getAsText();
                            }
                    }
                    return value;
            }
    Here one can see that the customEditor is used but the method getAsText() is used, not the getValue().

    I don't understand this choice. It breaks symetry between displaying and submitting my form.

    Someone else reported the same issue on the devel list back in September 2004.
    http://news.gmane.org/find-root.php?...0pcedev.com%3e

    So is this a bug? If not why is there a getDisplayValue() in BindStatus?

    My workaround is ugly (I use JSP 1.2) as I have to access the field itself instead of the status.value.

    Code:
        <c&#58;set var="IDs" value="$&#123;myForm.a.ids&#125;"/>
        <spring&#58;bind path="myForm.a.ids">
          <%Collection colIds = &#40;Collection&#41;pageContext.getAttribute&#40;"IDs"&#41;;%>
          <select name="<c&#58;out value="$&#123;status.expression&#125;"/>" size="5" multiple>
            <c&#58;forEach items="$&#123;features&#125;" var="feature">
              <c&#58;set var="id" value="$&#123;feature.id&#125;"/>
              <option value="<c&#58;out value="$&#123;feature.id&#125;"/>"
              <%Long myId = new Long&#40;pageContext.getAttribute&#40;"id"&#41;.toString&#40;&#41;&#41;;%>
              <%=colIds.contains&#40;myId&#41; ? "selected" &#58; ""%>>
              <c&#58;out value="$&#123;feature.name&#125;"/></option>
            </c&#58;forEach>
          </select>
        </spring&#58;bind>

    update: opened http://opensource.atlassian.com/proj...browse/SPR-798

  • #2
    status.value class morph

    I thought I was going crazy when I encountered this. I suspect it is the same issue but when we perform a get operation, the status.value is a String. When doing a post, it is the correct class. For example if I have

    Code:
    <spring:bind path="command.type">
     ...
     <c :out value="${status.value.class}"/>
    </spring:bind>
    it would print java.lang.String on get and com.mypackage.domain.MyType on post.

    We thought it was our custom property editors, or perhaps some other issue.

    Thanks for pointing out the area where this is happening. I got pretty lost trying to follow the spring source in the binding areas... :-(

    Anyway, the way we solved the issue is pretty ugly too.
    Instead of

    Code:
    <spring:bind path="command.type">
      some for-each code to iterate through a list of selections
      <option value="${option.id}" <c:if test="${option.id == status.value.id}"> selected</c:if>...</option>
    </spring:bind>
    we resorted to

    Code:
    <spring:bind path="command.type">
      some for-each code to iterate through a list of selections
      <option value="${option.id}" <c:if test="${option.id == command.type.id}"> selected</c:if>...</option>
    </spring:bind>

    This works because even though the status.value changed from String to object, the command.* is always the object. This is not very cool as the nice thing about the spring bind tag is it avoids having to have the full path inside the tag.

    Hope this helps

    Comment

    Working...
    X