Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could not write JSON: Infinite recursion (StackOverflowError); nested exception spring boot

Tags:

This is my District Controller, when I try to fetch data after saving I get the error, even when I try get object form getDistrict(Long id) the same strikes please suggest some way, am very new at spring environment:

    package com.gad.services;

    import java.util.List;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;

    import com.gad.repositories.DistrictMasterRepositories;
    import com.gad.rmodels.Districtmaster;
    import com.gad.rmodels.Statemaster;

    @Service
    public class DistricMasterServices {

        @Autowired
        DistrictMasterRepositories districtMasterRepositories;
        @Autowired
        StateMasterServices stateMasterServices;
        List<Districtmaster> districtmaster;

        public Iterable<Districtmaster> savenewdistrict(Long id,Districtmaster districtmaster_rec){
             System.out.println(id);
             Statemaster statemaster=null;
             statemaster = stateMasterServices.getStateById(id);
             System.out.println("savenewdistrict");



                districtmaster_rec.setStatemaster(statemaster);
                districtMasterRepositories.save(districtmaster_rec);
                    Iterable<Districtmaster>districtmaster2 = districtMasterRepositories.findAll();
                    return  districtmaster2;


        }


        public Districtmaster  getDistrict(Long id){
            Districtmaster districtmaster =  districtMasterRepositories.findOne(id);
            return districtmaster;

        }
    }

The model class for state:

 package com.gad.rmodels;
    import static javax.persistence.GenerationType.SEQUENCE;
    import java.util.HashSet;
    import java.util.Set;
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.SequenceGenerator;
    import javax.persistence.Table;

    /**
     * Statemaster generated by hbm2java
     */
    @Entity
    @Table(name="statemaster"
        ,schema="aop_gad_v1"
    )
    public class Statemaster  implements java.io.Serializable {


         private long id;
         private String stateName;
         private Set<Districtmaster> districtmasters = new HashSet<Districtmaster>(0);

        public Statemaster() {
        }


        public Statemaster(long id) {
            this.id = id;
        }
        public Statemaster(long id, String stateName, Set<Districtmaster> districtmasters) {
           this.id = id;
           this.stateName = stateName;
           this.districtmasters = districtmasters;
        }



        @SequenceGenerator(name="generator_statemasterid", sequenceName="aop_gad_v1.gad_statemaster_seq")
        @Id 
        @GeneratedValue(strategy=SEQUENCE, generator="generator_statemasterid")
        @Column(name="id", unique=true, nullable=false)
        public long getId() {
            return this.id;
        }

        public void setId(long id) {
            this.id = id;
        }

        @Column(name="state_name", length=20)
        public String getStateName() {
            return this.stateName;
        }

        public void setStateName(String stateName) {
            this.stateName = stateName;
        }

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
        public Set<Districtmaster> getDistrictmasters() {
            return this.districtmasters;
        }

        public void setDistrictmasters(Set<Districtmaster> districtmasters) {
            this.districtmasters = districtmasters;
        }




    }

Distric model:

package com.gad.rmodels;


import static javax.persistence.GenerationType.SEQUENCE;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

/**
 * Districtmaster generated by hbm2java
 */
@SuppressWarnings("serial")
@Entity
@Table(name="districtmaster",schema="aop_gad_v1")
public class Districtmaster  implements java.io.Serializable {


     private long id;
     private Statemaster statemaster;
     private String districtName;
     private Set<GadGuestHouseMaster> gadGuestHouseMasters = new HashSet<GadGuestHouseMaster>(0);

    public Districtmaster() {
    }


    public Districtmaster(long id) {
        this.id = id;
    }
    public Districtmaster(long id, Statemaster statemaster, String districtName, Set<GadGuestHouseMaster> gadGuestHouseMasters) {
       this.id = id;
       this.statemaster = statemaster;
       this.districtName = districtName;
       this.gadGuestHouseMasters = gadGuestHouseMasters;
    }


