title: Could not retrieve pre-bound Hibernate session - Could not obtain transaction-synchronized Session for current thread
body: <p>I am creating a web application with spring-mvc, spring-security, spring-core, and hibernate.</p>
  
  <p>But I always get this non-error from hibernate session factory.</p>
  
  <p>It is actually throwing HibernateException, but I see on the log it is in debug level, and my application actually continues its execution with no problem.</p>
  
  <p>But I am very curious to understand the reason of the exception raised.</p>
  
  <p>The log shows the following lines.</p>
  
  <pre><code>2016-08-29 13:34:55,310 DEBUG [sg.com.diamond.express.base.dao.impl.HibernateDAOImpl].[doExecute]([328]) [http-nio-8888-exec-4] - Could not retrieve pre-bound Hibernate session
  org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
      at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
      at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
      at org.springframework.orm.hibernate4.HibernateTemplate.doExecute(HibernateTemplate.java:325)
      at org.springframework.orm.hibernate4.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:308)
      at org.springframework.orm.hibernate4.HibernateTemplate.get(HibernateTemplate.java:418)
      at org.springframework.orm.hibernate4.HibernateTemplate.get(HibernateTemplate.java:411)
      at sg.com.diamond.express.base.dao.impl.BaseHibernateDaoImpl.findById(BaseHibernateDaoImpl.java:160)
      at sg.com.diamond.express.webadmin.service.impl.ClientProfileServiceImpl.searchByName(ClientProfileServiceImpl.java:48)
      at sg.com.diamond.express.webadmin.controller.impl.ClientController.home(ClientController.java:48)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:497)
      at org.springframework.web.servlet.mvc.multiaction.MultiActionController.invokeNamedMethod(MultiActionController.java:472)
      at org.springframework.web.servlet.mvc.multiaction.MultiActionController.handleRequestInternal(MultiActionController.java:409)
      at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:146)
      at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50)
      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
      at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
      at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
  </code></pre>
  
  <p>This is the code that I have.</p>
  
  <p><strong>DAO Level</strong></p>
  
  <p>This is an abstraction level that I created to minimise the number of boiler-plate codes for DAO, no need to implement the basic c-r-u-d.</p>
  
  <p><em>BaseDAO Interface</em></p>
  
  <pre><code>public interface BaseDAO &lt;ID extends Serializable, M extends BaseModel&gt; {
      Session getCurrentSession();
  
      M findById(ID id) throws DAOException;
      List&lt;M&gt; findByCriteria(M criteria) throws DAOException;
      List&lt;M&gt; listAll() throws DAOException;
      ID saveObject(M object) throws DAOException;
      void saveOrUpdate(M object) throws DAOException;
      Query createQuery(String hql) throws DAOException;
      Query createSQLQuery(String sql) throws DAOException;
      Criteria createCriteria(Class clazz) throws DAOException;
      List&lt;M&gt; runQuery(Query query) throws DAOException;
      List&lt;M&gt; runQuery(String sql) throws DAOException;
  }
  </code></pre>
  
  <p><em>BaseDAO Implementation</em></p>
  
  <pre><code>public class BaseHibernateDaoImpl&lt;ID extends Serializable, M extends BaseModel&gt; extends HibernateTemplate implements BaseDAO&lt;ID, M&gt; {
  
      protected Class&lt;M&gt; modelClass;
  
      @Override
      public Session getCurrentSession() {
          return this.getSessionFactory().getCurrentSession();
      }
  
      public ID saveObject(M object) throws DAOException {
          try {
              object.setCreator("Batch");
              object.setCreatedAt(new Timestamp(new Date().getTime()));
              object.setUpdater("Batch");
              object.setUpdatedAt(new Timestamp(new Date().getTime()));
              return (ID) super.save(object);
          } catch (Exception e) {
              logger.error(ExceptionUtil.getStackTraces(e), e);
              throw new DAOException(e);
          }
      }
  
      /** all other implementation methods **/
  </code></pre>
  
  <p><strong>Spring XML Configuration</strong></p>
  
  <pre><code>    &lt;!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          | Data Source Configuration
          |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  --&gt;
      &lt;bean id="targetDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
          &lt;property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /&gt;
          &lt;property name="url" value="jdbc:oracle:thin:@192.168.170.36:1521:EXPT2" /&gt;
          &lt;property name="username" value="EXP_USER" /&gt;
          &lt;property name="password" value="passw0rd" /&gt;
      &lt;/bean&gt;
      &lt;bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"&gt;
          &lt;property name="targetDataSource" ref="targetDataSource"/&gt;
      &lt;/bean&gt;
  
      &lt;!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          | Hibernate abstract session factory parent
          |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  --&gt;
      &lt;bean id="baseSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" abstract="true"&gt;
          &lt;property name="hibernateProperties"&gt;
              &lt;props&gt;
                  &lt;prop key="hibernate.show_sql"&gt;true&lt;/prop&gt;
                  &lt;prop key="hibernate.format_sql"&gt;true&lt;/prop&gt;
                  &lt;prop key="hibernate.jdbc.batch_size"&gt;10&lt;/prop&gt;
              &lt;/props&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          | Hibernate entity configurations
          |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  --&gt;
      &lt;bean id="expressSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" parent="baseSessionFactory"&gt;
          &lt;property name="hibernateProperties"&gt;
              &lt;props merge="true"&gt;
                  &lt;prop key="hibernate.dialect"&gt;org.hibernate.dialect.Oracle10gDialect&lt;/prop&gt;
              &lt;/props&gt;
          &lt;/property&gt;
          &lt;property name="dataSource" ref="dataSource"/&gt;
          &lt;property name="mappingLocations" value="classpath*:hbm/express/*.hbm.xml"/&gt;
      &lt;/bean&gt;
  
      &lt;!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          | Transaction Management
          |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  --&gt;
      &lt;bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"&gt;
          &lt;property name="sessionFactory" ref="expressSessionFactory"/&gt;
      &lt;/bean&gt;
  
      &lt;aop:config&gt;
          &lt;aop:pointcut id="servicePointcut" expression="execution(* sg.com.diamond.express.webadmin.service.*.*.*(..))"/&gt;
          &lt;aop:advisor id="serviceTx" advice-ref="txAdvice" pointcut-ref="servicePointcut"/&gt;
      &lt;/aop:config&gt;
  
      &lt;tx:advice id="txAdvice" transaction-manager="txManager"&gt;
          &lt;tx:attributes&gt;
              &lt;tx:method name="get*"      propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" /&gt;
              &lt;tx:method name="search*"   propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" /&gt;
              &lt;tx:method name="list*"     propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" /&gt;
              &lt;tx:method name="is*"       propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" /&gt;
              &lt;tx:method name="*"         propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="false"/&gt;
          &lt;/tx:attributes&gt;
      &lt;/tx:advice&gt;
  
      &lt;!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          | Base Dao Definitions
          |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  --&gt;
      &lt;bean id="baseExpressDAO" class="sg.com.diamond.express.base.dao.impl.BaseHibernateDaoImpl" abstract="true"&gt;
          &lt;property name="sessionFactory" ref="expressSessionFactory"/&gt;
      &lt;/bean&gt;
  </code></pre>
  
  <p><strong>Question</strong></p>
  
  <p>Why does the error happen? and it doesn't break my app, the log level is DEBUG, not ERROR, my app is able to continue properly after that.</p>
  
  <p>Is my configuration correct?</p>
  
  <p><strong>Note</strong></p>
  
  <p>Don't mind the full-xml config, for some reason, I need to use full-xml and none-annotations.</p>
  
  <p><strong>Answer</strong></p>
  
  <p>After mucking around with the aop pointcut expression, I noticed that on a simple batch program that I wrote, where I only have 1 context, I do not have this problem.</p>
  
  <p>This leads me to the answer.</p>
  
  <p>I originally structured my spring xml config as multiple layers. </p>
  
  <ul>
  <li>At the top level, at the application context, I declare all the data sources, and the transaction managements.</li>
  <li>At the second level, the servlet level, each servlet has its own context. At this level, I put all the controller-service-dao configurations.</li>
  <li>There should be multiple of this "second-level" context, for example, 1 servlet context should handle all RESTful services, where another one handles web-ui.</li>
  </ul>
  
  <p>I've structured it assuming it will take on the transaction management setup in the application context. Sort of like "all servlet context should be able to use the same data-source and transaction-management the same way"</p>
  
  <p>But as it turns out, it doesn't.</p>
  
  <p>When I moved the transaction management piece, including the data-source config, into the servlet context configuration, it all works fine, and the service is now wrapped correctly under transaction.</p>
  
  <p>Thanks.</p>