Saturday, 22 April 2017

org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion

When retrieving an object via remote http request. Getting following error:

Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion

The JSON response becomes incredible huge. This happens when two entities have a bi-directional relationship. The owning side needs to keep foreign key pointing to its associated entity. This may result in recursive references. On this case, it needs to close its JSON serialization.

Using @JsonIgnoreProperties, it works at the class level. Note: It is different from @JsonIgnore, for it works at the field and property level.



The following example is the solution for the exception above.  At the owning side: 

/**
 *
 * @author YNZ
 */
@Entity
@Table(name = "YARD")
@JsonIgnoreProperties(value = {"lister", "searcher"}, allowSetters = true)
public class Yard implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "YARD_ID_PK")
    @JsonIgnore
    protected long id;

    @Column(name = "NAME")
    protected String name;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "ADDRESS_ID_FK", referencedColumnName = "ADDRESS_ID_PK")
    protected Address address; //owning side keeping FK

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "Lister_ID_FK", referencedColumnName = "USER_PK")
    protected Lister lister;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "SEARCHER_ID_FK", referencedColumnName = "USER_PK")
    protected Searcher searcher;

At inverse side:
/**
 *
 * @author YNZ
 */
@Entity
@Table(name = "LISTER")
//@JsonIgnoreProperties(value = "listedYard", allowSetters = true)
public class Lister extends User {

    @OneToOne(mappedBy = "lister", cascade = CascadeType.ALL, targetEntity = Yard.class) //inverse side 
    private Yard listedYard;

    public Lister() {
    }

    public Yard getListedYard() {
        return listedYard;
    }

    public void setListedYard(Yard listedYard) {
        this.listedYard = listedYard;
    }

}


No comments:

Can Jackson Deserialize Java Time ZonedDateTime

Yes, but must include JSR310. Thus ZonedDateTime can be deserialized directly from JSON response to POJO field. <dependency> <g...