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>
CodePudding user response:
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>