Wednesday, June 13, 2012

JsonMappingException when serializing POJO reverse engineered using Hibernate, to JSON

We were working recently on a Java project with Hibernate as the ORM. We created the database and reverse engineered the entities to POJO using Hibernate (See how).

I am putting up a simple ER diagram to demonstrate the issue.

Each Item has a list of item details which are name/value pairs.



And we needed to serialize this object to JSON so we used Jackson. And when trying serialize we were confronted with an exception.

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ItemDetail.item, no session or session was closed

Closely looking at the generated ItemDetail class I found that there was a Item defined there. 

   @ManyToOne(cascade={}, fetch=FetchType.LAZY)  
   @JoinColumn(name="item_id", unique=false, nullable=false, insertable=true, updatable=true)  
   public Item getItem() {  
     return this.item;  
   }  
   public void setItem(Item item) {  
     this.item = item;  
   }  

The first (stupid) thing I tried was to change to FetchType from LAZY to EAGER. which I thought would solve the problem.  However that resulted in a StackoverflowException because the serializer kept recursing and it would never reach the end.

 Exception in thread "main" org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: ItemDetail["item"])

The problem here is that Hibernate provides us a way to navigate back using the foreign key relationship where in this instance to get the parent Item that belongs to each ItemDetail. But Jackson did not like it!

The solution was VERY simple.

Simply inform the serializer to ignore such parent relationships. You can inform Jackson to leave it aside using @JsonIgnore (See all the annotations here).

   @ManyToOne(cascade={}, fetch=FetchType.LAZY)   
   @JoinColumn(name="item_id", unique=false, nullable=false, insertable=true, updatable=true)   
   @JsonIgnore  
   public Item getItem() {   
    return this.item;   
   }   

And Jackson did not try to serialize it and it worked just as expected!

11 comments:

  1. This saved my day... thx lot!
    -Lahiru

    ReplyDelete
  2. Thnk u very much!!!

    ReplyDelete
  3. It's a good solution, but if I need to keep "items" in my serializable object?

    ReplyDelete
    Replies
    1. Right !! I need to keep "items"... any idea ?

      Delete
  4. Great solution . It saves a ton of time to find out solution

    ReplyDelete
  5. I added @JsonIgnore and it threw StackOverflowError

    ReplyDelete
  6. Thank you!!!!!!!.saved my day :) :)

    ReplyDelete
  7. Did you know there is a 12 word sentence you can speak to your man... that will trigger deep feelings of love and instinctual appeal to you buried inside his heart?

    Because hidden in these 12 words is a "secret signal" that fuels a man's instinct to love, please and protect you with all his heart...

    12 Words That Trigger A Man's Desire Response

    This instinct is so hardwired into a man's mind that it will drive him to try harder than ever before to to be the best lover he can be.

    In fact, triggering this powerful instinct is so important to getting the best possible relationship with your man that the second you send your man one of the "Secret Signals"...

    ...You'll instantly notice him open his heart and soul for you in a way he never experienced before and he will see you as the only woman in the universe who has ever truly appealed to him.

    ReplyDelete