3

I have a domain object called Order, and it has a collection attribute called serviceOrders where a collection of service --- order m:m association relationships are hold.

public class Order implements Serializable {

 private Long id = null;
 private BigDecimal amountPaid;
 private BigDecimal accountReceivable; 
 private User user;
 private Set serviceOrders = new HashSet();
 private Date closed;
 private Date created = new Date();
 private String status;

also there is a method for adding the association called addServiceOrder

public void addServiceOrder(ServiceOrder serviceOrder) {
  if (serviceOrder == null)
   throw new IllegalArgumentException("Can't add a null serviceOrder.");
  this.getServiceOrders().add(serviceOrder);
 }

how should I use commandName to set this collection with "path", I think it would only call its get set method of the Command Object. how should I add serviceOrder to this command Object. I have no idea about this problem. any help would be highly appreciated

user421038
  • 31
  • 1

2 Answers2

0

Assuming your ServiceOrder instances have unique ids your service method should be #add(Long id).

Jan
  • 2,803
  • 6
  • 36
  • 57
0

Ok bear with me on this one but the solution is simple an annoying at the same time. I ran into this a couple of months ago. I am going to show you my solution using the jstl libraries in my view for handling the collections.

<c:forEach items="${Questions}" var="quest" varStatus="itemsIndex">
        <fieldset>
          <legend>${quest.section}</legend>
          <form:form id="group${itemsIndex.index}" modelAttribute="ChoiceList" action="" method="POST" onsubmit="javascript:ajaxSave($(this).serialize()); return false;">
            <a id="Group${quest.id}"></a>
            <c:forEach items="${quest.qisQuestionsCollection}" var="quest2" varStatus="itemsRow">
              <div style="font-weight: bold; margin: 10px 0px">${quest2.shortText}</div>
              ( ${quest2.qisQuestionTypes.description} )<br/>
          ( ${quest2.helpText} )<br/>
              <a id="Question${quest2.id}"></a>
              <c:choose>
                <c:when test="${quest2.qisQuestionTypes.questionType == 'CHOOSEANY'}">
                  <c:forEach items="${quest2.qisChoicesCollection}" var="quest3" varStatus="indexStatus">
                    <c:forEach items="${ChoiceFields}" var="CField">
                      <c:set scope="request" value="${quest3}" var="ChoiceData"/>
                      <c:set scope="request" value="${CField}" var="ChoiceProperty"/>
                      <%
                                answerMap = (HashMap<QisChoice, Answer>) request.getAttribute("AnswerList");
                                choice = (QisChoice) request.getAttribute("ChoiceData");
                                if (answerMap.containsKey(choice.getChoiceID())) {
                                  Answer theAnswer = (Answer) answerMap.get(choice.getChoiceID());
                                  if (theAnswer != null) {
                                    if (theAnswer.getChoiceValue() != null) {
                                      request.setAttribute("itemValue", theAnswer.getChoiceValue());
                                      request.setAttribute("itemSelected", true);
                                    } else {
                                      request.setAttribute("itemSelected", false);
                                      request.setAttribute("itemValue", getReflectedValue(
                                              (QisChoice) request.getAttribute("ChoiceData"),
                                              (AccessorStruct) request.getAttribute("ChoiceProperty")));
                                    }
                                  }
                                } else {
                                  request.setAttribute("itemSelected", false);
                                  request.setAttribute("itemValue", getReflectedValue(
                                          (QisChoice) request.getAttribute("ChoiceData"),
                                          (AccessorStruct) request.getAttribute("ChoiceProperty")));
                                }
                                request.setAttribute("itemValue2", getReflectedValue(
                                        (QisChoice) request.getAttribute("ChoiceData"),
                                        (AccessorStruct) request.getAttribute("ChoiceProperty")));
                      %>
                      <c:choose>
                        <c:when test="${CField.visible == 'HIDDEN'}">
                          <form:hidden value="${itemValue2}" path="question[${itemsRow.index}].choice[${indexStatus.index}].${CField.beanName}" />
                        </c:when>
                        <c:otherwise>
                          <c:choose>
                            <c:when test="${itemSelected}">
                              <form:checkbox value="${itemValue}" label="${quest3.description}" path="question[${itemsRow.index}].choice[${indexStatus.index}].${CField.beanName}" checked="true" /><br/>
                            </c:when>
                            <c:otherwise>
                              <form:checkbox value="${itemValue}" label="${quest3.description}" path="question[${itemsRow.index}].choice[${indexStatus.index}].${CField.beanName}" /><br/>
                            </c:otherwise>
                          </c:choose>

                        </c:otherwise>
                      </c:choose>
                    </c:forEach>
                  </c:forEach>
                </c:when>

            <input type="submit" value="Save Section"
                   class="button-main" />
          </fieldset>
        </form:form>
      </c:forEach>`

The Key bit is in this line

<form:checkbox value="${itemValue}" label="${quest3.description}" path="question[${itemsRow.index}].choice[${indexStatus.index}].${CField.beanName}" checked="true" /><br/>

To link up the command object with its collection for the postback you have to show the indice of the element as part of the spring path. In my case I have two levels of collections to track

<c:forEach items="${quest.qisQuestionsCollection}" var="quest2" varStatus="itemsRow">

varStatus gives you access to a bean object with the index property you can use to your advantage.

In your case you can do just use the index property of the foreach jstl function in the jsp to generate the indice like I did and append it to the array index notation of your command object. The command object must of course follow the same flow as the path collection names. This works for an infinite number of levels but gets more annoying as we go.

This is a large live example so if you need something smaller show me your markup and I will walk you throgh it.

PaulSCoder
  • 593
  • 5
  • 19