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:
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>
Tenga en cuenta que '
Editar usuario $ {userInstance.username}
' parece hacer posibles las inyecciones de script java – Ralph