Skip to content
Advertisement

I getting an error while i am trying to update an user and not able to show my users roles using SpringBoot

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>
2 People found this is helpful
Advertisement