'Spring JPA bi-directional cannot evaluate toString

I have resolved JSON recursive loop with @JsonIdentityInfothrough to Baeldung's blog1 (Thanks)

But now, another error occurs :

Method threw 'java.lang.StackOverflowError' exception. Cannot evaluate com.mezoo.tdc.model.Payment.toString()

Here my Registration object :

    @Entity
    @Table(name="Registration")
    @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "uuid")
    public class Registration implements Serializable {

       /*some private variables..*/

      // Bidirectional relationship
      @OneToMany(mappedBy="registration", cascade = {CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE}, fetch = FetchType.LAZY)
      private List<Payment> payment;

                @Override
      public String toString() {
         return MoreObjects.toStringHelper(this)
            .add("payment", payment)
            .toString();
         }
    }

Now, Payment object :

    @Entity
    @Table(name="Payment")
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "uuid")
    public class Payment implements Serializable {
       @ManyToOne
       @JoinColumn(name = "registration")
       private Registration registration;

       @Override
       public String toString() {
       return MoreObjects.toStringHelper(this)
            .add("registration", registration)
            .toString();
       }
    }

This is, what I see in debugger :

debug screenshot

Please, what is wrong and why ?



Solution 1:[1]

Remove toString method.

In case you are using Lombok:

Check you Entity/DAO class you might be using @Data annotation from lombok which by default includes getter and setters. Change it to @Getters and @Setter in case you need those and remove @Data annotation.

Solution 2:[2]

in your Registration.toString() you are calling a Payment.toString() and on your Payment.toString() you are calling Registration.toString()

You have created a loop in toString

  @Override
  public String toString() {
     return MoreObjects.toStringHelper(this)
        .add("payment", payment) //<----------- REMOVE THIS
        .toString();
  }

or

   @Override
   public String toString() {
   return MoreObjects.toStringHelper(this)
        .add("registration", registration) //<----------- REMOVE THIS
        .toString();
   }

Or better... remove both

Solution 3:[3]

If you are using lombok then you can exclude mapping from toString() as follows,

@Entity
    @Table(name="Registration")
    @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "uuid")
@ToString(exclude = {"payment"})
    public class Registration implements Serializable {
..
..
..Your code
}

Same for payment entity.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rishabh Agarwal
Solution 2 ValerioMC
Solution 3 Rahul Dudhane