Announcement Announcement Module
Collapse
No announcement yet.
Problems w/Binding to a list of Objects Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problems w/Binding to a list of Objects

    Hi all,

    I have read http://forum.springframework.org/showthread.php?t=17646
    and http://forum.springframework.org/showthread.php?t=10322

    I believe that I have implemented everything correctly as outlined but I'm not sure how to get my custom PropertyEditor to kick off. I'm pretty sure it's because I'm not binding properly.

    I have an Investigation object which is my formBackingObject and I am trying to update a List of CausesOfDisc objects on my Investigation object. I am using Hibernate.

    Here is the code that I feel is relevent:

    My custom PropertyEditor
    Code:
    public class CausesOfDiscPropertyEditor extends PropertyEditorSupport {
        protected final Log logger = LogFactory.getLog(getClass());
        private final CausesOfDiscDao dao;
    
        public CausesOfDiscPropertyEditor (final CausesOfDiscDao theDAO) {
            this.dao = theDAO;
        }
    
        public String getAsText() {
            CausesOfDisc causesOfDisc = (CausesOfDisc) getValue();
            return causesOfDisc.getShortDescription();
        }
    
        public void setAsText(final String value) {
            try {
                logger.info("looking up value[" + value + "]");
                CausesOfDisc causesOfDisc = dao.getCausesOfDisc(new Long(value));
                super.setValue(causesOfDisc);
            } catch (final Exception e) {
                super.setValue(null);
            }
        }
    }
    How I bind the custom PropertyEditor
    Code:
            binder.registerCustomEditor(CausesOfDisc.class, new CausesOfDiscPropertyEditor(causesOfDiscManager));
    Code in my referenceData method to pull ALL possibilities as a sorted List and a HashMap to store the selected status for the view
    Code:
            Investigation investigation = (Investigation) command;
    
            Map<CausesOfDisc, Boolean> allCausesOfDiscCrit = new HashMap<CausesOfDisc, Boolean>();
            List allCausesOfDisc = causesOfDiscManager.getAllCausesOfDisc();
            for (int i = 0; i < allCausesOfDisc.size(); i++) {
              CausesOfDisc causeOfDisc = (CausesOfDisc) allCausesOfDisc.get(i);
              allCausesOfDiscCrit.put(causeOfDisc, new Boolean(investigation.getCausesOfDisc().contains(causeOfDisc)));
            }
            referenceData.put("allCausesOfDiscCrit", allCausesOfDiscCrit);
            referenceData.put("allCausesOfDisc", allCausesOfDisc);
    My jsp code for displaying the checkboxes
    Code:
                    <c:forEach items="${allCausesOfDisc}" var="causeOfDisc" varStatus="counter">
                      <input type="checkbox" name="investigation.causesOfDisc" value="${causeOfDisc.id}" <c:if test="${allCausesOfDiscCrit[causeOfDisc]}">checked</c:if>/>
                      ${causeOfDisc.shortDescription}<br/>
                    </c:forEach>
    I have tried several different things with spring:bind but they all seem to fail... with the above, nothing happens because the custom PropertyEditor never gets kicked off which I belive means I'm not binding correctly.

    Everything I've read so far got me to this point without too much headache... I'm fairly new to Spring MVC so I don't quite understand how the bind works in relation to kicking off the custom PropertyEditor. It would seem to me that maybe naming the checkboxes as investigation.causesOfDisc would tell the binder to look for a custom PropertyEditor that would be a List<CausesOfDisc> but I'm not sure if this is correct thinking and if so, how to fix the problem.

    I'm sure this is something simple.

    Thanks,
    Steve

  • #2
    Have you tried putting some debug in to find out exactly what the class of CausesOfDisc is? Hibernate does alter some classes at runtime with CGLIB which can give odd results. It may not be what you think.

    Bob

    Comment


    • #3
      CausesOfDisc is a Hibernate POJO... nothing more. I can't believe that Hibernate would do anything that would make my class no longer an Instance of CausesOfDisc.... that would wreak havoc on just about every application out there.

      So... does it look like everything is setup correctly?

      Again, my main point of concern is that my custom PropertyEditor is not kicking off which if what Bob says is true could be the problem.


      Steve

      Comment


      • #4
        Success

        OK... after playing around with it for another few hours... I figured out what I needed for binding.

        I needed to add an array to my formBackingObject (Investigation) and bind the form fields to that array rather than my Hibernate persisted List. I assume it is because Spring bind is not able to see that my List contains CausesOfDisc Objects whereas I setup the array as a CausesOfDisc[] array. (Feel free to correct me if I'm wrong there)

        So... the following code changes were made:

        To my Investigation Object (POJO)... I added:
        Code:
            CausesOfDisc[] causesOfDiscArray;
        
            @Transient
            public CausesOfDisc[] getCausesOfDiscArray() {
                return causesOfDiscArray;
            }
        
            public void setCausesOfDiscArray(CausesOfDisc[] causesOfDiscArray) {
                this.causesOfDiscArray = causesOfDiscArray;
            }
        I don't want to persist it, hence the @Transient

        My form jsp now has:
        Code:
                        <c:forEach items="${allCausesOfDisc}" var="causeOfDisc" varStatus="counter">
                          <spring:bind path="investigation.causesOfDiscArray">
                            <input type="checkbox" name="${status.expression}" value="${causeOfDisc.id}" <c:if test="${allCausesOfDiscCrit[causeOfDisc]}">checked</c:if>/>
                            ${causeOfDisc.shortDescription}<br/>
                          </spring:bind>
                        </c:forEach>
        I believe the only change from the first post is the bind tag... remember, this binds to my array and not my persisted List... SO... the next snippet of code is added before you save your Object (Investigation):

        Code:
        investigation.setCausesOfDisc(Arrays.asList(investigation.getCausesOfDiscArray()));
        This really makes this type of checkboxes on a form extremely easy to deal with... otherwise, it's a big mess to go through the request and figure out what was added and what was removed. Good job Spring.

        Hope this helps someone else.

        Steve

        Comment

        Working...
        X