I would like to know the difference between @JsonManagedReference
and @JsonBackReference
in Jackson?
As write Rajat Verma, his solution works perfectly. Thanks man you saved me lot of time and anger :-)
The important Part:
You need define fields asList
, I had that asSet
before and this solution NOT WORKING (appears as infinite loop)!
I add my solution:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)
public class Agent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToMany(mappedBy = "subscribers")
@ApiModelProperty(dataType = "List", example = "[1,2,3]") // for Swagger
@JsonIdentityReference(alwaysAsId = true) // show only id of Topic
private final List<Topic> subscribeTopics = new ArrayList<>()
}
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)
public class Topic {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinTable(name = "topic_agent",
joinColumns = @JoinColumn(name = "fk_topic_id"),
inverseJoinColumns = @JoinColumn(name = "fk_agent_id"))
@ApiModelProperty(dataType = "List", example = "[1,2,3]")
@JsonIdentityReference(alwaysAsId = true)
private final List<Agent> subscribers = new ArrayList<>();
}
@JsonManagedReference is the forward part of reference – the one that gets serialized normally. @JsonBackReference is the back part of reference – it will be omitted from serialization.
So they really depend on the direction of your relationship
public class User {
public int id;
public String name;
@JsonBackReference
public List<Item> userItems;
}
public class Item {
public int id;
public String itemName;
@JsonManagedReference
public User owner;
}
Use case: You have a one-many or many-many relationships in your entities/tables and not using the above would lead to errors like
Infinite Recursion and hence stackoverflow - > Could not write content: Infinite recursion (StackOverflowError)
The above errors occurs because Jackson (or someother similiar) tries to serialise both ends of the relationship and ends up in a recursion.
@JsonIgnore performs similiar functions but the above mentioned annotations are preferable.
I prefer
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)
where property is the name of primary key field and scope is Type of it
@JsonManagedReference
and @JsonBackReference
are designed to handle this two-way linkage between fields, one for Parent role, the other for Child role.
For avoiding the problem, linkage is handled such that the property annotated with @JsonManagedReference annotation is handled normally (serialized normally, no special handling for deserialization) and the property annotated with @JsonBackReference annotation is not serialized; and during deserialization, its value is set to instance that has the "managed" (forward) link.