title: Hibernate/Spring: failed to lazily initialize - no session or session was closed
body: <p><strong>For an answer scroll down to the end of this...</strong></p>
  
  <p>The basic problem is the same as asked multiple time. I have a simple program with two POJOs Event and User - where a user can have multiple events.</p>
  
  <pre><code>@Entity
  @Table
  public class Event {
   private Long id;
   private String name;
   private User user;
  
   @Column
   @Id
   @GeneratedValue
   public Long getId() {return id;}
   public void setId(Long id) { this.id = id; }
  
   @Column
   public String getName() {return name;}
   public void setName(String name) {this.name = name;}
  
   @ManyToOne
   @JoinColumn(name="user_id")
   public User getUser() {return user;}
   public void setUser(User user) {this.user = user;}
  
  }
  </code></pre>
  
  <p>The User:</p>
  
  <pre><code>@Entity
  @Table
  public class User {
   private Long id;
   private String name;
   private List&lt;Event&gt; events;
  
   @Column
   @Id
   @GeneratedValue
   public Long getId() { return id; }
   public void setId(Long id) { this.id = id; }
  
   @Column
   public String getName() { return name; }
   public void setName(String name) { this.name = name; }
  
   @OneToMany(mappedBy="user", fetch=FetchType.LAZY)
   public List&lt;Event&gt; getEvents() { return events; }
   public void setEvents(List&lt;Event&gt; events) { this.events = events; }
  
  }
  </code></pre>
  
  <p>Note: This is a sample project. I <strong>really</strong> want to use Lazy fetching here.</p>
  
  <p>Now we need to configure spring and hibernate and have a simple basic-db.xml for loading:</p>
  
  <pre>
  <code>
  &lt;?xml version="1.0" encoding="UTF-8"?>
  &lt;beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xsi:schemaLocation="http://www.springframework.org/schema/beans 
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/aop 
             http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
  
  
   &lt;bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close"  scope="thread">
    &lt;property name="driverClassName" value="com.mysql.jdbc.Driver" />
    &lt;property name="url" value="jdbc:mysql://192.168.1.34:3306/hibernateTest" />
    &lt;property name="username" value="root" />
    &lt;property name="password" value="" />
    &lt;aop:scoped-proxy/>
   &lt;/bean>
  
   &lt;bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    &lt;property name="scopes">
     &lt;map>
      &lt;entry key="thread">
       &lt;bean class="org.springframework.context.support.SimpleThreadScope" />
      &lt;/entry>
     &lt;/map>
    &lt;/property>
   &lt;/bean>
  
   &lt;bean id="mySessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" scope="thread">
    &lt;property name="dataSource" ref="myDataSource" />
    &lt;property name="annotatedClasses">
     &lt;list>
      &lt;value>data.model.User&lt;/value>
      &lt;value>data.model.Event&lt;/value>
     &lt;/list>
    &lt;/property>
    &lt;property name="hibernateProperties">
     &lt;props>
      &lt;prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect&lt;/prop>
      &lt;prop key="hibernate.show_sql">true&lt;/prop>
      &lt;prop key="hibernate.hbm2ddl.auto">create&lt;/prop>
     &lt;/props>
    &lt;/property>
    &lt;aop:scoped-proxy/>
  
   &lt;/bean>
  
   &lt;bean id="myUserDAO" class="data.dao.impl.UserDaoImpl">
    &lt;property name="sessionFactory" ref="mySessionFactory" />
   &lt;/bean>
  
   &lt;bean id="myEventDAO" class="data.dao.impl.EventDaoImpl">
    &lt;property name="sessionFactory" ref="mySessionFactory" />
   &lt;/bean>
  
  &lt;/beans>
  </code>
  </pre>
  
  <p>Note: I played around with the CustomScopeConfigurer and SimpleThreadScope, but that didnt change anything.</p>
  
  <p>I have a simple dao-impl (only pasting the userDao - the EventDao is pretty much the same - except with out the "listWith" function:</p>
  
  <pre>
  <code>
  public class UserDaoImpl implements UserDao{
  
   private HibernateTemplate hibernateTemplate;
  
   public void  setSessionFactory(SessionFactory sessionFactory) {
    this.hibernateTemplate = new HibernateTemplate(sessionFactory);
  
   }
  
   @SuppressWarnings("unchecked")
   @Override
   public List listUser() {
    return hibernateTemplate.find("from User");
   }
  
   @Override
   public void saveUser(User user) {
    hibernateTemplate.saveOrUpdate(user);
  
   }
  
   @Override
   public List listUserWithEvent() {
  
    List users = hibernateTemplate.find("from User");
    for (User user : users) {
     System.out.println("LIST : " + user.getName() + ":");
     user.getEvents().size();
    }
    return users;
   }
  
  }
  </code>
  </pre>
  
  <p>I am getting the org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: data.model.User.events, no session or session was closed at the line with <em>user.getEvents().size()</em>;</p>
  
  <p>And last but not least here is the Test class I use:</p>
  
  <pre>
  <code>
  public class HibernateTest {
  
   public static void main(String[] args) {
  
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("basic-db.xml");
  
  
    UserDao udao = (UserDao) ac.getBean("myUserDAO");
    EventDao edao = (EventDao) ac.getBean("myEventDAO");
  
  
    System.out.println("New user...");
    User user = new User();
    user.setName("test");
  
    Event event1 = new Event();
    event1.setName("Birthday1");
    event1.setUser(user);
  
    Event event2 = new Event();
    event2.setName("Birthday2");
    event2.setUser(user);
  
    udao.saveUser(user);
    edao.saveEvent(event1);
    edao.saveEvent(event2);
  
    List users = udao.listUserWithEvent();
    System.out.println("Events for users");
    for (User u : users) {
  
     System.out.println(u.getId() + ":" + u.getName() + " --");
     for (Event e : u.getEvents())
     {
      System.out.println("\t" + e.getId() + ":" + e.getName());
     }
    }
  
    ((ConfigurableApplicationContext)ac).close();
   }
  
  }
  </code>
  </pre>
  
  <p>and here is the Exception:</p>
  
  <pre>
  1621 [main] ERROR org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: data.model.User.events, no session or session was closed
  org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: data.model.User.events, no session or session was closed
   at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
   at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
   at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
   at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
   at data.dao.impl.UserDaoImpl.listUserWithEvent(UserDaoImpl.java:38)
   at HibernateTest.main(HibernateTest.java:44)
  Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: data.model.User.events, no session or session was closed
   at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
   at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
   at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
   at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
   at data.dao.impl.UserDaoImpl.listUserWithEvent(UserDaoImpl.java:38)
   at HibernateTest.main(HibernateTest.java:44)
  </pre>
  
  <p>Things tried but did not work:</p>
  
  <ul>
  <li>assign a threadScope and using beanfactory (I used "request" or "thread" - no difference noticed):</li>
  </ul>
  
  <pre>
    // scope stuff
    Scope threadScope = new SimpleThreadScope();
    ConfigurableListableBeanFactory beanFactory = ac.getBeanFactory();
    beanFactory.registerScope("request", threadScope);
    ac.refresh();
  ...
  </pre>
  
  <ul>
  <li>Setting up a transaction by getting the session object from the deo:</li>
  </ul>
  
  <pre>
  ...
    Transaction tx = ((UserDaoImpl)udao).getSession().beginTransaction();
    tx.begin();
    users = udao.listUserWithEvent();
  ...
  </pre>
  
  <ul>
  <li>getting a transaction within the listUserWithEvent()</li>
  </ul>
  
  <pre>
   public List listUserWithEvent() {
    SessionFactory sf = hibernateTemplate.getSessionFactory();
    Session s = sf.openSession();
    Transaction tx = s.beginTransaction();
    tx.begin();
  
    List users = hibernateTemplate.find("from User");
    for (User user : users) {
     System.out.println("LIST : " + user.getName() + ":");
     user.getEvents().size();
    }
    tx.commit();
    return users;
   }
  </pre>
  
  <p>I am really out of ideas by now. Also, using the listUser or listEvent just work fine. </p>
  
  <p><strong>Step forward:</strong></p>
  
  <p>Thanks to Thierry I got one step further (I think). I created the MyTransaction class and do my whole work in there, getting everything from spring. The new main looks like this:</p>
  
  <pre>
  <code>
   public static void main(String[] args) {
  
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("basic-db.xml");
  
    // getting dao
    UserDao udao = (UserDao) ac.getBean("myUserDAO");
    EventDao edao = (EventDao) ac.getBean("myEventDAO");
  
    // gettting transaction template
    TransactionTemplate transactionTemplate = (TransactionTemplate) ac.getBean("transactionTemplate");
  
    MyTransaction mt = new MyTransaction(udao, edao);
    transactionTemplate.execute(mt);
  
    ((ConfigurableApplicationContext)ac).close();
   }
  </code>
  </pre>
  
  <p>Unfortunately now there is a null-pointer Exception @: user.getEvents().size(); (in the daoImpl). </p>
  
  <p>I know that it should not be null (neither from the output in the console nor from the db layout). </p>
  
  <p>Here is the console output for more information (I did a check for user.getEvent() == null and printed "EVENT is NULL"):</p>
  
  <pre>
  New user...
  Hibernate: insert into User (name) values (?)
  Hibernate: insert into User (name) values (?)
  Hibernate: insert into Event (name, user_id) values (?, ?)
  Hibernate: insert into Event (name, user_id) values (?, ?)
  Hibernate: insert into Event (name, user_id) values (?, ?)
  List users:
  Hibernate: select user0_.id as id0_, user0_.name as name0_ from User user0_
  1:User1
  2:User2
  List events:
  Hibernate: select event0_.id as id1_, event0_.name as name1_, event0_.user_id as user3_1_ from Event event0_
  1:Birthday1 for 1:User1
  2:Birthday2 for 1:User1
  3:Wedding for 2:User2
  Hibernate: select user0_.id as id0_, user0_.name as name0_ from User user0_
  Events for users
  1:User1 --
  EVENT is NULL
  2:User2 --
  EVENT is NULL
  </pre>
  
  <p>You can get the sample project from <a href="http://www.gargan.org/code/hibernate-test1.tgz" rel="noreferrer">http://www.gargan.org/code/hibernate-test1.tgz</a> (it's an eclipse/maven project)</p>
  
  <p><strong>The solution (for console applications)</strong></p>
  
  <p>There are actually two solutions for this problem - depending on your environment:</p>
  
  <p>For a console application you need a transaction template which captures the actutal db logic and takes care of the transaction:</p>
  
  <pre>
  <code>
  public class UserGetTransaction implements TransactionCallback{
  
   public List users;
  
   protected ApplicationContext context;
  
   public UserGetTransaction (ApplicationContext context) {
    this.context = context;
   }
  
   @Override
   public Boolean doInTransaction(TransactionStatus arg0) {
    UserDao udao = (UserDao) ac.getBean("myUserDAO");
    users = udao.listUserWithEvent();
    return null;
   }
  
  }
  </code>
  </pre>
  
  <p>You can use this by calling:</p>
  
  <pre>
  <code>
   TransactionTemplate transactionTemplate = (TransactionTemplate) context.getBean("transactionTemplate");
   UserGetTransaction mt = new UserGetTransaction(context);
   transactionTemplate.execute(mt);
  </code>
  </pre>
  
  <p>In order for this to work you need to define the template class for spring (ie. in your basic-db.xml):</p>
  
  <pre><code>&lt;bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"&gt;
      &lt;property name="transactionManager" ref="transactionManager"/&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p><strong>Another (possible) solution</strong></p>
  
  <p>thanks andi</p>
  
  <pre><code>    PlatformTransactionManager transactionManager = (PlatformTransactionManager) applicationContext.getBean("transactionManager");
      DefaultTransactionAttribute transactionAttribute = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED);
  
  transactionAttribute.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
      TransactionStatus status = transactionManager.getTransaction(transactionAttribute);
      boolean success = false;
      try {
        new UserDataAccessCode().execute();
        success = true;
      } finally {
        if (success) {
          transactionManager.commit(status);
        } else {
          transactionManager.rollback(status);
        }
      }
  </code></pre>
  
  <p><strong>The solution (for servlets)</strong></p>
  
  <p>Servlets are not that big of a problem. When you have a servlet you can simply start and bind a transaction at the beginning of your function and unbind it again at the end:</p>
  
  <pre><code>public void doGet(...) {
    SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");
    Session session = SessionFactoryUtils.getSession(sessionFactory, true);
    TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
  
  // Your code....
  
    TransactionSynchronizationManager.unbindResource(sessionFactory);
  }
  </code></pre>