Spring does not map set of roles

49 views Asked by At

I work with the Spring framework and I encounter problem with mapping set of roles from many-to-many table. Let me show you my classes.

public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NonNull
    private String authority;

    @ManyToMany(mappedBy = "roles", fetch = FetchType.EAGER/*, cascade=CascadeType.MERGE*/)
    private Set<AppUser> appUsers;

    public Role(@NonNull String authority) {
        this.authority = authority;
    }

    public Role() {

    }
}
public class AppUser implements Serializable {
    @Serial
    private static final long serialVersionUID = -8357820005040969853L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    //    @NonNull
    @Column(unique = true)
    private /*final*/ String username;

    //    @NonNull
    private /*final*/ String password;

    @ManyToMany(fetch = FetchType.EAGER/*, cascade=CascadeType.MERGE*/)
//    @NonNull
    @JoinTable(name = "users_roles",
            joinColumns = @JoinColumn(name = "role_id"/*, referencedColumnName = "id"*/),
            inverseJoinColumns = @JoinColumn(name = "user_id"/*, referencedColumnName = "id"*/))
    private Set<Role> roles;
    }

Here is the saving process:

    @Bean
//    @Transactional
    public CommandLineRunner run(RoleRepository roleRepository, UserRepository userRepository, PasswordEncoder passwordEncoder) {
        return args -> {
            if (roleRepository.findByAuthority("ADMIN").isEmpty()) {
                Role admin = roleRepository.save(new Role("ADMIN"));
                Role user = roleRepository.save(new Role("USER"));

                userRepository.save(new AppUser("admin", passwordEncoder.encode("admin"), new HashSet<>() {
                    {
                        add(admin);
                        add(user);
                    }
                }));
            }
        };
    }

And here is the moment when I want to retrieve roles for the user:

@Component
public class UserInterceptor implements HandlerInterceptor {
    private final UserRepository userRepository;
    private final RoleRepository roleRepository;

    public UserInterceptor(UserRepository userRepository, RoleRepository roleRepository) {
        this.userRepository = userRepository;
        this.roleRepository = roleRepository;
    }

    @Override
    public void postHandle(@NonNull HttpServletRequest request,
                           @NonNull HttpServletResponse response,
                           @NonNull Object handler,
                           ModelAndView modelAndView) {
        if (modelAndView != null) {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            Optional<AppUser> appUser = userRepository.findByUsername(authentication.getName());

            if (appUser.isPresent()) {
                Set<Role> set = roleRepository.findByAppUsers(new HashSet<>() {
                    {
                        add(appUser.get());
                    }
                });
                log.info("Roles for user {}: {}", appUser.get().getUsername(), appUser.get().getRoles());
                modelAndView.addObject("username", appUser.get().getUsername());
                modelAndView.addObject("roles", appUser.get().getRoles());
            } else
                modelAndView.addObject("username", "anonymous");
        }
    }
}

The most interesting part is that when I login into system as the "admin" with the password "admin", it sees my User in the database and I actually have value inside Optional appUser. After checking presence I create simple set just to check, whether it maps roles for particular users and it does, after that I have set of roles retrieved by User object.

And now comes the magic part: if I try to get roles from the user doing appUser.get().getRoles(), I get EMPTY SET OF ROLES IN THE appUser OBJECT. I mean, I could have tried to get all roles using an extra set created by userRepository.findByUsername, but I feel like it shouldn't work this way. Can anyone help me please, I would appreciate it and it would help me to get Spring framework. Thanks in advance. P.S. Here is the table from the database and yes, names of columns are messed up, I've fixed it already.

Database

0

There are 0 answers