Issue
While save data in database got exception Cannot handle managed/back reference 'defaultReference': back reference type not compatible with managed type
. I got exception while persist data. I think problem is in @JsonManagedReference
or @JsonBackReference
annotation but can't findout the problem.
Here down is code:
Entity
@Entity
@Table(name = "user_master")
public class Users {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer user_id;
private String name;
@JsonManagedReference
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "users_roles", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = {
@JoinColumn(name = "role_id") })
private List<Roles> roles;
// constructor and getter/setter
}
@Entity
@Table(name = "role_master")
public class Roles {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer role_id;
private String name;
@JsonBackReference
@ManyToMany(cascade = CascadeType.ALL, mappedBy = "roles")
private List<Users> users;
// constructor and getter/setter
}
Service
@Override
public List<Users> addUserRole(List<Users> users) {
for(Users user: users)
{
for(Roles role: user.getRoles())
{
role.getUsers().add(user);
}
}
return userRepo.saveAll(users);
}
Controller
@RequestMapping(value = "/adduserrole", method = RequestMethod.POST)
public ResponseEntity<List<Users>> addUserRole(@RequestBody List<Users> users)
{
pojoService.addUserRole(users);
return ResponseEntity.ok(users);
}
Postman
[
{
"name": "Jack",
"roles": [
{
"name": "Engineer"
},
{
"name": "Doctor"
},
{
"name": "Charter Accountant"
}
]
}
]
Exception
"message": "Cannot invoke \"java.util.List.add(Object)\" because the return value of \"com.rest.RestApiPojo.Entity.Roles.getUsers()\" is null",
Solution
@JsonManagedReference
together with @JsonBackReference
are supposed to be used in bidirectional relationships of OneToMany
in one side and ManyToOne
on the other side, or when both sides are of type OneToOne
.
If you inspect closely the JsonBackReference Doc you will understand this
Value type of the property must be a bean: it can not be a Collection, Map, Array or enumeration. Linkage is handled such that the property annotated with this annotation is not serialized; and during deserialization, its value is set to instance that has the "managed" (forward) link.
In your case you have bidirectional ManyToMany
which means that in both sides there is a reference to a collection. So there is not a single compatible property on the side that you have @JsonBackReference
.
There are 2 solutions in your problem with ManyToMany
relationship
- Remove both
@JsonManagedReference
and@JsonBackReference
. Pick a side where you want the collection to be serialized and deserialized. Go to the other side where you don't want the other collection to be serialized and deserialized and use the annotation@JsonIgnore
. - Use custom Dtos which do not have circular dependencies and let your controller use those Dtos instead of plain entities.
Also you have another problem as well
Your controller
@RequestMapping(value = "/adduserrole", method = RequestMethod.POST)
public ResponseEntity<List<Users>> addUserRole(@RequestBody List<Users> users)
{
pojoService.addUserRole(users);
return ResponseEntity.ok(users);
}
expects as input a List of users. Not a single user. So when you want to send a single user your JSON should be
[
{
"name": "Jack",
"roles": [
{
"name": "Engineer"
},
{
"name": "Doctor"
},
{
"name": "Charter Accountant"
}
]
}
]
Answered By - Panagiotis Bougioukos
Answer Checked By - Marie Seifert (JavaFixing Admin)