Search code examples
jspstruts2ognl

Struts2 binding a map inside an object to an action attribute


Part 1: There is an object (ObjectA) which has another object (ObjectB). There is a Hashmap inside the Object B. This hashmap has a string as key and another object "ObjectC" as value. This hashmap has been displayed on the jsp using the s:iterator and s:textfield and it is being displayed correctly. i.e. the "values" inside the s:textfield are correct but the "name" are not. Now, the problem arises when the textfield is modified. How do we capture the modified values inside ObjectC in the action class?

public class ObjectA implements Serializable {
    private Integer attr1;
    private List<ObjectB> objB;
    //...getters and setters....
public class ObjectB implements Serializable {
private Integer attr11;
private Map<String,ObjectC> myMap;
    // ...getters and setters....
public class ObjectC implements Serializable {
private Integer attr111;
public String attr112;
    // ...getters and setters....

jsp code:

<s:iterator value="#objB.myMap" var="fieldMap" status="fieldStatus">

<li><label><s:property value="#fieldMap.key"/></label><span>
<s:textfield name="<NOT SURE>" value="%{#fieldMap.value.attr12}"  /></span></li>



</s:iterator> 

Solution

  • In your case, objB is a List contanining an HashMap, then one HashMap for every element of the List.

    objA
      |--- objB[0]
        |-- objC[A]
        |-- objC[B]
        |-- objC[C]
      |--- objB[1]
        |-- objC[X]
        |-- objC[Y]
        |-- objC[Z]
      |--- objB[n]
        |-- objC[N1]
        |-- objC[N2]
        |-- objC[N3]
    

    Then you need two iterators and the following OGNL notation, to refer to the single elements with the name attribute:

    <s:iterator value="objA.objB" var="listRow" status="listStatus">
    <!-- Iterating the List -->
        <s:iterator value="#listRow.myMap" var="mapRow" >
        <!-- Iterating the Map -->
            <li>
                <label>
                    <s:property value="#mapRow.key"/>
                </label>
                <span>
                    <s:textfield value="%{#mapRow.value.attr12}"  
                      name="objA.objB[#listStatus.index].myMap[#mapRow.key].attr112"
                    />
                </span>
            </li>
        </s:iterator> 
    </s:iterator>