title: Hibernate: Infinite recursion, how to solve it?
body: <p>I've very annoying problem with infinite recursion. My app is being build as Spring Rest API, and I use Lombok to generate constructors and getters and setter. I've few models.</p>
  
  <p>AppUser - probably the biggest one.</p>
  
  <pre><code>@NoArgsConstructor
  @AllArgsConstructor
  @Data
  @Entity
  public class AppUser {
  
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
      private String login;
      private String name;
      private String surname;
      @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
      private String password;
  
      public AppUser(String login, String password, UserRole userRole) {
          this.login = login;
          this.password = password;
          this.userRoleSet = new HashSet&lt;&gt;();
          this.userRoleSet.add(userRole);
      }
  
      public AppUser(String login, String name, String surname, String password) {
          this.login = login;
          this.name = name;
          this.surname = surname;
          this.password = password;
      }
  
      @OneToMany(mappedBy = "appUser",fetch = FetchType.EAGER)
      private Set&lt;UserRole&gt; userRoleSet;
  
      @OneToMany(mappedBy = "createdBy")
      private List&lt;Incident&gt; createdIncidentsList;
  
      @OneToMany(mappedBy = "assignedTo")
      private List&lt;Incident&gt; assignedToIncidentsList;
  
      @OneToMany(mappedBy = "postedBy")
      private List&lt;Comment&gt; commentList;
  
      @OneToMany(mappedBy = "appUser")
      private List&lt;IncidentChange&gt; incidentChangeList;
  
  }
  </code></pre>
  
  <p>Incident</p>
  
  <pre><code>@Data
  @Entity
  public class Incident {
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
      private String title;
      private String description;
      private LocalDateTime creationDate;
      private IncidentStatus status;
  
      @OneToMany(mappedBy = "incident", cascade = CascadeType.ALL)
      private List&lt;Comment&gt; commentList;
      @ManyToOne
      private AppUser createdBy;
      @ManyToOne
      private AppUser assignedTo;
      @OneToOne(cascade = CascadeType.ALL)
      private ChangeLog changeLog;
  
      public Incident(String title, String description) {
          this.title = title;
          this.description = description;
          this.creationDate = LocalDateTime.now();
          this.status = IncidentStatus.NEW;
          this.commentList = new ArrayList&lt;&gt;();
          this.changeLog = new ChangeLog();
      }
      public Incident(){
  
      }
      public Incident(String title, String description, LocalDateTime creationDate, IncidentStatus status, List&lt;Comment&gt; commentList, AppUser assignedTo, AppUser createdBy, ChangeLog changeLog) {
          this.title = title;
          this.description = description;
          this.creationDate = creationDate;
          this.status = status;
          this.commentList = commentList;
          this.changeLog = changeLog;
      }
  
  }
  </code></pre>
  
  <p>Comment</p>
  
  <pre><code>@Data
  @NoArgsConstructor
  @Entity
  public class Comment {
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
      private String description;
      private LocalDateTime creationDate;
  
      @ManyToOne
      private AppUser postedBy;
      @ManyToOne
      private Incident incident;
  
  }
  </code></pre>
  
  <p>ChangeLog</p>
  
  <pre><code>@Data
  @Entity
  public class ChangeLog {
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
      @OneToOne
      private Incident incident;
      @OneToMany(mappedBy = "changeLog")
      private List&lt;IncidentChange&gt; incidentChangeList;
  
      public ChangeLog(){
          this.incidentChangeList = new ArrayList&lt;&gt;();
      }
  
      public ChangeLog(Incident incident, List&lt;IncidentChange&gt; incidentChangeList) {
          this.incident = incident;
          this.incidentChangeList = incidentChangeList;
      }
  
  }
  </code></pre>
  
  <p>IncidentChange</p>
  
  <pre><code>@Data
  @NoArgsConstructor
  @Entity
  public class IncidentChange {
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
      private String description;
      private LocalDateTime changeDate;
  
      @ManyToOne
      private ChangeLog changeLog;
      @ManyToOne
      private AppUser appUser;
  }
  </code></pre>
  
  <p>And it works like this in short:</p>
  
  <p>AppUser has<br> OneToMany relation to Incident, Comment and IncidentChange.</p>
  
  <p>Incident has<br> ManyToOne relation to AppUser (TWICE that's important),<br>
               OneToMany to Comments,<br>
               OneToOne to ChangeLog</p>
  
  <p>Comment has <br> ManyToOne relation to AppUser,<br>
              ManyToOne to incident<br></p>
  
  <p>ChangeLog has <br> OneToOne relation to Incident,<br>
                OneToMany to IncidentChange</p>
  
  <p>IncidentChange  has <br> ManyToOne relation to ChangeLog, <br>
                  ManyToOne to AppUser</p>
  
  <p>I know that AppUser is in Incident, and is in Comment that is nested in Incident, same situation with IncidentChange, but it's nested even deeper. </p>
  
  <p>Here is code for people that would like to check how AppUser and Incident is created <a href="https://bitbucket.org/StabloPL/backendsimpleticketsystem/src/76e6bd107e68c82614fbc040b95f041fd7f51d28/src/main/java/com/djagiellowicz/ticketsystem/backendsimpleticketsystem/model/?at=master" rel="nofollow noreferrer">https://bitbucket.org/StabloPL/backendsimpleticketsystem/src/76e6bd107e68c82614fbc040b95f041fd7f51d28/src/main/java/com/djagiellowicz/ticketsystem/backendsimpleticketsystem/model/?at=master</a>
  IncidentController, AppUserControler, and IncidentService, AppUserService are things that could interest somebody.</p>
  
  <p>When I create user (Via Postman as JSON) and after that I fetch it, there is no problem everything works. When I create Incident and assign it to specific person, I can't fetch Incident, also I can't fetch this particual user. Other pages, where there are users without created incidents fetch without any issues. The same applies to Incidents without assigned createdBy users. Everything saves to database without any issues.</p>
  
  <p>Here is error thrown by Hibernate/Spring when I try to fetch Incident. Of course a little bit cut.</p>
  
  <pre><code>java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
      at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:472) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
      at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
      at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
  
  
  2018-04-24 11:39:43.731 ERROR 18300 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.djagiellowicz.ticketsystem.backendsimpleticketsystem.model.AppUser["createdIncidentsList"]-&gt;org.hibernate.collection.internal.PersistentBag[0]-&gt;com.djagiellowicz.ticketsystem.backendsimpleticketsystem.model.Incident["createdBy"]-&gt;com.djagiellowicz.ticketsystem.backendsimpleticketsystem.model.AppUser["createdIncidentsList"]-&gt;org.hibernate.collection.internal.PersistentBag[0]-&gt;
  java.lang.StackOverflowError: null
  </code></pre>
  
  <p>How can I solve it? I have to know which Comment has been posted by AppUser, the same applies to Incident and IncidentChange, and I don't want to remove these info from Incident/IncidentChange/Comment</p>