2012-04-26 57 views
1

我有一個非常簡單的用戶設置形式:調試Spring MVC的集合結合

<form:form method="post" id="fm1" cssClass="fm-v clearfix" commandName="${commandName}" htmlEscape="true"> 
    <div class="row fl-controls-left"> 
    <spring:message code="screen.userSettings.label.timeZone.accesskey" var="timeZoneAccessKey" /> 
    <label for="timeZone" class="fl-label"><spring:message code="screen.userSettings.label.timeZone" /></label> 
    <form:select id="timeZone" path="timeZone" accesskey="${timeZoneAccessKey}"> 
     <form:options items="${user.supportedTimeZones}" itemLabel="label" itemValue="id" /> 
    </form:select> 

    <c:forEach items="${user.answers}" var="answer" varStatus="loop"> 
     <div class="row fl-controls-left"> 
     <form:select path="answers[${loop.index}].questionId"> 
      <option value="-1"><spring:message code="screen.userSettings.question.selectOne" /></option> 
      <form:options items="${user.supportedQuestions}" itemLabel="question" itemValue="id" /> 
     </form:select> 
     <form:input path="answers[${loop.index}].answer" size="30" autocomplete="false" htmlEscape="true" type="text" cssClass="required" cssErrorClass="error"/> 
     </div> 
    </c:forEach> 
    </div> 
</form:form> 

基本上,你可以設置你的時區,並以列表忘記的密碼問題提供答案。綁定到這種形式的模型對象基本上是這樣的:

public class User implements Serializable { 
    private static final long serialVersionUID = 8974875234954842283L; 

    private List<Answer> answers; 
    private List<Question> supportedQuestions; 
    private List<TimeZone> supportedTimeZones; 
    private String timeZone; 

    public User() { 
     credentials = new UsernamePasswordCredentials(); 
    } 

    public List<Answer> getAnswers() { 
     return answers; 
    } 

    public List<Question> getSupportedQuestions() { 
     return supportedQuestions; 
    } 

    public List<TimeZone> getSupportedTimeZones() { 
     return supportedTimeZones; 
    } 

    public String getTimeZone() { 
     return timeZone; 
    } 

    public void setAnswers(List<Answer> answers) { 
     this.answers = answers; 
    } 

    public void setSupportedQuestions(List<Question> supportedQuestions) { 
     this.supportedQuestions = supportedQuestions; 
    } 

    public void setSupportedTimeZones(List<TimeZone> supportedTimeZones) { 
     this.supportedTimeZones = supportedTimeZones; 
    } 

    public void setTimeZone(String timeZone) { 
     this.timeZone = timeZone; 
    } 

    ... 
} 

的形式顯示就好了。它提供一個下拉菜單,顯示所有支持的時區,然後是幾行問題/答案對,問題包含所有支持的問題。當我將表單提交回來時,處理失敗,因爲List<Answer> answers沒有得到表單中的值的更新。我的問題有兩個方面,第一,我做錯了什麼?其次,我將來應該如何調試這種類型的映射問題?

我試過用調試器代碼。 setTimeZone()方法正在從窗體的值調用,但方法不是setAnswers()Answer類的setQuestionId()setAnswer()方法也不是。我查看了Request對象,它具有所有answer[x].questionIdanswer[x].answer參數的鍵值,但不確定這些值是什麼。你會建議如何追蹤這類問題?

-------------------------- UPDATE ------------------- -------------

我剛拔掉這從調試器:

map[ 
'answers[4].questionId' -> 'cn=honeymoon,ou=questions,dc=company' 
'answers[2].questionId' -> 'cn=honeymoon,ou=questions,dc=company' 
'answers[0].questionId' -> 'cn=firstPet,ou=questions,dc=company' 
'lt' -> 'LT-786e9b77-efbd-f302-062e-90364cc4634aZe1s2' 
'answers[1].answer' -> 'qwer' 
'answers[3].answer' -> 'poiu' 
'submit' -> 'Save' 
'answers[3].questionId' -> 'cn=honeymoon,ou=questions,dc=company' 
'answers[1].questionId' -> 'cn=mothersMaiden,ou=questions,dc=company' 
'answers[2].answer' -> 'zxcv' 
'answers[4].answer' -> 'lkjh' 
'timeZone' -> 'America/New_York' 
'_eventId' -> 'submit' 
'answers[0].answer' -> 'asdf' 
] 

這是什麼是包含在requestParameterMap。很明顯,它表明answersquestionIdanswer)的返回值。爲什麼春天不在模型對象上調用setAnswers()(請記住setTimeZone()被調用)?

回答

1

事實證明,這是viewState中活頁夾的一個問題。看起來這應該工作:

<binder> 
    <binding property="answers" /> 
    <binding property="timeZone" /> 
</binder> 

因爲answers是綁定模型對象的屬性。然而,我實際上是指定列表中的元素的屬性:

<binder> 
    <binding property="answers[0].questionId" /> 
    <binding property="answers[0].answer" /> 
    <binding property="answers[1].questionId" /> 
    <binding property="answers[1].answer" /> 
    <binding property="answers[2].questionId" /> 
    <binding property="answers[2].answer" /> 
    <binding property="answers[3].questionId" /> 
    <binding property="answers[3].answer" /> 
    <binding property="answers[4].questionId" /> 
    <binding property="answers[4].answer" /> 
    <binding property="timeZone" /> 
</binder> 

對我來說,這將工作(現在)我有元素的固定大小數。必須包含列表中每個元素的每個屬性都有點痛苦,但它是有效的。有bugs/feature requests申請這應該更容易,但在那之前...