2 Replies Latest reply on Jan 27, 2008 10:56 AM by Eric H

    failed to lazily initialize a collection

    Bernard Labno Master

      I have stateless bean (LocationBean) that provides access to data, and stateful action bean (CountryEditorBean) that has reference to stateless bean (Local interface). When I click a link on data table with list of entities that redirects me to page with edit form for that entity, I get exception that other aggregated entities cannot be fetched since session has been closed.

      org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: pl.labno.bernard.bidbull.locations.Region.towns, no session or session was closed

      So I figure that LocationBean fetches list of entities, and closes session (but why?), or detatches that entities. They exist only in some seam context.
      Then on editCountry.jspx there is an attempt to count number of Regions aggregated in that country entity. This causes the error, I think, since by default relations are lazy fetched.
      Is my interpretation correct ?
      I do not want to change fething policy, so what can I do to make things work ? Cutting LocationBean out is not an option for me.

      @Stateless
      public class LocationBean implements LocationLocal {
       @PersistenceContext
       private EntityManager em;
       public void add(Country country) throws NonUniqueObjectException {
       if (em.find(Country.class, country.getId()) == null) {
       em.persist(country);
       } else {
       throw new NonUniqueObjectException(country.getId(), Country.class.getCanonicalName());
       }
       }
       public void add(Region region) {
       em.persist(region);
       }
       public void add(Town town) {
       em.persist(town);
       }
       public void update(Country country) {
       em.merge(country);
       }
       public void update(Region region) {
       em.merge(region);
       }
       public void update(Town town) {
       em.merge(town);
       }
       public void remove(Country country) {
       em.remove(country);
       }
       public void remove(Region region) {
       em.remove(region);
       }
       public void remove(Town town) {
       em.remove(town);
       }
       public List<Country> getCountries() {
       return em.createNamedQuery(Country.GET_COUNTRIES_QUERY).getResultList();
       }
      }

      @Name("countryEditor")
      @Scope(ScopeType.CONVERSATION)
      @Stateful
      public class CountryEditorBean implements CountryEditorLocal {
       @In @Out
       private Country country;
       @EJB
       private LocationLocal locationBean;
       private Boolean error = false;
       @Begin(pageflow = "editCountry")
       public void editCountry() {}
       public void save() {
       locationBean.update(getCountry());
       }
       public Country getCountry() {
       return country;
       }
       public void setCountry(Country country) {
       this.country = country;
       }
       @Remove
       public void destroy() {}
      }


        • 1. Re: failed to lazily initialize a collection
          Krunoslav Samardzic Newbie

          Use statefull beans, stateless beans only live for one request-response cycle( they are not very usefull in this way), and use @PersistenceContext(type = PersistenceContextType.EXTENDED) on manager if you want to keep persistence context for more than one cycle,
          this way persistence context is bound to life cycle of statefull bean not just transaction.
          That way your entities will not be detached after response.
          Something else there is a third way, you can bound persistence context to an conversation, that can only be managed with seam, that way all statefull or stateless beans that live in side conversation share the same persistence context, but you have to inject manager

           @In
           private EntityManager em;
          


          • 2. Re: failed to lazily initialize a collection
            Eric H Novice

            I use the Seam-managed persistence context (@In private EntityManager entityManager) and conversation scope, and that cures all these things.