what i am trying to do after logging in, in the usersPage, i am trying to show all users with their roles and when i click on edit on one of them i get to edit_user page which i will allow me to edit users but i get an error while am doing that and in the usersPage i can’t see user’s roles.
USER ENTITY:
@Entity @Table(name = "users" ,uniqueConstraints = @UniqueConstraint(columnNames = "userName")) public class Users { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String userName; private String password; @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) @JoinTable( name = "users_roles", joinColumns = @JoinColumn( name = "user_id",referencedColumnName ="id"), inverseJoinColumns = @JoinColumn( name ="role_id" ,referencedColumnName ="id" ) ) private Collection<Roles> roles; public Users(String userName, String password, Collection<Roles> roles) { this.userName = userName; this.password = password; this.roles = roles; } public Users() { super(); } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Collection<Roles> getRoles() { return roles; }
UserRegistrationDto
public class UserRegistrationDto { private String userName; private String password; private Collection<Roles> role; public UserRegistrationDto(String userName, String password, Collection<Roles> role) { this.userName = userName; this.password = password; this.role = role; } public UserRegistrationDto() { super(); } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Collection<Roles> getRole() { return role; } public void setRole(Collection<Roles> role) { this.role = role; }
}
UserController
in this controller layer it responsible for getting,deleting,editing users
@Controller public class UserController { @Autowired private UserService userService; @Autowired private RoleRepository roleRepository; public UserController(UserService userService, RoleRepository roleRepository) { this.userService = userService; this.roleRepository = roleRepository; } @ModelAttribute("roles") public List<Roles> initializeRoles(){ List<Roles> roles = roleRepository.findAll(); return roles ; } @GetMapping("/users/AllUsers") public String getAllUsers(Model model) { model.addAttribute("user",userService.getAlluser()); return "Users/users"; } @GetMapping("/user/edit/{id}") public String editUserForm(@PathVariable long id, Model model) { model.addAttribute("user",userService.getUserById(id)); return "Users/edit_user"; } @RequestMapping(value = "/user/update/{id}",method = RequestMethod.POST) public String updateUser(@PathVariable Long id, @ModelAttribute("user") UserRegistrationDto registrationDto) { Users userExisting = userService.getUserById(id); userExisting.setId(id); userExisting.setUserName(registrationDto.getUserName()); userExisting.setRoles(registrationDto.getRole()); userService.updateUser(userExisting); return "redirect:/users/AllUsers"; } @GetMapping("/user/delete/{id}") public String deleteUser(@PathVariable long id) { userService.deleteUser(id); return "redirect:/users/AllUsers"; }
}
UserService
//save a user from the userRegistration form that been shown in the class model public Users save(UserRegistrationDto registrationDto) { //Users user = new Users(registrationDto.getUserName(),passwordEncoder.encode(registrationDto.getPassword()),Arrays.asList(new Roles(registrationDto.setRole(registrationDto.getRole()))));;//Arrays.asList(new Roles("ROLE_USER")) Users usersEntity = new Users(); usersEntity.setUserName(registrationDto.getUserName()); usersEntity.setRoles(registrationDto.getRole()); usersEntity.setPassword(passwordEncoder.encode(registrationDto.getPassword())); return userRepository.save(usersEntity); } @Override public Users getUserById(Long id) { return userRepository.findById(id).get(); } //we converting roles to authorities private Collection <? extends GrantedAuthority> mapRolesToAuthorities(Collection<Roles> roles) { return roles.stream() .map(role -> new SimpleGrantedAuthority(role.getName())) .collect(Collectors.toList()); }
edit_user.html
<form th:action="@{/user/update/{id}}" method="post" th:object="${user}"> <div class="form-group"> <label class="control-label" for="userName"> Username </label> <input id="userName" class="form-control" th:field="*{userName}" required autofocus="autofocus" /> </div> <div class="col-1.5"> <label th:for="roles"> User Type: </label> <select class="form-control form-control-sm" id="roles" name="roles"> <option value="">Select User Type</option> <option th:each = "role: ${roles}" th:value="${role.id}" th:text="${role.name}" > </option> </select> </div> <div class="form-group"> <label class="control-label" for="password"> Password </label> <input id="password" class="form-control" th:field="*{password}" required autofocus="autofocus" type="password" /> </div> <div class="form-group"> <button type="submit" class="btn btn-success">Submit</button> </div> </form>
users.html where i will show all users
<section class="table_content"> <!--main-container-part--> <div id="content"> <!--End-breadcrumbs--> <!--Action boxes--> <div class ="container"> <div class = "row"> <h1> All Users </h1> </div> <br> <br> <table class = "table table-striped table-bordered"> <thead class = "table-dark"> <tr> <th> Name </th> <th> Roles </th> <th> Edit </th> <th> Delete </th> </tr> </thead> <tbody> <tr th:each = "user: ${user}"> <!-- this attribute to list up products --> <td th:text="${user.userName}" ></td> <td th:text="${user.roles}"></td> <td> <center> <a th:href="@{/user/edit/{id}(id=${user.id})}" style="color: green"> Edit </a> </center> </td> <td> <center> <a th:href="@{/user/delete/{id}(id=${user.id}) }" style="color: red"> Delete </a> </center> </td> </tr> </tbody> </table> </div> </div>
Advertisement
Answer
The first error you made is in edit_user.html, as the stack trace you provided says, the endpoint /user/update/{id} is failing to convert ‘{id}’ to a long. That’s because id you are passing is not the user id but the string ‘{id}’ itself.
in edit_user.html change this:
<form th:action="@{/user/update/{id}}" method="post" th:object="${user}">
to
<form th:action="@{/user/update/{id}(id=${user.id})}" method="post" th:object="${user}">
if this still not work I suggest passing userID as an attribute in the model too.
For the second problem, you can’t visualise users roles because of this line in users.html:
<td th:text="${user.roles}"></td>
since User.roles is a collection, it can’t be rendered at “once”, you have to use the same syntax used in edit_user, hence:
<td> <p th:each="role: ${user.roles}" th:text="${role.name}"></p> </td>