I know there have been already questions around this topic, but I have not figured out how to solve the following issue:
I have a user/roles relationship and I want to list all available roles in a JSP as checkbox items, where the users assigned checkboxes are selected. However, the matching items are not checked (here I am using Spring 3.1).
Extract from the User object:
private Set<RoleEntity> roles = new HashSet<RoleEntity>();
Extract from the Spring Controller (adding user object and role list to Model):
UserEntity userEntity = userEntityService.findById(UserEntity.class, new Long(id));
model.addAttribute("userAttribute", userEntity);
List<RoleEntity> roleList = roleEntityService.findAll();
model.addAttribute("roleList", roleList);
Extract from the JSP:
<form:form modelAttribute="userAttribute" method="POST" action="${saveUrl}">
...
<table align="center">
<tr>
<td>ID</td>
<td>Role Name</td>
</tr>
<c:forEach items="${roleList}" var="role" varStatus="status">
<tr>
<td><form:checkbox path="roles" value="${role}" label="${role.id}" /></td>
<td><c:out value="${role.name}" /></td>
</tr>
</c:forEach>
</table>
...
</form:form>
The Spring MVC documentation says this:
When the bound value is of type array or java.util.Collection, the input(checkbox) is marked as ‘checked’ if the configured setValue(Object) value is present in the bound Collection.
Isn’t that the case here? What am I missing here?
Thanks a lot.
Paul
My guess is you are missing the implementation for the
equalsandhashcodemethods on the RoleEntity class.This is correct, but to check for presence in a
HashSetyou needequalsandhashcodeimplemented correctly.Just as a quick test to see if that’s the problem, replace this line:
with this line:
Do you get all your checkboxes checked? If yes, then you didn’t provide your own
equalsandhashcodeand the default ones are used (those inherited fromObject).The default
equalscompares identity which means that a variable holds the same instance as another variable. Equality means two different object contain the same state or have the same meaning, so to speak.Using
model.addAttribute("roleList", userEntity.getRoles())triggers the defaultequalsmethod to return true because the list and values you check for presence in the list are identical (two identical objects are always equal).But in your case you use
userEntityService.findByIdfor one androleEntityService.findAllfor the other which means different objects. At this point you have to use a proper equality test as opposed to identity.Do you have
equals/hashcodeimplemented?Based on your code, here is an example that works:
Controller:
User class:
Roles class (notice the
equalsandhashcodemethods; if you remove them, the example no longer works):View:
P.S. Just one observation about your JSP. If you do
value="${role}"for your form:checkbox you will get HTML checkbox attributes likevalue="your.pack.age.declaration.RoleEntity@1"which might get you in another sort of trouble later on.