type-conversionstruts2ognl

How to pass a Map<ObjectA, List<ObjectB>> to action in Struts 2?


I have an event object, inside there is a Map<ObjectA, List<ObjectB>>, the ObjectA is the label, and the List<ObjectB> are table rows. With following code, I can display the tables correctly, but when I submit the form to Action class, the map is null inside the event.

JSP code:

<s:iterator value="event.planMap" var="map" >
    <h4>Plan Type: <s:property value='key' /></h4>
    <table id="plan">
    <s:iterator value="value" status="stat" var="detail" >
        <tr>
            <td><input type="text" id="name" name="event.planMap['%{#map.key}'][%{#stat.index}].name" value="<s:property value='name'/>"/></td>
            <td><input type="text" id="text" name="event.planMap['%{#map.key}'][%{#stat.index}].text" value="<s:property value='text'/>"/></td>
            <td><input type="text" id="contact" name="event.planMap['%{#map.key}'][%{#stat.index}].contact" value="<s:property value='contact'/>"/></td>
        </tr>
        </s:iterator>
    </table>
</s:iterator>

So, I modified the code. Displaying the table is correct, but I got error, and it went to result input. If I remove the planMap, the action goes to success. So, at least I know, the error is the planMap. The modified code is:

The Event definition:

public Event {
    private Map<Object_A, Object_B> planMap;
    public Map<Object_A, Object_B> getPlanMap {
           return this.planMap;
    }

    public void setPlanMap(Map<Object_A, Object_B> planMap) {
           this.planMap = planMap;
    }
}

The Object_B definition:

public Object_B {
    private List<Object_C> details;
    
    public List<Object_C> getDetials() {
           return this.details;
    }
    public void setDetails(List<Object_C> details) {
           this.details = details;
    }
}

The JSP code is:

<s:iterator value="event.planMap" status="mStat"  >
    <h4>Plan Type: <s:property value='key' /></h4>
    <table id="plan">
    <s:iterator value="value.details" status="stat">
    <tr>
        <td><input type="text" id="name" name="event.planMap['% {#mStat.index}'].details[%{#stat.index}].name" value="<s:property value='name'/>"/></td>
        <td><input type="text" id="text" name="event.planMap['%{#mStat.index}'].details[%{#stat.index}].text" value="<s:property value='text'/>"/></td>
        <td><input type="text" id="contact" name="event.planMap['%{#mStat.index}'].details[%{#stat.index}].contact" value="<s:property value='contact'/>"/></td>
    </tr>
    </s:iterator>
</table>
</s:iterator>
      

Solution

  • I made it work after the following change.

    <s:iterator value="event.planMap" status="mStat"  >
    <h4>Plan Type: <s:property value='key' /></h4>
    <table id="plan">
    <s:iterator value="value.details" status="stat">
    <tr>
        <td><s:textfield id="name" name="event.planMap['%{key}'].details[%{#stat.index}].name" /></td>
        <td><s:textfield  id="text" name="event.planMap['%{key}'].details[%{#stat.index}].text" /></td>
        <td><s:textfield id="contact" name="event.planMap['%{key}].details[%{#stat.index}].contact" /></td>
    </tr>
    </s:iterator>