1 Reply Latest reply on Dec 26, 2007 5:39 PM by susnet

    Memory leak in SFSB in session scope in Seam 2.0.0 on JBoss

    susnet

      Hi!
      I upgraded to Seam 2.0.0.GA and it is running on JBoss 4.2.2.

      I have a SFSB in Session scope. The SFSB has an ObjectPool, which is really just a Collection of Entities. The entities in the collection are of type TeaserRecipe which just maps to a table in my database.
      For each httpRequest for certain pages the method getNextTeaserRecipes() are called. This is configured in pages.xml.

      Now to the strange behaviour. If I just use the default settings for conversation timeout and session timeout OR if i set it to for example:
      conversation timeout = 600000 ( = 10 minutes)
      session timeout = 10
      Then the number of instances of TeaserRecipe just grows and gradually leads to OutOfMemoryException. I have also tested a lot of other configurations where session timeout is much longer than conversation timeout and vice versa, all with the same result -> Growing number or instances and OutOfMemoryException if I just wait long enough before restarting JBoss.

      But if don't set any conversation timeout at all AND set session timeout to 2 minutes it works fine and the instances don't grow and gets garbage collected as they should.

      Any Ideas????



      My SFSB. It has 4 objectPools in reality, but i stripped it to one to save some space and making it easier to read.

      import java.util.*;
      import javax.ejb.Remove;
      import javax.ejb.Stateful;
      import javax.ejb.Stateless;
      import javax.persistence.*;
      import org.jboss.seam.ScopeType;
      import org.jboss.seam.annotations.*;
      import org.jboss.seam.log.Log;
      import recepten.common.ObjectPool;
      import recepten.entities.db.TeaserRecipe;
      
      @Stateful
      @Name("recipeTeaserService")
      @Scope(ScopeType.SESSION)
      public class RecipeTeaserServiceBean implements
       recepten.actions.RecipeTeaserServiceLocal {
      
       @Logger Log log;
      
       @PersistenceContext(type = PersistenceContextType.EXTENDED)
       private EntityManager em;
      
       ObjectPool<TeaserRecipe> recipePoolSidebarLeft1;
      
       private TeaserRecipe recipeSidebarLeft1;
      
       public RecipeTeaserServiceBean() {
       }
      
       @Create
       public void initPools() {
       // Create new objectPools
       recipePoolSidebarLeft1 = new ObjectPool<TeaserRecipe>();
      
       // Create a pool of the pools
       ArrayList<ObjectPool<TeaserRecipe>> poolList = new ArrayList<ObjectPool<TeaserRecipe>>();
       poolList.add(recipePoolSidebarLeft1);
      
       // Get recipes from database
       List<TeaserRecipe> teaserRecipeList = em
       .createQuery(
       "SELECT t FROM TeaserRecipe t WHERE t.show = true ORDER BY seq")
       .getResultList();
      
       int poolListIndex = 0;
       for (TeaserRecipe teaserRecipe : teaserRecipeList) {
       poolList.get(poolListIndex).add(teaserRecipe);
       if (++poolListIndex == poolList.size()) {
       poolListIndex = 0;
       }
       }
       }
      
       public TeaserRecipe getRecipeSidebarLeft1() {
       return recipeSidebarLeft1;
       }
      
      
       public void getNextTeaserRecipes() {
       // Get next recipe from pool
       recipeSidebarLeft1 = recipePoolSidebarLeft1.next();
       }
      
       @Destroy
       @Remove
       public void destroy() {
       }
      


      ObjectPool:
      package recepten.common;
      
      import java.util.ArrayList;
      import java.util.Collections;
      
      public class ObjectPool<T> {
      
       ArrayList<T> list = new ArrayList<T>();
       int pointer;
      
       public ObjectPool() {}
      
       public void add(T instance) {
       list.add (instance);
       }
      
       public T next(){
       if (++pointer == list.size()) {
       pointer = 0;
       }
       if (list.size () == 0) {
       return null;
       }
       return list.get(pointer);
       }
      
       public void shuffle() {
       Collections.shuffle (list);
       }
      }
      


      TeaserRecipe:
      @Entity
      @Table(name = "teaserrecipe")
      public class TeaserRecipe implements Serializable {
      
       @Id
       @Column(name = "recipeid", nullable = false)
       private Integer recipeid;
      
       @Column(name = "headline")
       private String headline;
      
       @Column(name = "teasertext")
       private String teasertext;
      
       @Column(name = "seq", nullable = false)
       private int seq;
      
       @Column(name = "show", nullable = false)
       private boolean show;
      
       @JoinColumn(name = "recipeid", referencedColumnName = "recipeid", insertable = false, updatable = false)
       @OneToOne
       private Recipe recipe;
      
       /** Creates a new instance of TeaserRecipe */
       public TeaserRecipe () {
       }
      
       // Getters and setters and overridden equals, toString and hashcode methods.
      }
      


      pages.xml (only the interesting part)
      <page view-id="/pages/*">
       <action execute="#{recipeTeaserService.getNextTeaserRecipes}"/>
       </page>
      



      The same code worked fine in Seam 1.2.1. and JBoss 4.0.5.

      Please tell me if there are some more code you would like to see.

      Any help is appreciated since now I'm forced to have a session timeout set to 2 minutes which leads to many View experiation exceptions since the timeout is too short.

      Thanks in advance!

        • 1. Re: Memory leak in SFSB in session scope in Seam 2.0.0 on JB
          susnet

          I have tried removing the method call to getNextTeaserRecipes() from pages.xml and the problem is still the same.

          The only solution is still setting the session timeout to 2 minutes.

          I discovered that the growth rate of number of instances is higher with a longer session timeout, like between 10-30 minutes but for a lower number like 5 minutes the growth rate is much lower and for 2 minutes it is 0 i.e. no growth rate.

          Please help me! Is something wrong with my code or is it a bug in seam or ejb3 or what do you think?