Spring MVC - JSON infinite recursion
Asked Answered
A

12

24

I have bi-directional relationship like this...

Person.java

 public class Person{

    @JsonIgnore
    @OneToMany(targetEntity=PersonOrganization.class, cascade=CascadeType.ALL,
        fetch=FetchType.EAGER, mappedBy="person")
    private Set<PeopleOrg> organization;
    .....
 }

PersonOrganization.java

  public class PersonOrganization{

    @JsonIgnore
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="PERSONID", nullable=false)
private Person person;
  }

Even with @JsonIgnore annotation I am getting infinite recursion error when trying to retrieve Person records. I have tried new annotations in 1.6 version. @JsonBackReference and @JsonManagedReference. Even then I am getting infinite recursion..

With @JsonBackReference("person-organization") on Person and @JsonManagedReference("person-organization") on PersonOrganization

org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.entity.Person["organization"]->org.hibernate.collection.PersistentSet[0]->com.entity.PersonOrganization["person"]->com.entity.Person["organization"]->org.hibernate.collection.PersistentSet[0]...

Even If I interchange the annotations, I am still getting this exception.. Please let me know if there is something wrong with the mappings or the way I am using JSON annotations. Thanks

Admeasure answered 27/1, 2012 at 18:7 Comment(0)
S
40

I've run into this before. But after moving @JsonIgnore from private field to getter of the field, infinite recursion is gone. So my wild guess is that @JsonIgnore might no work on private field. However, javadoc or tutorial of Jackson Java JSON-processor do not mention about this, so I cannot be 100% sure. Just for your information.

Stace answered 28/1, 2012 at 10:55 Comment(2)
I could give you a big fat kiss right now. This fixed my issue. In my case, the field was protected.Tarragona
It's not enough, I still have the problem.Zenda
E
10

The following link says you should annotate the method used by JSON tool to traverse the object graph, to instruct the it to ignore the traversal.

http://jackson.codehaus.org/1.0.1/javadoc/org/codehaus/jackson/annotate/JsonIgnore.html

In my case I have two objects related like this Product <-> ProductImage. So JSON parser went into an infinite loop with out @JsonIgnore annotation on the following to get methods

@JsonIgnore
public Product getImageOfProduct() {
    return imageOfProduct;
}

in ProductImage and

@JsonIgnore
public Set<ProductImage> getProductImages() {
    return productImages;
}

in Product.

With the annotation, things are working fine.

Entomb answered 10/5, 2012 at 6:42 Comment(1)
Annotating the getter instead of the field worked for me. WAS 8.5 JEE 6.Turban
G
5

I know this question isn't specifically about Spring Data REST, but I ran into this exception in the context of Spring Data REST, and wanted to share what the problem was. I had a bidirectional relationship involving an entity with no repository. Creating the repository made the loop disappear.

Gellman answered 7/5, 2013 at 17:26 Comment(2)
I have both repositories, but I still have the loopZenda
I have found the solution: we need to use @ JsonManagedReference and @ JsonBackReference on the Projections (NOT in the entitites)Zenda
T
4

Since Jackson 1.6 you can use two annotations to solve the infinite recursion problem without ignoring the getters/setters during serialization: @JsonManagedReference and @JsonBackReference.

For more details refer https://mcmap.net/q/73385/-infinite-recursion-with-jackson-json-and-hibernate-jpa-issue

Turmel answered 6/4, 2014 at 3:41 Comment(0)
I
3

Apparently since Jackson 1.6 you can use @JsonManagedReference and @JsonBackReference to effectively solve the infinite recursion problem.

I won't go into the details but this changing you classes to the below format should solve the problem.

 public class Person{

    @OneToMany(targetEntity=PersonOrganization.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="person")
    @Column(nullable = true)
    @JsonManagedReference
    private Set<PeopleOrg> organization;
    .....
 }

public class PersonOrganization{

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name="PERSONID")
    @JsonBackReference
    private Person person;
  }

Basically Jackson converts Set<PeopleOrg> organization, the forward part of the reference a to json-like format using the marshalling process, it then looks for Person person, the back part of the reference and does not serialize it.

Credits - Kurt Bourbaki & More info - http://keenformatics.blogspot.co.ke/2013/08/how-to-solve-json-infinite-recursion.html

Impassioned answered 5/7, 2017 at 8:58 Comment(0)
R
1

If A has B & B has A.

This is one to one relationship, but forming a circular relation.

In any of the class, use JustIgnore annotation.

class A
{    
B b;    
}

class B
{    
@JsonIgnore
A a;
}

This applies for other relationships also like one to many.

Rumpus answered 22/9, 2017 at 6:29 Comment(0)
J
0

This might be little old but you can add @JsonIgnore at class level with all properties it should ignore. e.g

@JsonIgnore("productImaes","...")
public class Product{ ...
}
Jakob answered 6/1, 2016 at 18:53 Comment(0)
F
0

Sometimes the member field may have inner reference to the same class type of itself, which could cause infinite recursion when toJson.

E.g.: you have a member field Klass a, while the class definition of that Klass is as below.

class Klass {
    Klass mySibling;

    public toString() {
        return "something" + mySibling.whateverMethod;
    }
}

Solution: refactor the member field, eliminate the inner reference.

Foumart answered 1/3, 2016 at 22:52 Comment(0)
U
0

This exception is because, your constructor field are not proper, please check your constructors properties once again in your classes, and check mapping give properly or not,

Keep the two Constructors, first is zero construction and second constructor is with fields and both should be contain the super

Ulotrichous answered 13/7, 2017 at 20:20 Comment(0)
A
0

for me, i have tried @JsonIgnore, @JsonManagedReference/@JsonBackReference but nothing worked, till i read this Exception thrown ["hibernateLazyInitializer"] solution 1 and this Exception thrown ["hibernateLazyInitializer"] solution 2

solution 1 is to change from fetch.LAZY to fetch.EAGER, and solution 2 is using @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}), and of course use @JsonIgnore in both solutions

Allanadale answered 2/10, 2019 at 10:58 Comment(0)
E
0

In my case, I have imported wrong @JsonIgnore annotation like net.minidev.json.annotate.JsonIgnore instead of com.fasterxml.jackson.annotation.JsonIgnore. Changing this import fixed infinite recursion issue for me.

Exhaustion answered 26/2 at 18:18 Comment(0)
M
-2

Jackson works on Reflection by calling getters. I too had such a situation where I had a getter of the same Object inside its class. Jackson went into infinite recursion eating up stack by repeatedly calling its own getter. Removed getter, then it got fixed.

My Advice : If you want to use jackson for conversion of an object, never keep getters which references the same object, like in case of singletons.

Musicianship answered 15/6, 2016 at 6:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.