Insert users id to the patient in Spring Boot - spring

I can't insert the id of the currently logged-in user while making the patient data.
I want the user to be able to add his own patients, but the problem is that when I add a new patient, the column id_user is null
I tried lots of ways but couldn't add id_user to the patient.
What do I miss?
This is my User Entity:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idUser;
private String firstName;
private String lastName;
private String username;
...
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
#JoinTable(name = "users_roles",
joinColumns = #JoinColumn(name = "id_user"),
inverseJoinColumns = #JoinColumn(name = "id_role"))
#JsonManagedReference
private Set<Role> roles = new HashSet<>();
#OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
private List<Patient> patients = new ArrayList<>();
public void add(Patient patient) {
if (patient != null) {
if (patients == null) {
patients = new ArrayList<>();
}
patients.add(patient);
patient.setUser(this);
}
}
Patient Entity:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_patient")
private int idPatient;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
...
#ManyToOne
#JoinColumn(name = "user_id", nullable = false)
private User user;
}
Controller
#RequestMapping("/addPatient")
public String addPatient(Model theModel, HttpServletRequest request) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
UserDetails userD = (UserDetails) auth.getPrincipal();
User u = userService.findByUsername(userD.getUsername());
request.getSession().setAttribute("id_user", u.getIdUser());
// int userId = user.getIdUser();
int userId = (int) request.getSession().getAttribute("id_user");
User user = new User();
user.setIdUser(userId);
Patient patient = new Patient();
patient.setUser(user);
theModel.addAttribute("patient", patient);
return "user/patients/add-patient-dashboard";
}
#PostMapping("savePatient")
public String savePatient(#ModelAttribute("patient") Patient thePatient, Model model) {
patientService.save(thePatient);
return "redirect:/user/allPatients";
}
I try editing the User service from:
#Override
public void save(User user) {
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
userRepository.save(user);
}
to:
#Override
public void save(User user) {
List<Patient> patients = user.getPatients();
patients.forEach(patient -> user.add(patient));
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
userRepository.save(user);
}
if someone can help me resolve this I would appreciate it since I'm struggling for a very long time with this

Thanks to M Denium I finally solve the issue. I have moved the whole code from addUser to saveUser method:
#RequestMapping("/addPatient")
public String addPatient(Model theModel) {
Patient patient = new Patient();
theModel.addAttribute("patient", patient);
return "user/patients/add-patient-dashboard";
}
#PostMapping("savePatient")
public String savePatient(#ModelAttribute("patient") Patient thePatient, Model model, HttpServletRequest request) {
patientService.save(thePatient);
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
UserDetails userD = (UserDetails) auth.getPrincipal();
User u = userService.findByUsername(userD.getUsername());
request.getSession().setAttribute("id_user", u.getIdUser());
int userId = (int) request.getSession().getAttribute("id_user");
User user = userService.findById(userId);
thePatient.setUser(user);
patientService.save(thePatient);
return "redirect:/user/allPatients";
}

Related

Detached entity passed to persist when I try to save an entity

