title: Spring MVC Pre Populate Checkboxes
body: <p>First little background info.  Got a fairly standard User Role relationship where the User can have many roles.  I have roles defined as a set within the user class. Now I know that html forms have all the values as strings and trying to get values as my custom Role object does not work.  I implemented an initbinder to convert the id's back into object so that I can retrieve the selected values off of my checkboxes, that part works.</p>
  
  <p>But I can't seem to go back the other way.  I retrieve a User from the database that already has roles and want to pre populate role checkboxes with all the roles that a user has.  Based on this example :</p>
  
  <p><a href="http://www.mkyong.com/spring-mvc/spring-mvc-checkbox-and-checkboxes-example/" rel="noreferrer">Checkboxes example</a></p>
  
  <p>They say that: </p>
  
  <blockquote>
    <p>form:checkboxes items="${dynamic-list}" path="property-to-store"</p>
    
    <p>For multiple checkboxes, as long as the “path” or “property” value is
    equal to any of the “checkbox values – ${dynamic-list}“, the matched
    checkbox will be checked automatically.</p>
  </blockquote>
  
  <p>My interpretation of that is I should be able to feed it a Set of all the roles and define the path to be the roles from the User object and it should match them thus causing the check box to pre populate.</p>
  
  <p>Every example out there seems to have the value of dynamic-list as a String[].  Well thats great and dandy but how does this work for custom objects that our defined as a Set?  Can I still use this one line definition for checkboxes or do I need to do some kind of data binding heading into the view also?</p>
  
  <p>Here is my user dto, user controller, custom form binder, and user edit page.</p>
  
  <p>User DTO</p>
  
  <pre><code>@Entity
  @Table
  public class User extends BaseDto
  {
     @Column(updatable = false) @NotBlank
     private String username;
  
     @Column(name = "encrypted_password") @Size(min = 6, message = "password must be at least 6 characters") @Pattern(regexp = "^\\S*$", message = "invalid character detected")
     private String password;
  
     @Column(name = "first_name")
     private String firstName;
  
     @Column(name = "last_name")
     private String lastName;
  
     @Column @NotNull
     private boolean enabled;
  
     @Column @Email @NotBlank
     private String email;
  
     @Transient
     private String confirmPassword;
  
     @ManyToMany(targetEntity = Role.class, fetch = FetchType.EAGER, cascade = CascadeType.REFRESH) @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id"))
     private Set&lt;Role&gt; roles;
  
     public User()
     {
     }
  
     public User(final String usernameIn, final String passwordIn, final String firstNameIn, final String lastNameIn, final String emailIn, final boolean enabledIn)
     {
        username = usernameIn;
        password = passwordIn;
        firstName = firstNameIn;
        lastName = lastNameIn;
        email = emailIn;
        enabled = enabledIn;
     }
  
     public String getUsername()
     {
        return username;
     }
  
     public void setUsername(final String usernameIn)
     {
        username = usernameIn;
     }
  
     public String getPassword()
     {
        return password;
     }
  
     public void setPassword(final String passwordIn)
     {
        password = passwordIn;
     }
  
     public String getFirstName()
     {
        return firstName;
     }
  
     public void setFirstName(final String firstNameIn)
     {
        firstName = firstNameIn;
     }
  
     public String getLastName()
     {
        return lastName;
     }
  
     public void setLastName(final String lastNameIn)
     {
        lastName = lastNameIn;
     }
  
     public String getEmail()
     {
        return email;
     }
  
     public void setEmail(final String emailIn)
     {
        email = emailIn;
     }
  
     public String getConfirmPassword()
     {
        return confirmPassword;
     }
  
     public void setConfirmPassword(final String confirmPasswordIn)
     {
        confirmPassword = confirmPasswordIn;
     }
  
     public boolean isEnabled()
     {
        return enabled;
     }
  
     public void setEnabled(final boolean enabledIn)
     {
        enabled = enabledIn;
     }
  
     public Set&lt;Role&gt; getRoles()
     {
        return roles;
     }
  
     public void setRoles(final Set&lt;Role&gt; rolesIn)
     {
        roles = rolesIn;
     }
  }
  </code></pre>
  
  <p>User Controller</p>
  
  <pre><code>@Controller @RequestMapping("/user")
  public class UserController
  {
     @Autowired private UserService userService;
     @Autowired private UserDao userDao;
     @Autowired private RoleDao roleDao;
  
     @InitBinder
     public void bindForm(final WebDataBinder binder)
     {
        binder.registerCustomEditor(Set.class, "roles", new CustomFormBinder&lt;RoleDao&gt;(roleDao, Set.class));
     }
  
     @RequestMapping(method = RequestMethod.GET)
     public String index(final ModelMap modelMap)
     {
        return "/user/index";
     }
  
     @RequestMapping(value = "/create", method = RequestMethod.GET)
     public String create(final ModelMap modelMap)
     {
        modelMap.addAttribute("userInstance", new User());
        modelMap.addAttribute("validRoles",  new HashSet&lt;Role&gt;(roleDao.findAll()));
  
        return "/user/create";
     }
  
     @RequestMapping(value = "/save", method = RequestMethod.POST)
     public String save(final ModelMap modelMap, @Valid @ModelAttribute("userInstance") final User user, final BindingResult bindingResult)
     {
        // TODO move to service validation
        if (user.getPassword() == null || !user.getPassword().equals(user.getConfirmPassword()) )
        {
           bindingResult.addError(new FieldError("userInstance", "password", "password fields must match"));
           bindingResult.addError(new FieldError("userInstance", "confirmPassword", "password fields must match"));
        }
        if (user.getRoles() == null || user.getRoles().isEmpty())
        {
           bindingResult.addError(new FieldError("userInstance", "roles", "Must select at least one role for a User"));
        }
        if (bindingResult.hasErrors())
        {
           modelMap.addAttribute("validRoles",  new HashSet&lt;Role&gt;(roleDao.findAll()));
           return "/user/create";
        }
  
        userService.save(user);
        return "redirect:/user/list";
     }
  
     @RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
     public String edit(@PathVariable final Integer id, final ModelMap modelMap)
     {
        final User user = userDao.find(id);
  
        if (user != null)
        {
           modelMap.addAttribute("userInstance", user);
           modelMap.addAttribute("validRoles",  new HashSet&lt;Role&gt;(roleDao.findAll()));
           return "/user/edit";
        }
        return "redirect:/user/list";
     }
  
     @RequestMapping(value = "/edit", method = RequestMethod.GET)
     public String editCurrent(final ModelMap modelMap)
     {
        return edit(userService.getLoggedInUser().getId(), modelMap);
     }
  
     @RequestMapping(value = "/update", method = RequestMethod.POST)
     public String update(@Valid @ModelAttribute("userInstance") final User user, final BindingResult bindingResult)
     {
        if (bindingResult.hasErrors())
        {
           return "/user/edit";
        }
  
        userService.save(user);
        return "redirect:/user/list";
     }
  
     @ModelAttribute("userInstances")
     @RequestMapping(value = "/list", method = RequestMethod.GET)
     public List&lt;User&gt; list()
     {
        return userDao.findAll();
     }
  }
  </code></pre>
  
  <p>Custom Form Binder</p>
  
  <pre><code>public class CustomFormBinder&lt;T extends GenericDao&gt; extends CustomCollectionEditor
  {
     private final T dao;
  
     private static final Logger LOG = LoggerFactory.getLogger(CustomFormBinder.class);
  
     public CustomFormBinder(final T daoIn, final Class collectionType)
     {
        super(collectionType, true);
        dao = daoIn;
     }
  
     @Override
     protected Object convertElement(final Object element)
     {
        try
        {
           // forms should return the id as the itemValue
           return dao.find(Integer.valueOf(element.toString()));
        }
        catch (NumberFormatException e)
        {
           LOG.warn("Unable to convert " + element + " to an integer");
           return null;
        }
     }
  
  }
  </code></pre>
  
  <p>User Edit View</p>
  
  <pre><code>    &lt;html&gt;
      &lt;head&gt;
          &lt;title&gt;Create User&lt;/title&gt;
      &lt;/head&gt;
      &lt;body&gt;
  
      &lt;c:url value="/user/update" var="actionUrl"/&gt;
      &lt;form:form method="post" commandName="userInstance" action="${actionUrl}"&gt;
          &lt;h1&gt;Edit User ${userInstance.username}&lt;/h1&gt;
  
          &lt;div&gt;
              &lt;form:label path="username"&gt;Username:&lt;/form:label&gt;
              &lt;form:input path="username" id="username" readonly="true"/&gt;
          &lt;/div&gt;
  
          &lt;div&gt;
              &lt;form:label path="password"&gt;Password:&lt;/form:label&gt;
              &lt;form:input path="password" id="password" type="password" readonly="true"/&gt;
              &lt;tag:errorlist path="userInstance.password" cssClass="formError"/&gt;
          &lt;/div&gt;
  
          &lt;div&gt;
              &lt;form:label path="firstName"&gt;First Name:&lt;/form:label&gt;
              &lt;form:input path="firstName" id="firstName"/&gt;
              &lt;tag:errorlist path="userInstance.firstName" cssClass="formError"/&gt;
          &lt;/div&gt;
  
          &lt;div&gt;
              &lt;form:label path="lastName"&gt;Last Name:&lt;/form:label&gt;
              &lt;form:input path="lastName" id="lastName"/&gt;
              &lt;tag:errorlist path="userInstance.lastName" cssClass="formError"/&gt;
          &lt;/div&gt;
  
          &lt;div&gt;
              &lt;form:label path="email"&gt;Email:&lt;/form:label&gt;
              &lt;form:input path="email" id="email" size="30"/&gt;
              &lt;tag:errorlist path="userInstance.email" cssClass="formError"/&gt;
          &lt;/div&gt;
  
          &lt;div&gt;
           **&lt;%--Want to Pre Populate these checkboxed--%&gt;   
  &lt;form:checkboxes title="Assigned Roles:" path="roles" id="roles" items="${validRoles}" itemLabel="displayName" itemValue="id" element="div"/&gt;**
              &lt;tag:errorlist path="userInstance.roles" cssClass="formError"/&gt;
          &lt;/div&gt;
  
          &lt;form:hidden path="enabled"/&gt;
          &lt;form:hidden path="id"/&gt;
          &lt;form:hidden path="version"/&gt;
  
          &lt;div class="submit"&gt;
              &lt;input type="submit" value="Update"/&gt;
              &lt;a href="&lt;c:url value='/user/list'/&gt;" class="cancel"&gt;Cancel&lt;/a&gt;
          &lt;/div&gt;
      &lt;/form:form&gt;
  
      &lt;/body&gt;
      &lt;/html&gt;
  </code></pre>