I have been following the tutorial on Spring security with JWT (link), and decided to use Spring Boot Starter Data JDBC version 2.6.6 instead of of JPA and noticed quite strange behaviour. I have a user class:
@Table("CUSTOMER")
public class Customer {
@Id
@Column
private Long id;
@Column
private String email;
@Column
private String password;
@MappedCollection(keyColumn = "ROLE_ID", idColumn = "ROLE_ID")
private Collection<Role> roles = new ArrayList<>();
@MappedCollection(keyColumn = "CART_ITEM_ID",idColumn = "CART_ITEM_ID")
private Map<Long, CartItem> productsInCart = new HashMap<>();
//constructors, getters and setters
and Role class:
@Table("ROLE")
public class Role {
@Id
private Long roleId;
@Column
private String name;
public Role(Long roleId, String name) {
this.roleId = roleId;
this.name = name;
}
///getters and setters
When the application runs, I have this method being executed:
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
@Bean
CommandLineRunner runner(CustomerService customerService){
return args -> {
customerService.saveCustomer(new Customer("1234@example.com", "newpassword", new ArrayList<>(), new HashMap<>()));
customerService.saveCustomer(new Customer("112233@example.com", "password", new ArrayList<>(), new HashMap<>()));
customerService.saveCustomer(new Customer("test@example.com", "passwd", new ArrayList<>(), new HashMap<>()));
customerService.saveRole(new Role( null, "ROLE_ADMIN"));
customerService.saveRole(new Role( null, "ROLE_USER"));
customerService.saveRole(new Role( null, "ROLE_SUPER_ADMIN"));
customerService.addRoleToUser("1234@example.com", "ROLE_USER");
customerService.addRoleToUser("112233@example.com", "ROLE_ADMIN");
};
}
}
Customer Service is an interface containing methods for data manipulation.
Each repository extends CrudRepository
The method saveRole() is simply:
public Role saveRole(Role role) {
return roleRepo.save(role);
}
The method addRoleToUser():
public void addRoleToUser(String email, String roleName) {
Customer customer = customerRepo.findByEmail(email);
Role role = roleRepo.findByName(roleName);
customer.getRoles().add(role);
}
In the code above only addRoleToUser() does operations on the Collection of Roles in Customer class. both saveRole() and addRoleToUser() are implemented in a class with @Service and @Transactional annotations.
However, when I test this with Postman, I get the following response:
[
{
"id": 1,
"email": "1234@example.com",
"password": "$2a$10$bdSBoB3yuLdNkmdDvUazwOrw5BFAZB2iOqPBKi28RaGTZ9Dtkfo76",
"roles": [
{
"roleId": 1,
"name": "ROLE_ADMIN"
}
],
"productsInCart": {}
},
{
"id": 2,
"email": "112233@example.com",
"password": "$2a$10$Qr15M9SGyZ5.D0fVijZeUOrD10nOTeEDT5LkCNlMNMpvocVP2gM/G",
"roles": [
{
"roleId": 2,
"name": "ROLE_USER"
}
],
"productsInCart": {}
},
{
"id": 3,
"email": "test@example.com",
"password": "$2a$10$g2qVrzQHxY1s9rSP.o.XiedbyuuXQ7xB29syo5fu4mf4cxbRWkGji",
"roles": [
{
"roleId": 3,
"name": "ROLE_SUPER_ADMIN"
}
],
"productsInCart": {}
}
]
So it kind of seems that while saving a Role to the database, the Role is added to customer. What could be the reason for that? I tried changing the order of addition of Roles to the database in the runner() method and the JSON I received always reflected the order I chose (If I add "ROLE_USER,_ROLE_ADMIN, ROLE_SUPER_ADMIN user 1 will get ROLE_USER, user 2 gets ROLE_ADMIN and so on...). I tried to assign the Roles using addRoleToUser() method but the changes it makes are not saved in the database. Any tip would be greatly appreciated.