2011-08-08 18 views
5

Primera pequeña información de fondo. Obtuve una relación de roles de usuario bastante estándar en la que el usuario puede tener muchos roles. Tengo roles definidos como un conjunto dentro de la clase de usuario. Ahora sé que los formularios html tienen todos los valores como cadenas y tratando de obtener valores porque mi objeto Role personalizado no funciona. Implementé un initbinder para convertir el ID en objeto para que pueda recuperar los valores seleccionados de mis casillas, esa parte funciona.Spring MVC Pre populate casillas de verificación

Pero parece que no puedo volver por el otro lado. Recupero un usuario de la base de datos que ya tiene roles y quiero llenar previamente las casillas de roles con todos los roles que tiene un usuario. En base a este ejemplo:

Checkboxes example

Dicen que:

formulario: casillas de verificación artículos = "$ {-lista dinámica}" path = "propiedad-a-tienda"

Para casillas de verificación múltiples, siempre que el valor "ruta" o "propiedad" sea igual a cualquiera de los "valores de casilla de verificación - $ {lista dinámica"), la casilla correspondiente se marcará automáticamente.

Mi interpretación de eso es que debería ser capaz de alimentarlo con un conjunto de todos los roles y definir la ruta para que sean los roles del objeto User y debería coincidir haciendo que la casilla de verificación se llene previamente.

Cada ejemplo parece tener el valor de dynamic-list como String []. Bueno, eso es genial y elegante, pero ¿cómo funciona esto para los objetos personalizados que nuestro definido como un conjunto? ¿Puedo seguir usando esta definición de una línea para las casillas de verificación o necesito hacer algún tipo de enlace de datos en la vista también?

Aquí está mi dto de usuario, controlador de usuario, encuadernador de formulario personalizado y página de edición de usuario.

usuario DTO

@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<Role> 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<Role> getRoles() 
    { 
     return roles; 
    } 

    public void setRoles(final Set<Role> rolesIn) 
    { 
     roles = rolesIn; 
    } 
} 

Usuario del Controlador

@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<RoleDao>(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<Role>(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<Role>(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<Role>(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<User> list() 
    { 
     return userDao.findAll(); 
    } 
} 

formulario personalizado Carpeta

public class CustomFormBinder<T extends GenericDao> 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; 
     } 
    } 

} 

Editar usuario Ver

<html> 
    <head> 
     <title>Create User</title> 
    </head> 
    <body> 

    <c:url value="/user/update" var="actionUrl"/> 
    <form:form method="post" commandName="userInstance" action="${actionUrl}"> 
     <h1>Edit User ${userInstance.username}</h1> 

     <div> 
      <form:label path="username">Username:</form:label> 
      <form:input path="username" id="username" readonly="true"/> 
     </div> 

     <div> 
      <form:label path="password">Password:</form:label> 
      <form:input path="password" id="password" type="password" readonly="true"/> 
      <tag:errorlist path="userInstance.password" cssClass="formError"/> 
     </div> 

     <div> 
      <form:label path="firstName">First Name:</form:label> 
      <form:input path="firstName" id="firstName"/> 
      <tag:errorlist path="userInstance.firstName" cssClass="formError"/> 
     </div> 

     <div> 
      <form:label path="lastName">Last Name:</form:label> 
      <form:input path="lastName" id="lastName"/> 
      <tag:errorlist path="userInstance.lastName" cssClass="formError"/> 
     </div> 

     <div> 
      <form:label path="email">Email:</form:label> 
      <form:input path="email" id="email" size="30"/> 
      <tag:errorlist path="userInstance.email" cssClass="formError"/> 
     </div> 

     <div> 
     **<%--Want to Pre Populate these checkboxed--%> 
<form:checkboxes title="Assigned Roles:" path="roles" id="roles" items="${validRoles}" itemLabel="displayName" itemValue="id" element="div"/>** 
      <tag:errorlist path="userInstance.roles" cssClass="formError"/> 
     </div> 

     <form:hidden path="enabled"/> 
     <form:hidden path="id"/> 
     <form:hidden path="version"/> 

     <div class="submit"> 
      <input type="submit" value="Update"/> 
      <a href="<c:url value='/user/list'/>" class="cancel">Cancel</a> 
     </div> 
    </form:form> 

    </body> 
    </html> 
+0

Tenga en cuenta que '

Editar usuario $ {userInstance.username}

' parece hacer posibles las inyecciones de script java – Ralph

Respuesta

5

¡Necesita un método igual implementado correcto para Role!

Si esto no es suficiente, eche un vistazo a la clase oorg.springframework.web.servlet.tags.form.AbstractCheckedElementTag. El método void renderFromValue(Object item, Object value, TagWriter tagWriter) es donde se establece el indicador de verificación.

+1

El método equals hizo el truco !! No estoy seguro de que alguna vez pensé en hacer eso. ¡¡GRACIAS!! – sauce

+0

@Ralf - Ahora tengo un problema con este problema ... http: //stackoverflow.com/questions/7003152/openentitymanagerinviewfilter-problems...mind ¿echando un vistazo? – sauce

+0

alguien puede dar un ejemplo sobre cómo se debe escribir el método igual? porque utilicé la función Eclipse generate equals y hashcode, pero tengo algunos problemas ... gracias – SaganTheBest

Cuestiones relacionadas