title: java.lang.StackOverflowError when persisting an object jpa
body: <p>I am building an application using JPA, JSF, EJB, Derby. At this point the application is still small. I have a form in the application to add new products. When adding data to the db it goes smoothly until I restart the application or the server. When I restart either the server or app I get <code>java.lang.StackOverflowError</code>, I still can query the db for the data represented by the product db, but creation product is not possible. I have only 5 entries in the db, as of now, but I am concerned about this happening so early.</p>
  
  <p>This is the Ejb (Getter, setter and constructors removed for simplicity):</p>
  
  <pre><code>@Stateless
  public class ProductEJB{
  
      @PersistenceContext(unitName = "luavipuPU")
      private EntityManager em;
  
      public List&lt;Product&gt; findAllProducts()
      {
          TypedQuery&lt;Product&gt; query = em.createNamedQuery("findAllProducts", Product.class);
          return query.getResultList();
      }
  
      public Product findProductById(int productId)
      {
          return em.find(Product.class, productId);
      }
  
      public Product createProduct(Product product)
      {
          product.setDateAdded(productCreationDate());
          em.persist(product);
          return product;        
      }    
  
      public void updateProduct(Product product)
      {
          em.merge(product);
      }
  
      public void deleteProduct(Product product)
      {
          product = em.find(Product.class, product.getProduct_id());
          em.remove(em.merge(product));
      }
  </code></pre>
  
  <p>this is the ProductController (Getter, setter and constructors removed for simplicity):</p>
  
  <pre><code>    @Named
  @RequestScoped
  public class ProductController {
  
      @EJB
      private ProductEJB productEjb;
      @EJB
      private CategoryEJB categoryEjb;
  
      private Product product = new Product();
      private List&lt;Product&gt; productList = new ArrayList&lt;Product&gt;();
  
      private Category category;
      private List&lt;Category&gt; categoryList = new ArrayList&lt;Category&gt;();
  
      public String doCreateProduct()
      {
          product = productEjb.createProduct(product);
          productList = productEjb.findAllProducts();
          return "listProduct?faces-redirect=true";
      }
  
      public String doDeleteProduct()
      {
          productEjb.deleteProduct(product);
          return "deleteProduct?faces-redirect=true";
      }
  
      public String cancelDeleteAction()
      {
          return "listProduct?faces-redirect=true";
      }
  
  
      @PostConstruct
      public void init()
      {
          categoryList = categoryEjb.findAllCategory();
          productList = productEjb.findAllProducts();        
      }
  </code></pre>
  
  <p>Category Entity (Getters, setters, hash() and constructors removed for simplicity):</p>
  
  <pre><code>@Entity
  @NamedQueries({
      @NamedQuery(name= "findAllCategory", query="SELECT c FROM Category c")        
  })
  public class Category implements Serializable
  {
      private static final long serialVersionUID = 1L;
  
      @Id @GeneratedValue(strategy= GenerationType.AUTO)
      private int category_id;
      private String name;
      private String description;
      @OneToMany(mappedBy = "category_fk")
          private List&lt;Product&gt; product_fk;
  
   // readObject() and writeObject() 
  
      private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException
      {
          // default deserializer
          ois.defaultReadObject();
  
          // read the attributes
          category_id = ois.readInt();
          name = (String)ois.readObject();
          description = (String)ois.readObject();
  
      }
  
      private void writeObject(ObjectOutputStream oos) throws IOException, ClassNotFoundException
      {
          // default serializer
          oos.defaultWriteObject();
  
          // write the attributes
          oos.writeInt(category_id);
          oos.writeObject(name);
          oos.writeObject(description);
  
  
         }
  
   @Override
      public boolean equals(Object obj) {
          if (obj == null) {
              return false;
          }
          if (getClass() != obj.getClass()) {
              return false;
          }
          final Category other = (Category) obj;
          if (this.category_id != other.category_id) {
              return false;
          }
          if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
              return false;
          }
          if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) {
              return false;
          }
          if (this.product_fk != other.product_fk &amp;&amp; (this.product_fk == null || !this.product_fk.equals(other.product_fk))) {
              return false;
          }
          return true;
      }
  </code></pre>
  
  <p>Product Entity (Getters, setters, hash() and constructors removed for simplicity):</p>
  
  <pre><code>@Entity
  @NamedQueries({
      @NamedQuery(name="findAllProducts", query = "SELECT p from Product p")
  
  })
  public class Product implements Serializable
  {
      private static final long serialVersionUID = 1L;
  
      @Id @GeneratedValue(strategy= GenerationType.AUTO)
      private int product_id;
      private String name;
      private String description;
      protected byte[] imageFile;
      private Float price;
      @Temporal(TemporalType.TIMESTAMP)
      private Date dateAdded;        
      @ManyToOne
      private Category category_fk;
      @ManyToOne
      private SaleDetails saleDetails_fk;
  
      // readObject() and writeObject() methods
  
      private void readObject (ObjectInputStream ois)throws IOException, ClassNotFoundException
      {
          // default deserialization
          ois.defaultReadObject();
  
          // read the attributes
          product_id = ois.readInt();
          name = (String)ois.readObject();
          description = (String)ois.readObject();
  
          for(int i=0; i&lt;imageFile.length; i++ )
          {
              imageFile[i]=ois.readByte();
          }
  
          price = ois.readFloat();
          dateAdded = (Date)ois.readObject();
          category_fk = (Category)ois.readObject();
          saleDetails_fk = (SaleDetails)ois.readObject();
  
      }
  
  @Override
  public boolean equals(Object obj) {
      if (obj == null) {
          return false;
      }
      if (getClass() != obj.getClass()) {
          return false;
      }
      final Product other = (Product) obj;
      if (this.product_id != other.product_id) {
          return false;
      }
      if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
          return false;
      }
      if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) {
          return false;
      }
      if (!Arrays.equals(this.imageFile, other.imageFile)) {
          return false;
      }
      if (this.price != other.price &amp;&amp; (this.price == null || !this.price.equals(other.price))) {
          return false;
      }
      if (this.dateAdded != other.dateAdded &amp;&amp; (this.dateAdded == null || !this.dateAdded.equals(other.dateAdded))) {
          return false;
      }
      if (this.category_fk != other.category_fk &amp;&amp; (this.category_fk == null || !this.category_fk.equals(other.category_fk))) {
          return false;
      }
      if (this.saleDetails_fk != other.saleDetails_fk &amp;&amp; (this.saleDetails_fk == null || !this.saleDetails_fk.equals(other.saleDetails_fk))) {
          return false;
      }
      return true;
  }
  
      private void writeObject(ObjectOutputStream oos) throws IOException, ClassNotFoundException
      {
          // default serialization
          oos.defaultWriteObject();
  
          // write object attributes
          oos.writeInt(product_id);
          oos.writeObject(name);
          oos.writeObject(description);
          oos.write(imageFile);
          oos.writeFloat(price);
          oos.writeObject(dateAdded);
          oos.writeObject(category_fk);
          oos.writeObject(saleDetails_fk);
  
      }
  </code></pre>
  
  <p>This is the stacktrace:</p>
  
  <pre><code>    javax.faces.el.EvaluationException: java.lang.StackOverflowError
      at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
      at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
      at javax.faces.component.UICommand.broadcast(UICommand.java:315)
      at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
      at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
      at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
      at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
      at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
      at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
      at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
      at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
      at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
      at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
      at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
      at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
      at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
      at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
      at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
      at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
      at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
      at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
      at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
      at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
      at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
      at java.lang.Thread.run(Thread.java:722)
  Caused by: java.lang.StackOverflowError
      at java.util.Vector$Itr.&lt;init&gt;(Vector.java:1120)
      at java.util.Vector.iterator(Vector.java:1114)
      at java.util.AbstractList.hashCode(AbstractList.java:540)
      at java.util.Vector.hashCode(Vector.java:988)
      at org.eclipse.persistence.indirection.IndirectList.hashCode(IndirectList.java:460)
      at com.lv.Entity.Category.hashCode(Category.java:96)
      at com.lv.Entity.Product.hashCode(Product.java:148)
      at java.util.AbstractList.hashCode(AbstractList.java:541)
  </code></pre>