title: Infinite Recursion with Jackson JSON and Hibernate JPA issue
body: <p>When trying to convert a JPA object that has a bi-directional association into JSON, I keep getting</p>
  <pre><code>org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError)
  </code></pre>
  <p>All I found is <a href="http://forum.springsource.org/showthread.php?t=88803" rel="noreferrer">this thread</a> which basically concludes with recommending to avoid bi-directional associations. Does anyone have an idea for  a workaround for this spring bug?</p>
  <p>------ EDIT 2010-07-24 16:26:22 -------</p>
  <p>Codesnippets:</p>
  <p>Business Object 1:</p>
  <pre class="lang-java prettyprint-override"><code>@Entity
  @Table(name = &quot;ta_trainee&quot;, uniqueConstraints = {@UniqueConstraint(columnNames = {&quot;id&quot;})})
  public class Trainee extends BusinessObject {
  
      @Id
      @GeneratedValue(strategy = GenerationType.TABLE)
      @Column(name = &quot;id&quot;, nullable = false)
      private Integer id;
  
      @Column(name = &quot;name&quot;, nullable = true)
      private String name;
  
      @Column(name = &quot;surname&quot;, nullable = true)
      private String surname;
  
      @OneToMany(mappedBy = &quot;trainee&quot;, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
      @Column(nullable = true)
      private Set&lt;BodyStat&gt; bodyStats;
  
      @OneToMany(mappedBy = &quot;trainee&quot;, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
      @Column(nullable = true)
      private Set&lt;Training&gt; trainings;
  
      @OneToMany(mappedBy = &quot;trainee&quot;, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
      @Column(nullable = true)
      private Set&lt;ExerciseType&gt; exerciseTypes;
  
      public Trainee() {
          super();
      }
  
      //... getters/setters ...
  }
  </code></pre>
  <p>Business Object 2:</p>
  <pre class="lang-java prettyprint-override"><code>import javax.persistence.*;
  import java.util.Date;
  
  @Entity
  @Table(name = &quot;ta_bodystat&quot;, uniqueConstraints = {@UniqueConstraint(columnNames = {&quot;id&quot;})})
  public class BodyStat extends BusinessObject {
  
      @Id
      @GeneratedValue(strategy = GenerationType.TABLE)
      @Column(name = &quot;id&quot;, nullable = false)
      private Integer id;
  
      @Column(name = &quot;height&quot;, nullable = true)
      private Float height;
  
      @Column(name = &quot;measuretime&quot;, nullable = false)
      @Temporal(TemporalType.TIMESTAMP)
      private Date measureTime;
  
      @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
      @JoinColumn(name=&quot;trainee_fk&quot;)
      private Trainee trainee;
  }
  </code></pre>
  <p>Controller:</p>
  <pre class="lang-java prettyprint-override"><code>import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Controller;
  import org.springframework.ui.Model;
  import org.springframework.web.bind.annotation.RequestBody;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.RequestMethod;
  import org.springframework.web.bind.annotation.ResponseBody;
  
  import javax.servlet.http.HttpServletResponse;
  import javax.validation.ConstraintViolation;
  import java.util.*;
  import java.util.concurrent.ConcurrentHashMap;
  
  @Controller
  @RequestMapping(value = &quot;/trainees&quot;)
  public class TraineesController {
  
      final Logger logger = LoggerFactory.getLogger(TraineesController.class);
  
      private Map&lt;Long, Trainee&gt; trainees = new ConcurrentHashMap&lt;Long, Trainee&gt;();
  
      @Autowired
      private ITraineeDAO traineeDAO;
       
      /**
       * Return json repres. of all trainees
       */
      @RequestMapping(value = &quot;/getAllTrainees&quot;, method = RequestMethod.GET)
      @ResponseBody        
      public Collection getAllTrainees() {
          Collection allTrainees = this.traineeDAO.getAll();
  
          this.logger.debug(&quot;A total of &quot; + allTrainees.size() + &quot;  trainees was read from db&quot;);
  
          return allTrainees;
      }    
  }
  </code></pre>
  <p>JPA-implementation of the trainee DAO:</p>
  <pre class="lang-java prettyprint-override"><code>@Repository
  @Transactional
  public class TraineeDAO implements ITraineeDAO {
  
      @PersistenceContext
      private EntityManager em;
  
      @Transactional
      public Trainee save(Trainee trainee) {
          em.persist(trainee);
          return trainee;
      }
  
      @Transactional(readOnly = true)
      public Collection getAll() {
          return (Collection) em.createQuery(&quot;SELECT t FROM Trainee t&quot;).getResultList();
      }
  }
  </code></pre>
  <p>persistence.xml</p>
  <pre class="lang-xml prettyprint-override"><code>&lt;persistence xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot;
               xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
               xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd&quot;
               version=&quot;1.0&quot;&gt;
      &lt;persistence-unit name=&quot;RDBMS&quot; transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;
          &lt;exclude-unlisted-classes&gt;false&lt;/exclude-unlisted-classes&gt;
          &lt;properties&gt;
              &lt;property name=&quot;hibernate.hbm2ddl.auto&quot; value=&quot;validate&quot;/&gt;
              &lt;property name=&quot;hibernate.archive.autodetection&quot; value=&quot;class&quot;/&gt;
              &lt;property name=&quot;dialect&quot; value=&quot;org.hibernate.dialect.MySQL5InnoDBDialect&quot;/&gt;
              &lt;!-- &lt;property name=&quot;dialect&quot; value=&quot;org.hibernate.dialect.HSQLDialect&quot;/&gt;         --&gt;
          &lt;/properties&gt;
      &lt;/persistence-unit&gt;
  &lt;/persistence&gt;
  </code></pre>