I'm getting this error when I try to save my user entity to the database
org.hibernate.PersistentObjectException: detached entity passed to persist: kpi.diploma.ovcharenko.entity.user.AppUser
Some more information where where does this error appear
at kpi.diploma.ovcharenko.service.user.LibraryUserService.createPasswordResetTokenForUser(LibraryUserService.java:165) ~[classes/:na]
at kpi.diploma.ovcharenko.service.user.LibraryUserService$$FastClassBySpringCGLIB$$ca63bf4b.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.10.jar:5.3.10]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.3.10.jar:5.3.10]
at kpi.diploma.ovcharenko.service.user.LibraryUserService$$EnhancerBySpringCGLIB$$6160822e.createVerificationTokenForUser(<generated>) ~[classes/:na]
at kpi.diploma.ovcharenko.service.activation.RegistrationListener.confirmRegistration(RegistrationListener.java:39) ~[classes/:na]
at kpi.diploma.ovcharenko.service.activation.RegistrationListener.onApplicationEvent(RegistrationListener.java:32) ~[classes/:na]
at kpi.diploma.ovcharenko.service.activation.RegistrationListener.onApplicationEvent(RegistrationListener.java:16) ~[classes/:na]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176) ~[spring-context-5.3.10.jar:5.3.10]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169) ~[spring-context-5.3.10.jar:5.3.10]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143) ~[spring-context-5.3.10.jar:5.3.10]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421) ~[spring-context-5.3.10.jar:5.3.10]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378) ~[spring-context-5.3.10.jar:5.3.10]
at kpi.diploma.ovcharenko.controller.UserController.registerUserAccount(UserController.java:96) ~[classes/:na]
As you can see error appeared in this method. In this method I create a verification token for user
#Override
#Transactional
public void createVerificationTokenForUser(final AppUser user, final String token) {
final VerificationToken myToken = new VerificationToken(token, user);
verificationTokenRepository.save(myToken);
}
I call this method in my RegistrationListener
private void confirmRegistration(OnRegistrationCompleteEvent event) {
AppUser user = event.getUser();
log.info(user.toString());
String token = UUID.randomUUID().toString();
userService.createVerificationTokenForUser(user, token);
final SimpleMailMessage email = constructEmailMessage(event, user, token);
mailSender.send(email);
}
And how I call my confirmRegistration method in the RegistrationListener
#Override
public void onApplicationEvent(OnRegistrationCompleteEvent event) {
this.confirmRegistration(event);
}
And this RegistrationListener I used in my Controller like this
#PostMapping("/registration")
public String registerUserAccount(#ModelAttribute("user") #Valid UserModel userModel, BindingResult result, HttpServletRequest request) {
AppUser existing = userService.findByEmail(userModel.getEmail());
if (existing != null) {
result.rejectValue("email", null, "There is already an account registered with that email");
}
if (result.hasErrors()) {
return "registration";
}
AppUser registeredUser = userService.save(userModel);
log.info(registeredUser.toString());
String appUrl = request.getContextPath();
eventPublisher.publishEvent(new OnRegistrationCompleteEvent(registeredUser, request.getLocale(), appUrl));
return "redirect:/regSuccessfully";
}
As you can see I have log.info() in the controller and in the listener, its because I thought that the problem can be because something wrong with user ID, but, when my logs showed that with user and user id is everything is ok
2022-05-16 21:33:27.522 INFO 65143 --- [nio-8080-exec-7] k.d.o.controller.UserController : AppUser{id=42, firstName='ovcharenko.messor#gmail.com', lastName='ovcharenko.messor#gmail.com', email='ovcharenko.messor#gmail.com', telephoneNumber='', password='$2a$10$4ao20SYR2QJsQ.Fj50Jek.ZBRG0R0g9N8t3iaksUx2.byIb0fj6Y6', registrationDate=2022-05-16 21:33:27.492, enabled=false, roles=[kpi.diploma.ovcharenko.entity.user.UserRole#bbe3026f], bookCards=[]}
2022-05-16 21:33:27.523 INFO 65143 --- [nio-8080-exec-7] k.d.o.s.activation.RegistrationListener : AppUser{id=42, firstName='ovcharenko.messor#gmail.com', lastName='ovcharenko.messor#gmail.com', email='ovcharenko.messor#gmail.com', telephoneNumber='', password='$2a$10$4ao20SYR2QJsQ.Fj50Jek.ZBRG0R0g9N8t3iaksUx2.byIb0fj6Y6', registrationDate=2022-05-16 21:33:27.492, enabled=false, roles=[kpi.diploma.ovcharenko.entity.user.UserRole#bbe3026f], bookCards=[]}
And another point is that after I try to register user, i am getting the error as above, but my user is successfully saved into the database
[
Here is my AppUser class and VerificationToken class
#Getter
#Setter
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Builder(toBuilder = true)
#Table(uniqueConstraints = #UniqueConstraint(columnNames = "email"), name = "library_user")
public class AppUser {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotEmpty
#Column(name = "first_name")
private String firstName;
#NotEmpty
#Column(name = "last_name")
private String lastName;
#NotEmpty
#Email
#Column(name = "email")
private String email;
#Column(name = "number")
private String telephoneNumber;
#NotEmpty
#Column(name = "password")
private String password;
#CreationTimestamp
#Column(name = "create_time")
private Timestamp registrationDate;
#Column(name = "enabled")
private boolean enabled;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(
name = "user_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private Collection<UserRole> roles = new HashSet<>();
#EqualsAndHashCode.Exclude
#OnDelete(action = OnDeleteAction.CASCADE)
#OneToMany(mappedBy = "book", fetch = FetchType.EAGER)
private Set<BookCard> bookCards = new HashSet<>();
public void addBookCard(BookCard bookCard) {
bookCards.add(bookCard);
bookCard.setUser(this);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AppUser user = (AppUser) o;
return Objects.equals(id, user.id) &&
Objects.equals(firstName, user.firstName) &&
Objects.equals(lastName, user.lastName) &&
Objects.equals(email, user.email) &&
Objects.equals(password, user.password);
}
#Override
public int hashCode() {
return Objects.hash(id, firstName, lastName, email, password);
}
public void setRoles(Collection<UserRole> roles) {
this.roles = roles;
}
#Override
public String toString() {
return "AppUser{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", telephoneNumber='" + telephoneNumber + '\'' +
", password='" + password + '\'' +
", registrationDate=" + registrationDate +
", enabled=" + enabled +
", roles=" + roles +
", bookCards=" + bookCards +
'}';
}
}
#Getter
#Setter
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Builder(toBuilder = true)
#Table(name = "verification_token")
public class VerificationToken {
private static final int EXPIRATION = 60 * 24;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String token;
#OneToOne
#JoinColumn(nullable = false, name = "user_id", foreignKey = #ForeignKey(name = "FK_VERIFY_USER"))
private AppUser user;
private Date expiryDate;
public VerificationToken(final String token, final AppUser user) {
super();
this.token = token;
this.user = user;
this.expiryDate = calculateExpiryDate();
}
public Long getId() {
return id;
}
public String getToken() {
return token;
}
public void setToken(final String token) {
this.token = token;
}
public AppUser getUser() {
return user;
}
public void setUser(final AppUser user) {
this.user = user;
}
public Date getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(final Date expiryDate) {
this.expiryDate = expiryDate;
}
private Date calculateExpiryDate() {
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(new Date().getTime());
cal.add(Calendar.MINUTE, VerificationToken.EXPIRATION);
return new Date(cal.getTime().getTime());
}
public void updateToken(final String token) {
this.token = token;
this.expiryDate = calculateExpiryDate();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
VerificationToken that = (VerificationToken) o;
return Objects.equals(token, that.token) && Objects.equals(user, that.user) && Objects.equals(expiryDate, that.expiryDate);
}
#Override
public int hashCode() {
return Objects.hash(token, user, expiryDate);
}
}
I tried different variants with of cascade type , for example (cascade = CascadeType.ALL, cascade = CascadeType.MERGE). Also as you can see in VerificationToken class, I tried to delete any type of cascade, but it doesn't help me. I don't have any idea how can I solve this problem
You probably load the user within a transaction and then create and publish an event on which you set the user. After the transactional method where you created and published the event has ended, the transaction ends as well and the AppUser entity becomes detached from the persistence context. In order to use it further like an entity that you have just obtained from a repository or the EntityManager, you need to "reattach" it to the context. You can read more about the lifecycle of a Hibernate entity in the Hibernate docs or in this Baldung article.
Alternatively, you could load the AppUser again within the same transaction where you want to persist the VerificationToken. You could for example change your method to:
private final AppUserRepository appUserRepository;
#Override
#Transactional
public void createVerificationTokenForUser(final String userId, final String token) {
final AppUser user = appUserRepository.findById(userId).orElseThrow();
final VerificationToken myToken = new VerificationToken(token, user);
verificationTokenRepository.save(myToken);
}

Spring Jpa - Records deleted and re-inserted upon addition/deletion in join table

I have 3 entities user, role and user_roles.
User and Role entity have a one-to-many relationship with the UserRoles entity which is a join table. I have added user_roles as a entity because we plan to have additional properties in future as part of the join table.
User Entity
#Entity
#Table(name = "users")
public class User
{
#Id
#Column(name = "user_id")
#GeneratedValue(generator = RandomIdGenerator.GENERATOR_NAME)
#GenericGenerator(name = RandomIdGenerator.GENERATOR_NAME, strategy = "com.cs.util.RandomIdGenerator")
private Long id;
#Column(name = "email", nullable = false)
private String email;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
#OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER,mappedBy = "user", orphanRemoval = true)
private List<UserRole> userRoles = new ArrayList<UserRole> ();
#JsonSerialize(using = ToStringSerializer.class)
public Long getId ()
{
return id;
}
public void setId (Long id)
{
this.id = id;
}
public String getEmail()
{
return email;
}
public void setEmail (String email)
{
this.email = email;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
#Transient
public Set<Role> getRoles()
{
Set<Role> roles = new HashSet<Role> ();
for (UserRole userRole : this.userRoles)
{
roles.add (userRole.getRole ());
}
return roles;
}
#JsonIgnore
public List<UserRole> getUserRoles()
{
return userRoles;
}
}
Role Entity
#Entity
#Table(name="roles")
public class Role {
#Id
#Column(name = "role_id")
#GeneratedValue(generator = RandomIdGenerator.GENERATOR_NAME)
#GenericGenerator(name = RandomIdGenerator.GENERATOR_NAME, strategy = "com.cs.util.RandomIdGenerator")
private Long id;
#Column(name="name", nullable = false)
private String name;
#Column(name="description", nullable = true)
private String description;
#Column(name = "suspend_flag")
private int suspendFlag;
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(name = "roles_permission",
joinColumns = #JoinColumn(name = "role_id"),
inverseJoinColumns = #JoinColumn(name = "permission_id"))
private Set<Permission> permissions= new HashSet<>();
#OneToMany(mappedBy = "role")
private List<UserRole> userRoles = new ArrayList<UserRole>();
#JsonSerialize(using=ToStringSerializer.class)
public Long getId ()
{
return id;
}
public void setId (Long id)
{
this.id = id;
}
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
public String getDescription ()
{
return description;
}
public void setDescription (String description)
{
this.description = description;
}
public Set<Permission> getPermissions ()
{
return permissions;
}
public int getSuspendFlag ()
{
return suspendFlag;
}
public void setSuspendFlag (int suspendFlag)
{
this.suspendFlag = suspendFlag;
}
}
UserRole Entity
#Entity
#Table(name = "user_roles")
public class UserRole
{
public UserRole ()
{
}
public UserRole (User user, Role role)
{
this.user = user;
this.role = role;
}
#Id
#Column(name = "user_role_id")
#GeneratedValue(generator = RandomIdGenerator.GENERATOR_NAME)
#GenericGenerator(name = RandomIdGenerator.GENERATOR_NAME, strategy = "com.cs.util.RandomIdGenerator")
private Long id;
#ManyToOne
#JoinColumn(name = "user_id", referencedColumnName = "user_id")
private User user;
#ManyToOne
#JoinColumn(name = "role_id", referencedColumnName = "role_id")
private Role role;
public Long getId ()
{
return id;
}
public void setId (Long id)
{
this.id = id;
}
#JsonIgnore
public User getUser ()
{
return user;
}
public void setUser (User user)
{
this.user = user;
}
public Role getRole ()
{
return role;
}
public void setRole (Role role)
{
this.role = role;
}
}
With above code everything works fine but whenever I insert or delete a user_role all the records in the user_role table are deleted and re-inserted again.
For instance when I associate a new user_role to a user the existing user_role is deleted first and then it is re-associated again along with the new user role.
Hibernate: delete from user_roles where user_role_id=?
Hibernate: insert into user_roles (role_id, user_id, user_role_id) values (?, ?, ?)
Hibernate: insert into user_roles (role_id, user_id, user_role_id) values (?, ?, ?)
This is how I add a user role to the user entity.
UserRole userRole = new UserRole(user,role);
user.getUserRoles ().add (userRole);
m_userRepository.save (_user)
And then delete the user role from user like below
List<UserRole> uRolesTobeRemoved = new ArrayList<UserRole> ();
for(Role role : userRoles)
{
UserRole uRole = user.getUserRoles ().stream ().filter (userRole ->
userRole.getRole ().getId () == role.getId ()).collect (Collectors.toList ()).get (0);
uRolesTobeRemoved.add (uRole);
}
user.getUserRoles ().removeAll (uRolesTobeRemoved);
I'm not sure what is missing.
It looks like you see this behaviour due to so called "collection recreation".
Try to replace List<UserRole> userRoles to Set<UserRole> userRoles.
More detailed explanation you can find here.

How to fix jpa one to many

Need to fetch data from one table to another.I performed jpa one to many mapping. But id cannot fetched. Where is my mistake?
I have tried mapping using one to many and many to one concepts but can't able to fetch data from one table to another
User.java
#Entity
#Table(name = "users")
public class User implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "User_ID")
#GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy = "uuid")
private String id;
private String firstName;
private String lastName;
private Long phoneNumber;
#NotNull(message="Password is compulsory")
#Email(message = "Email is invalid")
private String email;
private String password;
#OneToMany(mappedBy="user", cascade = CascadeType.ALL)
Set<Data> data = new HashSet<Data>();
public Set<Data> getData() {
return data;
}
public void setData(Set<Data> data) {
this.data = data;
}
public User() {
super();
}
Data.java
#Entity
#Table(name = "data")
public class Data implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "DataID")
#GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy = "uuid")
private String id;
#ManyToOne(fetch = FetchType.EAGER,cascade= CascadeType.ALL)
#JoinColumn(name = "User_ID")
private User user;
public Data() {
super();
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
DataController.java
#PostMapping("/data/{userId}")
public Data createData(
#PathVariable(value= "userId") String userId,
#Valid #RequestBody Data data) {
return userRepository.findById(userId).map(user -> {
data.setUser(user);
return dataRepository.save(data);
}).orElseThrow(() -> new ResourceNotFoundException("userId" + userId +
"not found"));
}
Results in no error but can't able to fetch user id

Roles not getting fetched from database along with the user object

I am creating a user registration flow with spring boot (2.1.3.RELEASE) . With the help of few articles I am able to successfully add a user along with its roles and user is able to login into the system. The problem is when user is successfully loged-in, the authentication obect has empty role even when I can see th correct role mapping in mysql database (honestly I am not able to get exactly how roles are fetched from database when findByUserName method is called.
Below is my code:
Entity objects
1. User.java
public class User implements UserDetails {
private static final long serialVersionUID = 1L;
public User() {
//Verification flow 2. set enabled = false
this.enabled = false;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_unique_number")
private long id;
#UniqueUser(groups = UniqueUserOrder.class)
#Column(name = "username", length = 60,nullable = false, unique = true)
private String username;
#Column(name = "email", nullable = false, unique = true)
private String email;
#Column(name = "password", nullable = false)
private String password;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<UserRole> userRoles = new HashSet<>();
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authorities = new HashSet<>();
userRoles.forEach(ur -> authorities.add(new Authority(ur.getRole().getName())));
return authorities;
}
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles = userRoles;
}
...//OTHER GETTERS AND SETTERS
}
Roles.java
public class Role
{#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
private String name;
#OneToMany(mappedBy = "role", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<UserRole> userRoles = new HashSet<>();
public Role() {
}
public Role(RolesEnum rolesEnum) {
this.id = rolesEnum.getId();
this.name = rolesEnum.getRoleName();
}
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles = userRoles;
}
...//OTHER GETTERS AND SETTERS }
UserRole.java
public class UserRole {
public UserRole() {}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
public UserRole(User user, Role role) {
this.user = user;
this.role = role;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "user_id")
private User user;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "role_id")
private Role role;
...//OTHER GETTERS AND SETTERS
}
4.RolesEnum.java
public enum RolesEnum {
ADMIN(1, "ROLE_ADMIN"),
BASIC(2, "ROLE_BASIC");
private final int id;
private final String roleName;
...//OTHER GETTERS AND SETTERS
}
New user is getting created as below:
...
...
String encryptedPassword = passwordEncoder.encode(adminPassword);
user.setPassword(encryptedPassword);
user.setUsername(adminUsername);
user.setEmail(adminEmail);
user.setUserCreateTime(LocalDateTime.now());
Set<UserRole> userRoles = new HashSet<>();
UserRole userRole = new UserRole();
userRole.setUser(user);
userRole.setRole(new Role(RolesEnum.ADMIN));
userRoles.add(userRole);
user.getUserRoles().addAll(userRoles);
user.setAccountNonLocked(true);
user.setEnabled(true);
user.setAccountNonExpired(true);
user.setCredentialsNonExpired(true);
user = userRepository.save(user);
...
...
At this point user is added successfully along with the roles in database
User is also able to successfully log-in but the problem is after logging, authentication object has an empty list of roles
Below is the code which is failing
public class SecurityConfig extends WebSecurityConfigurerAdapter {
......
......
private AuthenticationSuccessHandler loginSuccessHandler() {
return (request, response, **authentication**) -> {
Collection<? extends GrantedAuthority> authorities
= authentication.getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
isAdmin = true;
break;
} else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
isBasic = true;
break;
}
}
if (isAdmin) { return "/admin/"; } else if (isBasic) { return
"/profile.html"; } else { throw new IllegalStateException(); }
response.sendRedirect("/");
};
}
......
......
When i inspect authentication object using eclipse the roles are not getting fetched from database
Here is the code for fetching user#Override
public User findByUserName(String username) {
return userRepository.findByUsername(username);
}
Do I need to add some additional logic to fetch roles along with user or Spring handles it behind the scene? Please let me know what I am doing wrong here... Thanks

Spring JpaRepository using EntityGraph returns null instead of Optional

Calling this method:
#EntityGraph(attributePaths = "permissionGroups")
Optional<User> findOneWithPermissionGroupsByLogin(String login);
With non-exsisting user login returns null instead of Optional.of(null).
I would like to figure out what should I add in order to get an Optional resault?
more complete code:
Repository
public interface UserRepository extends JpaRepository<User, Long>
{
Optional<User> findOneByLogin(String login);
#EntityGraph(attributePaths = "permissionGroups")
Optional<User> findOneWithPermissionGroupsByLogin(String login);
}
User Entity
this is relevant user entity code
#Entity
#Table(name = "jhi_user")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class User extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#NotNull
#Pattern(regexp = Constants.LOGIN_REGEX)
#Size(min = 1, max = 50)
#Column(length = 50, unique = true, nullable = false)
private String login;
#JsonIgnore
#ManyToMany
#JoinTable(
name = "jhi_user_authority",
joinColumns = {#JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn(name = "authority_name", referencedColumnName = "name")})
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#BatchSize(size = 20)
private Set<Authority> authorities = new HashSet<>();
#ManyToMany
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#JoinTable(name = "euser_permission_group",
joinColumns = #JoinColumn(name="eusers_id", referencedColumnName="id"),
inverseJoinColumns = #JoinColumn(name="permission_groups_id", referencedColumnName="id"))
private Set<PermissionGroup> permissionGroups = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLogin() {
return login;
}
//Lowercase the login before saving it in database
public void setLogin(String login) {
this.login = login.toLowerCase(Locale.ENGLISH);
}
public Set<Authority> getAuthorities() {
return authorities;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
User user = (User) o;
return login.equals(user.login);
}
#Override
public int hashCode() {
return login.hashCode();
}

Resources