9 Replies Latest reply on Mar 13, 2008 1:04 PM by zilbi

    EJB3 Lazy Load problem

    zilbi

      Hi,

      i am new to this, so i apologize if this question is stupid...

      have 2 entities with 1 to many relations:

      @Entity
      @Table(name = "contents")
      public class Content implements Serializable
      {
       private Long id;
       private Integer version;
       ... some more simple fields
      
       private Collection lastTaggingCollection;
      
       @ManyToOne
       @JoinColumn(name = "last_tagging_collection", nullable = true)
       public Collection getLastTaggingCollection()
       {
       return lastTaggingCollection;
       }
      
       public void setLastTaggingCollection(Collection lastTaggingCollection)
       {
       this.lastTaggingCollection = lastTaggingCollection;
       }
      
       ... more methods
      }
      
      @Entity
      @Table(name = "cm_collections")
      public class Collection implements Serializable
      {
       private Long id;
       private Integer version;
       ... some more simple fields
      
       private List<Content> contents;
      
       @OneToMany(fetch = FetchType.LAZY, mappedBy = "lastTaggingCollection")
       @JoinColumn(name = "last_tagging_collection")
       public List<Content> getContents()
       {
       return contents;
       }
      
       public void setContents(List<Content> contents)
       {
       this.contents = contents;
       }
      
       ... more methods
      }


      now, when i am inside a stateless session bean method with a transaction type = required i try the following:
      Collection collection = dao.findById( 1L );
      log.debug("fetchContacts() - caller: " + collection.getContents().size());

      (the dao is injected using @EJB)

      i get:
      org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.jinni.content.mgmt.model.Collection.contents, no session or session was closed


      but when i change the fetch type to eager all works...

      ???

      any clue why?
      what am i missing?

      thanks

        • 1. Re: EJB3 Lazy Load problem
          tom_goring

          Post your 'session' bean code.

          • 2. Re: EJB3 Lazy Load problem
            zilbi

            there you go:

            @Stateless
            @Remote(ContactsInviter.class)
            @SecurityDomain("jinni")
            public class ContactsInviterImpl implements ContactsInviter
            {
             private static final Log log = LogFactory.getLog(ContactsInviterImpl.class);
            
             @EJB
             private CollectionDao dao;
            
             @TransactionAttribute(TransactionAttributeType.REQUIRED)
             public List<ExternalContact> fetchContacts(String email, String password) throws ExternalProfileException
             {
             log.debug("fetchContacts() - starting with email: " + email + " with password: " + password);
             try
             {
             // some non relevant code here...
            
             Collection collection = dao.findById( 1L );
             log.debug("fetchContacts() - caller: " + collection.getContents().size());
            
             // some more non relevant code here...
             }
             catch (Exception e)
             {
             String errMsg = "failed to fetch contacts for email: " + email + " with password: " + password + " due to: " + e.getMessage();
             log.error("fetchContacts() - " + errMsg, e);
             throw new ExternalProfileException( e );
             }
             }
            
             // some more methods...
            }
            


            • 3. Re: EJB3 Lazy Load problem
              tom_goring

              Is your

              @EJB
              private CollectionDao dao;
              


              a remote interface ?


              • 4. Re: EJB3 Lazy Load problem
                zilbi

                both:

                @Stateless
                @Local(CollectionDao.class)
                @Remote(CollectionDao.class)
                public class CollectionDaoImpl extends DaoImpl<Collection, Long>
                {
                
                }


                • 5. Re: EJB3 Lazy Load problem
                  tom_goring

                  I've not seen it done like that (same interface for both local/remote) ... try making your DAO layer local only. I'm not sure how you have things setup if you will get a local or remote interface injected.

                  I think if it's the remote interface your entities will be serialized and thus detached.

                  I've things setup like:

                  @Remote
                  public interface AddressManagerRemote extends AddressManagerInterface {
                  }
                  ...
                  @Local
                  public interface AddressManagerLocal extends AddressManagerInterface {
                  }
                  ...
                  @Stateless
                  @Remote(AddressManager.class)
                  @Local(AddressManagerLocal.class)
                  public class AddressManagerBean implements AddressManagerRemote {
                  }
                  



                  Then I can choose to use the local interface if required (in my SLSB's etc).

                  • 6. Re: EJB3 Lazy Load problem
                    zilbi

                    Mary Mother of GOD!!!!

                    you are RIGHT!!!
                    thanks man.
                    would never think of it by my self...

                    so the conclusion here is that in jboss 4.2:
                    if your local and remote interface are actually one;
                    and your SLSB implements both;
                    and you use injection rather than a lookup to retrieve it,

                    you will get the remote by default!
                    which will cause the LAZY stuff to be corrupted...


                    why is that?
                    sounds like a bug to me, or at least an optimization error.

                    comments are welcomed

                    • 7. Re: EJB3 Lazy Load problem
                      alrubinger

                       

                      "EJB 3.0 Core Specification, 4.6.6 Bullet 5.4" wrote:
                      The same business interface cannot be both a local and a remote business interface of
                      the bean


                      More recent versions of JBoss EJB3 will throw an exception on deployment when this case is encountered, see http://jira.jboss.com/jira/browse/EJBTHREE-751.

                      S,
                      ALR

                      • 8. Re: EJB3 Lazy Load problem
                        tom_goring

                         

                        you will get the remote by default!


                        well Its going to have to pick one method ...


                        which will cause the LAZY stuff to be corrupted...


                        not true... they will just be detached (as they will have been serialised i.e. copy object).

                        I'd advise you have separate Local / Remote interfaces.... well I'd advise you drop Remote all-together and use jboss Seam !!




                        • 9. Re: EJB3 Lazy Load problem
                          zilbi

                          thanks,

                          the reason i'm having the remote for now is for my JUnits, i plan to remove them at production.

                          as for seam, my web developer just doest like JSF so i will stick to simple EJBs for now.

                          cheers