Chris Banks
Chris Banks

Reputation:

Form binding a HashMap using annotation based controller in Spring 2.5

I have been hitting a brick wall with this problem for some time and no amount of searching and reading has turned up an answer. I have posted on the Spring forums, but to no avail. Maybe someone here can help?

I have a bean containing a HashMap which I have bound to form using the Spring:form taglib and Spring:bind. Binding to the view works perfectly, but upon submitting the form and handling with an annotation based controller the binding does not appear to work correctly. I get no exceptions, but the HashMap is not populated. Here is my setup:

The JSP:

<form:form method="post" action="updateUserPermissions" modelAttribute="wsPermissions" >
    <table>
        <tr class="head">
            <td>Workspace</td>
            <td>Read?</td>
            <td>Write?</td>
            <td>Manage?</td>
        </tr>
        <c:forEach var="ws" varStatus="wsItem" items="${selectedUserWSs}">
            <c:set var="wsURI" value="'${ws.uri}'"/>
            <tr>
                <td>${ws.kbInfo.name} @ ${ws.community.name}</td>
                <td>
                    <spring:bind path="wsPermissions.map[${ws.uri}].read">
                        <input type="checkbox" <c:if test="${status.value}">checked</c:if> disabled="disabled"/>
                    </spring:bind>
                </td>
                <td>
                    <spring:bind path="wsPermissions.map[${ws.uri}].write">
                        <input type="checkbox" <c:if test="${status.value}">checked</c:if>/>
                    </spring:bind>
                </td>
                <td>
                    <spring:bind path="wsPermissions.map[${ws.uri}].manage">
                        <input type="checkbox" <c:if test="${status.value}">checked</c:if>/>
                    </spring:bind>
                </td>
                <td><a href="removeUserWorkspace?userid=${selectedUser.email}&wsid=${ws.uri}">[Remove]</a></td>
            </tr>
        </c:forEach>
    </table>
    <input type="hidden" name="userid" value="${selectedUser.email}" />
    <input type="submit" value="Update user permissions" />
</form:form>

This displays fine, binding works, the checkboxes show the correct initial values. Form submission is then handled by this controller method:

@RequestMapping
public String updateUserPermissions(@ModelAttribute(value="wsPermissions") WorkspacePermissionMap wsPermissions,
        @RequestParam String userid,
        HttpServletRequest request, ModelMap modelMap){
    // code to update permissions here.....
    LOG.debug(wsPermissions.getMap().size());
    //the above prints zero
    return "redirect:editUser?id="+userid;
}

Debugging the controller method shows that HashMap is empty.

Here is the code for WorkspacePermissionMap:

public class WorkspacePermissionMap {

private Map<String, WorkspacePermission> map = new HashMap<String, WorkspacePermission>();

/**
 * @param map the map to set
 */
public void setMap(Map<String, WorkspacePermission> map) {
    this.map = map;
}

/**
 * @return the map
 */
public Map<String, WorkspacePermission> getMap() {
    return map;
}

}

and for WorkspacePermission:

public class WorkspacePermission {
private boolean read = false;
private boolean write = false;
private boolean manage = false;


/**
 * @return the write
 */
public boolean isWrite() {
    return write;
}
/**
 * @param write the write to set
 */
public void setWrite(boolean write) {
    this.write = write;
    if (write){
        setRead(write);
    } else {
        setManage(write);
    }
}
/**
 * @return the moderate
 */
public boolean isManage() {
    return manage;
}
/**
 * @param moderate the moderate to set
 */
public void setManage(boolean moderate) {
    this.manage = moderate;
    if (moderate){
        setWrite(moderate);
        setRead(moderate);
    }
}
/**
 * @param read the read to set
 */
public void setRead(boolean read) {
    this.read = read;
    if (!read){
        setWrite(read);
        setManage(read);
    }
}
/**
 * @return the read
 */
public boolean isRead() {
    return read;
}

}

Can anybody please point out where I'm going wrong? Am I barking up completely the wrong tree, or have I made a stupid error?

Thank you for your help,

Chris

Upvotes: 1

Views: 9429

Answers (2)

cafebabe
cafebabe

Reputation: 1400

How is that your HTML checkbox element has no name or value attribute on it? Spring isn't supposed to do 'all' the magic for you ;)

Upvotes: 1

Pablojim
Pablojim

Reputation: 8582

There's definitely some weirdness on the jsp path expressions needed for this.

I'm using hard coded values:

applicationDetails['first_name']

or for your example:

wsPermissions.map['hardcodeduri'].read

These work fine for me.

My advice is to try it first hardcoded and then see if you can alter this to use the dynamic variable.

Upvotes: 2

Related Questions