     @SequenceGenerator(name="generator_districtmasterid", sequenceName="aop_gad_v1.gad_districtmasterid_seq")
     @Id 
     @GeneratedValue(strategy=SEQUENCE, generator="generator_districtmasterid")
     @Column(name="id", unique=true, nullable=false)
    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }
@ManyToOne(fetch=FetchType.LAZY)

    @JoinColumn(name="district_of_state")
    public Statemaster getStatemaster() {
        return this.statemaster;
    }

    public void setStatemaster(Statemaster statemaster) {
        this.statemaster = statemaster;
    }

    @Column(name="district_name", length=20)
    public String getDistrictName() {
        return this.districtName;
    }

    public void setDistrictName(String districtName) {
        this.districtName = districtName;
    }
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="districtmaster")
    public Set<GadGuestHouseMaster> getGadGuestHouseMasters() {
        return this.gadGuestHouseMasters;
    }

    public void setGadGuestHouseMasters(Set<GadGuestHouseMaster> gadGuestHouseMasters) {
        this.gadGuestHouseMasters = gadGuestHouseMasters;
    }




}

The Error I get:

[{"timestamp":1512641978311,"status":200,"error":"OK","exception":"org.springframework.http.converter.HttpMessageNotWritableException","message":"Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.gad.rmodels.Statemaster[\"districtmasters\"]->org.hibernate.collection.internal.PersistentSet[0]-

like image 912
Bikash Dhal Avatar asked Dec 07 '17 10:12

Bikash Dhal


2 Answers

You are facing this issue because the Statemaster model contains the object of Districtmaster model, which itself contains the object of Statemaster model. This causes an infinite json recursion.

You can solve this issue by 3 methods.

1 - Create a DTO and include only the fields that you want to display in the response.

2 - You can use the @JsonManagedReference and @JsonBackReference annotations.

E.g. Add the @JsonManagedReference annotation to the Statemaster model.

@JsonManagedReference
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
    return this.districtmasters;
}

Add the @JsonBackReference annotation to the Districtmaster model.

@JsonBackReference
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="district_of_state")
public Statemaster getStatemaster() {
    return this.statemaster;
}

3 - You can use the @JsonIgnore annotation on the getter or setter method.

@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
    return this.districtmasters;
}

However, this approach will omit the set of Districtmaster from the response.

like image 139
Shoeb Shaikh Avatar answered Oct 22 '22 02:10

Shoeb Shaikh


I've been struggling with the same problem for days, I tried @JsonIgnore, @JsonManagedReference and @JsonBackReference annotation, and even @JsonIdentityInfo annotation and none of them have worked.

If you (the future readers ) are in the same situation, the solution is easier than you expected, simply put @JsonIgnore or @JsonManagedReference / @JsonBackReference on the attribute's getter and not on the attribute itself. And that will do.

Here's a simple example how to do so :

Say we have two classes, Order and Product, and OneToMany relation between them.

Order class

public class Order{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private String id_order;
  private double price;
  @OneToMany(mappedBy = "order")
  @LazyCollection(LazyCollectionOption.FALSE)
  private List<Product> products
  //constructor, getters & setter 
}

Product Class:

public class Product{
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private String id_product;
   private String name;
   @ManyToOne
   @JoinColumn(name = "id_order")
   private Order order;
   //consturctor, getters & setters
 }

So in order to use @JsonManagedReference and @JsonBackReference, just add them to the getters as the following :

public class Order{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private String id_order;
  private double price;
  @OneToMany(mappedBy = "order")
  @LazyCollection(LazyCollectionOption.FALSE)
  private List<Product> products
  //constructor, getters & setter 
  @JsonManagedReference
  public List<Product> getProducts(){
    return products;
}

Product class:

public class Product{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private String id_product;
  private String name;
  @ManyToOne
  @JoinColumn(name = "id_order")
  private Order order;
  //consturctor, getters & setters
  @JsonBackReference
  public Order getOrder(){
    return order;
  }
 }
like image 45
Faouzi Avatar answered Oct 22 '22 03:10

Faouzi