Spring Webflow: binding does not work with map although map values are in the httprequest

StackOverflow https://stackoverflow.com/questions/19397879

  •  30-06-2022
  •  | 
  •  

This question is very similar to this one: Collection/List property won't bind or update on form submit

What i am trying to do is map a set of Checkboxes within a JSP to a Map within a webflow. Binding for example Strings to the model works totally fine. However, the map does not. Here is some example code: The Model:

public class MyForm {
  private String selectedOrderBy;
  private Map<String, boolean> selected = new HashMap<>();
  private List<MyClass> items = new ArrayList<>();
  //Now setters and getters for the members
}

public MyClass {
  private String hash = "<some hash>"; //plus getter and setter
}

The flow:

<flow xmlns="http://www.springframework.org/schema/webflow"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/webflow
                      http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <var name="model" class="MyForm"/>
    <var name="selectedOrderBy" class="java.lang.String"/>

    <view-state id="selection" model="model">
      <binder>
        <binding property="selectedOrderBy"/>
        <binding property="selected"/>
      </binder>
      <transition on="submit" to="saveSelection"/>
    </view-state>

    <action-state id="saveSelection">
      <evaluate expression="MyService.saveSelection(model, externalContext.nativeRequest)"/>
      <transition to="selection"/>
    </action-state>
</flow>

The JSP:

<form:form modelAttribute="model" method="post" enctype="application/x-www-form-urlencoded" acceptCharset="utf-8">
  ...here is some more code including a selectbox mapping to selectOrderBy...
  <table>
    <c:foreach items="${model.items}" var="item">
      <tr><td>
        <form:checkbox path="selected['${item.hash}']" value="true"/>
        ...
      </td></tr>
    </c:foreach>
  </table>
</form:form>

And finally the Service:

@Named
public class MyService {
  public void saveSelection(MyForm model, HttpServletRequest request){...}
}

The checkboxes successfully display the values found in the map. However, on submit, the changed values are not bound to the model (while the String "selectOrderBy" works). So i debugged into MyService#saveSelection, and i found that the map in the model still has the old values. At the same time, the new values are actually in the request.

So for the moment, I manually extract them from the request:

String selected = request.getParameter("selected['" + hash + "']");

But this is some pretty ugly workaround. Does anybody have a clue why this is the case?

Greetings, Sascha.

有帮助吗?

解决方案

I was not able to solve the initial problem. However, I was able to achieve a similar outcome in a much cleaner way by using a List instead of a Map to bind the values. The JSP now says:

<form:checkbox path="selectedList" value="${myClass.hash}"/>

The form:

public class MyForm {
  private String selectedOrderBy;
  private List<String> selectedList = new ArrayList<>(); //selected Items hashes
  private List<MyClass> items = new ArrayList<>(); //All items, regardless of selectionstate
  //Now setters and getters for the members
}

In the Service, the Model now contains a list of selected items. By comparing it with the list of available items (hashes), you basically get the same result.

Greetings.

其他提示

Removing binding restriction makes your sample work. I found some improvement request to allow wildcards on binding properties that seems to be added in version 3.0.0 (https://jira.spring.io/browse/SWF-913).

So, to make your sample work i just remove the binding restrictions.

<view-state id="selection" model="model">
    <transition on="submit" to="saveSelection"/>
</view-state>

Also, notice that by setting value="true" you are making all classes selected by default.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top