JSON: Troubleshooting circular dependency errors!

If you’re using Object Relational Mapping frameworks like Hibernate, and are using the bi-directional mappings then you can be sure of getting the following errors if you try to generate JSON of the entities involved.

1. If you’re using Jackson


com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)

2. If you’re using Google’s Gson


java.lang.IllegalStateException: circular reference error

Let’s take a case of two entities Actor, and Movie having a bi-directional relationship and using them we’ll see how to get over the above exceptions when we try to generate JSON.

This solution uses Jackson for generating JSON.

So if you’re using Google’s Gson you’ll have to write an exclusion strategy yourself, and more importantly the rest of the post is useless for you, unless you’re willing to switch to Jackson like I did with such great finesse! 😉

If yes, then you can download Jackson’s libraries and continue reading the post further, rest assured that it’ll be of immense help to you! 🙂

Now, these entities will have a many-to-many relationship amongst them. As one Actor can act in many Movies and one Movie can have many Actors (as it so often happens, and by the way due apologies for being trite and rhetoric!).

Actor.java

@Entity
@Table(name="Actor")
public class Actor implements Serializable {
  . . .
       /* This is the exception-saving-annotation */
       @JsonManagedReference
       @ManyToMany
       private List<Movie> movies;
  . . .
}

Movie.java

@Entity
@Table(name="Movie")
public class Movie implements Serializable {
 . . .
      /* This is the exception-saving-annotation */
      @JsonBackReference
      @ManyToMany(mappedBy="movies")
      private List<Actor> actors;
 . . .
}

So all we did was adding two annotations to the fields having a relationship.

  1. @JsonManagedReference: This annotation should be put on the owner of the relationship, or as you may deem fit.
  2. @JsonBackReference: This annotation should be used on the other end of the relationship.

Now, having done that it’s extremely easy to generate the JSON.

//com.fasterxml.jackson.databind.ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
//The input argument of the writeValueAsString() function can be a bean, array, list, map or a set.
String actorsAsJson = objectMapper.writeValueAsString(actorsList);
//actorsList is a variable of type List<Actor>
//Voila! You're done!

That’s all for the circular dependency errors.

~ Entity Class Code Snippets by Amit 

~Jackson JSON processor

8 thoughts on “JSON: Troubleshooting circular dependency errors!”

  1. I cannot imagine how your code works — I have a similar situation and an exception is thrown saying that back reference cannot be a list. Actually the javadoc of JsonBackreference class also clearly states this

    ” * Annotation used to indicate that associated property is part of
    * two-way linkage between fields; and that its role is “child” (or “back”) link.
    * Value type of the property must be a bean: it can not be a Collection, Map,
    * Array or enumeration.”

    Like

  2. Hi, i have a problem. I have implemented that into my entities and everything works fine, except for one entity. It has a @ManyToMany relation unidireccional(not bidiretional) to the same entity and I always get circular error. can you help me?

    Like

    1. Hi, I couldn’t get your problem. You are saying you have an entity and that entity has in turn reference to the same entity. But why would you have @ManytoMany on the same entity? Isn’t that used to define the relation with some other entity?

      Like

      1. Hi, I have a entity call “User” and a ‘user’ has many friends(other users). so I put a @ManyToMany relation, I wrote to Set’s into de entity “User” to make a bidireccional relation and that resolve the cycle problem, but when I try to get a ‘user’ whitout his friends i always obtain the ‘user’ and all his relations “fiends, and other things”.
        is there a way that if i call just the ‘user’ just get the ‘user’? and not all the relations?

        I have my relations defiend with Lazy scope.

        Like

      2. I still think you don’t need a @ManyToMany relation there. Can you please post your entity class code snippet please?

        As you would do that in a case of self referencing as in Employee-Manager.

        public class Employee {

        @ManyToOne
        private Employee manager;

        @OneToMany(mappedBy=”manger”)
        private Set reportees;


        }

        See here you have two kinds of relations one Manager and the other his Reportees. But in your case i.e. User has many friends.

        So just having a set friends would suffice I guess.

        Like

Leave a comment