title: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
body: <p>I am getting this exception when I call a DAO method which uses <code>SessionFactory.getCurrentSession()</code>.  The DAO class is annotated with <code>@Transactional</code> and I also have <code>&lt;tx:annotation-driven/&gt;</code> declared in the application context configuration file.</p>
  
  <p>I can call my DAO methods which perform HQL queries, but whenever I call a DAO method which first gets the Hibernate session then I run into this exception:</p>
  
  <pre><code>SEVERE: Failed to save the object.
  org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
      at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
      at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:622)
      at gov.noaa.ncdc.cmb.persistence.dao.GenericDaoHibernateImpl.getCurrentSession(GenericDaoHibernateImpl.java:56)
      at gov.noaa.ncdc.cmb.persistence.dao.GenericDaoHibernateImpl.saveOrUpdate(GenericDaoHibernateImpl.java:187)
  </code></pre>
  
  <p>I have the following application context configuration file:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xmlns:flex="http://www.springframework.org/schema/flex"
         xmlns:tx="http://www.springframework.org/schema/tx"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
                             http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                             http://www.springframework.org/schema/flex
                             http://www.springframework.org/schema/flex/spring-flex-1.0.xsd
                             http://www.springframework.org/schema/tx
                             http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"&gt;
  
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;!--  load values used for bean properties  --&gt;
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;
          &lt;property name="locations"&gt;
              &lt;value&gt;applicationContext.properties&lt;/value&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
  
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;!--  DataSource where objects will be persisted  --&gt;
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
          &lt;property name="username" value="${datasource.username}" /&gt;
          &lt;property name="password" value="${datasource.password}" /&gt;
          &lt;property name="url" value="${datasource.url}" /&gt;
          &lt;property name="driverClassName" value="${datasource.driver}" /&gt;
      &lt;/bean&gt;
  
  
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;!-- Factory bean for Hibernate Sessions --&gt;
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&gt;
          &lt;property name="dataSource" ref="dataSource" /&gt;
          &lt;property name="annotatedClasses"&gt;
              &lt;list&gt;
                  &lt;value&gt;gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlDailyAvg&lt;/value&gt;
                  &lt;value&gt;gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlObservations&lt;/value&gt;
                  &lt;value&gt;gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlStation&lt;/value&gt;
              &lt;/list&gt;
          &lt;/property&gt;
          &lt;property name="hibernateProperties"&gt;
              &lt;props&gt;
                  &lt;prop key="hibernate.dialect"&gt;${hibernate.dialect}&lt;/prop&gt;
                  &lt;prop key="hibernate.show_sql"&gt;false&lt;/prop&gt;
                  &lt;prop key="hibernate.format_sql"&gt;true&lt;/prop&gt;
                  &lt;prop key="hibernate.use_sql_comments"&gt;true&lt;/prop&gt;
                  &lt;prop key="hibernate.jdbc.batch_size"&gt;50&lt;/prop&gt;
                  &lt;prop key="hibernate.query.substitutions"&gt;true 1, false 0&lt;/prop&gt;
                  &lt;prop key="hibernate.max_fetch_depth"&gt;6&lt;/prop&gt;
                  &lt;prop key="hibernate.hbm2ddl.auto"&gt;${hibernate.hbm2ddlauto}&lt;/prop&gt;
                  &lt;prop key="hibernate.cache.use_second_level_cache"&gt;${hibernate.use_second_level_cache}&lt;/prop&gt;
              &lt;/props&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
  
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;!--  Transaction Manager bean  --&gt;
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;
          &lt;property name="sessionFactory" ref="hibernateSessionFactory" /&gt;
      &lt;/bean&gt;
  
  
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;!--  enable the configuration of transactional behavior based on annotations  --&gt;
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;tx:annotation-driven transaction-manager="transactionManager" /&gt;
  
  
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;!--  DAO for ESRL Station objects  --&gt;
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;bean id="esrlStationDao" class="gov.noaa.ncdc.cmb.esrl.domain.dao.EsrlStationDaoHibernateImpl"&gt;
          &lt;property name="sessionFactory" ref="hibernateSessionFactory" /&gt;
          &lt;property name="persistentClass" value="gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlStation" /&gt;
      &lt;/bean&gt;
  
  
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;!--  DAO for ESRL Observations objects  --&gt;
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;bean id="esrlObservationsDao" class="gov.noaa.ncdc.cmb.esrl.domain.dao.EsrlObservationsDaoHibernateImpl"&gt;
          &lt;property name="sessionFactory" ref="hibernateSessionFactory" /&gt;
          &lt;property name="persistentClass" value="gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlObservations" /&gt;
      &lt;/bean&gt;
  
  
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;!--  DAO for ESRL daily average objects  --&gt;
      &lt;!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&gt;
      &lt;bean id="esrlDailyAvgDao" class="gov.noaa.ncdc.cmb.esrl.domain.dao.EsrlDailyAvgDaoHibernateImpl"&gt;
          &lt;property name="sessionFactory" ref="hibernateSessionFactory" /&gt;
          &lt;property name="persistentClass" value="gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlDailyAvg" /&gt;
      &lt;/bean&gt;
  
  
  &lt;/beans&gt; 
  </code></pre>
  
  <p>The generic DAO class (from which the DAO being used in my program is extended) looks like this:</p>
  
  <pre><code>package gov.noaa.ncdc.cmb.persistence.dao;
  
  import gov.noaa.ncdc.cmb.persistence.entity.PersistentEntity;
  import java.io.Serializable;
  import java.util.Collection;
  import java.util.Date;
  import java.util.List;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.hibernate.Criteria;
  import org.hibernate.Session;
  import org.hibernate.SessionFactory;
  import org.hibernate.criterion.Criterion;
  import org.hibernate.criterion.Example;
  
  /**
   * This class is an implementation of GenericDao&lt;T, PK&gt; using Hibernate.
   */
  public class GenericDaoHibernateImpl&lt;T extends PersistentEntity&lt;PK&gt;, PK extends Serializable&gt;
      implements GenericDao&lt;T, PK&gt;
  {
      private SessionFactory sessionFactory;
  
      static private Log log = LogFactory.getLog(GenericDaoHibernateImpl.class);
  
      private Class&lt;T&gt; persistentClass;
  
      /**
       * Can be used within subclasses as a convenience method.
       * 
       * @param criterionList the criteria to find by
       * @return the list of elements that match the specified criteria
       */
      protected List&lt;T&gt; findByCriteria(final List&lt;Criterion&gt; criterionList)
      {
          Criteria criteria = getCurrentSession().createCriteria(persistentClass);
          for (Criterion criterion : criterionList)
          {
              criteria.add(criterion);
          }
          return criteria.list();
      }
  
      protected String getCanonicalPersistentClassName()
      {
          return persistentClass.getCanonicalName();
      }
  
      /**
       * Gets the current Hibernate Session object.
       * 
       * @return
       */
      protected Session getCurrentSession()
      {
          return sessionFactory.getCurrentSession();
      }
  
      /*
       * This method only provided for interface compatibility.  Not recommended for use with large batches 
       * (this is an inefficient implementation, and it's somewhat difficult to perform batch operations with Hibernate).
       * 
       * (non-Javadoc)
       * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#batchInsert(java.util.Collection)
       */
      @Override
      public int[] batchInsert(final Collection&lt;T&gt; entityCollection)
      {
          int[] updateCounts = new int[entityCollection.size()];
          int i = 0;
          for (T entity : entityCollection)
          {
              try
              {
                  saveOrUpdate(entity);
                  updateCounts[i] = 1;
                  i++;
              }
              catch (Exception ex)
              {
                  clear();
                  throw new RuntimeException(ex);
              }
          }
          flush();
          clear();
  
          return updateCounts;
      }
  
      /*
       * This method only provided for interface compatibility.  Not recommended for use with large batches 
       * (this is an inefficient implementation, and it's somewhat difficult to perform batch operations with Hibernate).
       * 
       * (non-Javadoc)
       * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#batchUpdate(java.util.Collection)
       */
      @Override
      public int[] batchUpdate(final Collection&lt;T&gt; entityCollection)
      {
          return batchInsert(entityCollection);
      }
  
      /**
       * Completely clear the session. Evict all loaded instances and cancel all pending saves, updates and deletions. Do
       * not close open iterators or instances of ScrollableResults.
       */
      public void clear()
      {
          getCurrentSession().clear();
      }
  
      /*
       * (non-Javadoc)
       * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#delete(gov.noaa.ncdc.cmb.persistence.entity.PersistentEntity)
       */
      @Override
      public void delete(final T persistentObject)
      {
          getCurrentSession().delete(persistentObject);
      }
  
      /*
       * (non-Javadoc)
       * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#findAll()
       */
      @Override
      public List&lt;T&gt; findAll()
      {
          return getCurrentSession().createQuery("from " + persistentClass.getName()).list();
      }
  
      /**
       * Finds a collection of entity objects which match to the example instance, minus any specified properties which should be excluded from the matching.
       * 
       * @param exampleInstance
       * @param excludeProperty
       * @return
       */
      public List&lt;T&gt; findByExample(final T exampleInstance,
                                   final String[] excludeProperty)
      {
          Criteria criteria = getCurrentSession().createCriteria(persistentClass);
          Example example = Example.create(exampleInstance);
          if (excludeProperty != null)
          {
              for (String exclude : excludeProperty)
              {
                  example.excludeProperty(exclude);
              }
          }
          criteria.add(example);
          return criteria.list();
      }
  
      /*
       * (non-Javadoc)
       * @see com.sun.cloud.lifecycle.core.persistence.dao.GenericDao#findById(java.io.Serializable)
       */
      @Override
      public T findById(final PK id)
      {
          return (T) getCurrentSession().load(persistentClass, id);
      }
  
      /**
       * Force this session to flush. Must be called at the end of a unit of work, before commiting the transaction and
       * closing the session (depending on flush-mode, Transaction.commit() calls this method).
       * 
       * Flushing is the process of synchronizing the underlying persistent store with persistable state held in memory.
       */
      public void flush()
      {
          getCurrentSession().flush();
      }
  
      /*
       * (non-Javadoc)
       * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#saveOrUpdate(gov.noaa.ncdc.cmb.persistence.entity.PersistentEntity)
       */
      @Override
      public T saveOrUpdate(final T entity)
      {
          try
          {
              entity.setUpdatedDate(new Date());
              getCurrentSession().saveOrUpdate(entity);
              return entity;
          }
          catch (Exception ex)
          {
              String errorMessage = "Failed to save the object.";
              log.error(errorMessage, ex);
              throw new RuntimeException(errorMessage, ex);
          }
      }
  
      /**
       * Setter for the persistentClass property.
       * 
       * @param persistentClass
       */
      public void setPersistentClass(final Class&lt;T&gt; persistentClass)
      {
          this.persistentClass = persistentClass;
      }
  
      /**
       * Property setter.
       * 
       * @param sessionFactory
       */
      public void setSessionFactory(final SessionFactory sessionFactory)
      {
          this.sessionFactory = sessionFactory;
      }
  
  }
  </code></pre>
  
  <p>My application gets the DAO from the application context:</p>
  
  <pre><code>// load the Spring application context, get the DAOs
  ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[] { "dailyAveragingApplicationContext.xml" });
  esrlDailyAvgDao = (EsrlDailyAvgDao) applicationContext.getBean("esrlDailyAvgDao");
  esrlObservationsDao = (EsrlObservationsDao) applicationContext.getBean("esrlObservationsDao");
  </code></pre>
  
  <p>And the exception is encountered when I try to save an entity:</p>
  
  <pre><code>esrlDailyAvgDao.saveOrUpdate(esrlDailyAvg);
  </code></pre>
  
  <p>The DAO class itself uses the Transactional annotation:</p>
  
  <pre><code>@Transactional
  public class EsrlDailyAvgDaoHibernateImpl
      extends GenericDaoHibernateImpl&lt;EsrlDailyAvg, Long&gt;
      implements EsrlDailyAvgDao
  </code></pre>
  
  <p>The exception stack trace looks like this:</p>
  
  <pre><code>SEVERE: Failed to save the object.
  org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
      at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
      at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:622)
      at gov.noaa.ncdc.cmb.persistence.dao.GenericDaoHibernateImpl.getCurrentSession(GenericDaoHibernateImpl.java:56)
      at gov.noaa.ncdc.cmb.persistence.dao.GenericDaoHibernateImpl.saveOrUpdate(GenericDaoHibernateImpl.java:187)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
      at $Proxy19.saveOrUpdate(Unknown Source)
      at gov.noaa.ncdc.cmb.esrl.ingest.EsrlDailyAvgProcessor.main(EsrlDailyAvgProcessor.java:469)
  </code></pre>