Announcement Announcement Module
Collapse
No announcement yet.
Session Handling Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Session Handling

    Hello!

    I am using hibernate 3.x with annotations and spring with annotation based transactions. I have a command line application and want to have a session with a transaction for ever call of my application (session-per-request pattern).

    After struggeling with HibernateTemplate (did open a session per database access) I read in some blogs and also in this forum that I should use plain hibernate with spring. So I changed to it and face different problems now, I receive this exception;

    Code:
    No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    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:544)
    My applicationContext.xml looks like this:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans ...>	
    	<!-- enable the configuration of transactional behavior based on annotations -->
    	<tx:annotation-driven/> 
    	       	
    	<!-- DataSource -->
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
            <property name="driverClassName"><value>org.postgresql.Driver</value></property>
            <property name="url"><value>jdbc:postgresql:test</value></property>
            <property name="username"><value>postgres</value></property>
            <property name="password"><value>postgres</value></property>
            <property name="suppressClose"><value>true</value></property>
        </bean>
    
    	<!-- Hibernate SessionFactory -->
    	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    		<property name="dataSource" ref="dataSource" />
    		<property name="configLocation" value="classpath:hibernate.cfg.xml" />
       </bean>
    
    	<!-- Transaktionsmanager -->
    	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    		<property name="sessionFactory" ref="sessionFactory" />
    	</bean>
    	
    	<!-- DAOs -->
    	<bean id="genericDao" class="at.gv.bmi.zmr_su.bf.data.persistence.hibernate.GenericDaoHibernateImpl" abstract="true">
    		<property name="sessionFactory" ref="sessionFactory" />
    	</bean >
    
    	<bean id="logImportDao" class="at.gv.bmi.zmr_su.bf.data.persistence.hibernate.LogImportDaoHibernateImpl" parent="genericDao" />
    ...
    My hibernate.cfg.xml looks like this:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
    		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    		... >
    <hibernate-configuration>
        <session-factory>
            <property name="hibernate.default_schema">public</property>
            <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
            
            <!-- for Batch-Inserts set the size to 100 entries -->
            <property name="hibernate.jdbc.batch_size">100</property>
            
            <!-- Disable the second level cache. This is necessary for batch operations. -->
            <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
            
            <!-- Echo all executed SQL to standard out -->
            <property name="show_sql">true</property>
            <property name="hibernate.format_sql">true</property> 
    
            <!-- Mappings -->
            <mapping class="at.gv.bmi.zmr_su.bf.data.logs.businessobject.LogImport" />
    ...
    Then I have one class with transactional behaviour:
    Code:
    public class LogDirectory
    {
    	(at)Transactional
        public void parseFile(String dirPath, String dirEntry, LogParser parser)
        	throws FileNotFoundException, IOException, LogParserException
        {
    Please replace (at) with the at sign.

    And I would expect that spring creates a session per default but there is no session. With the HibernateTemplate approach the template created a new session for every call. When I configured DAO with
    Code:
    	protected void initDao()
        {
            getHibernateTemplate().setAllowCreate(false);
        }
    I had the same behaviour like in the current solution. Can someone point me in the right direction?

    Thanks in advance, Christian

  • #2
    Use a plain hibernate sessionfactory don't use the HibernateDaoSupport/HibernateTemplate. Use the sessionFactory.getCurrentSession method and make sure you have a proper transaction configuration, also you don't follow the best practice to program to interfaces. So enable class proxying on the tx:annotation-driven element.

    Comment


    • #3
      Thanks for your answer.

      - I don't use HibernateDaoSupport/HibernateTemplate
      - I have a interface for my GenericDAO and extended interfaces for all DAOs and a GenericDAO implementation
      - In the DAO implementations I am using sessionFactory.getCurrentSession

      I wanted to implement DAOs based on plain Hibernate 3 API:
      hxxp://static.springframework.org/spring/docs/2.5.x/reference/orm.html#orm-hibernate-straight
      As stated here I wanted to inject the Spring SessionFactory with DI, is it possible to inject also a Hibernate SessionFactory? How can I avoid the HibernateUtils when not using the Spring Session Factory?

      I wanted to use annotations for transaction configuration, see hxxp://static.springframework.org/spring/docs/2.5.x/reference/transaction.html#transaction-declarative-annotations
      I thought when using annotations I can spare AOP.

      Does anyone know a full example on the web using Spring and native Hibernate?
      Thanks in advance, Christian
      Last edited by ChrLipp; Aug 5th, 2008, 02:23 AM.

      Comment


      • #4
        I wanted to inject the Spring SessionFactory with DI, is it possible to inject also a Hibernate SessionFactory? I assume I have to use HibernateUtils instead.
        There is no Spring SessionFactory, there is a SessionFactoryBean and I suggest you readup on how FactoryBeans work.

        @Transactional is as much of AOP as with the aop:config stuff, it is still implemented/being activated the same way.

        Code:
        public class LogDirectory
        {
        	(at)Transactional
            public void parseFile(String dirPath, String dirEntry, LogParser parser)
            	throws FileNotFoundException, IOException, LogParserException
            {
        You state that you use interfaces there is no interface here, no interface means class proxying which isn't enabled in your case.

        Comment


        • #5
          OK, I read about the SessionFactoryBean and implemented an interface for the object with the transatcional behaviour:

          Code:
          public class LogDirectoryImpl implements LogDirectory
          {
          	@Override
          	@Transactional
              public void parseFile(String dirPath, String dirEntry, LogParser parser)
              	throws FileNotFoundException, IOException, LogParserException
              {
          I still receive the same exception:
          Code:
          [2008-08-05 10:27:17,750]DEBUG main - org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(318) - Opening Hibernate Session
          [2008-08-05 10:27:17,781]DEBUG main - org.springframework.orm.hibernate3.SessionFactoryUtils.closeSession(774) - Closing Hibernate Session
          No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
          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:544)
          	at at.gv.bmi.zmr_su.bf.data.persistence.hibernate.GenericDaoHibernateImpl.find(GenericDaoHibernateImpl.java:89)
          	at at.gv.bmi.zmr_su.bf.data.logs.filesystem.LogDirectoryImpl.isFileAlreadyImported(LogDirectoryImpl.java:156)
          	at at.gv.bmi.zmr_su.bf.data.logs.filesystem.LogDirectoryImpl.parseFile(LogDirectoryImpl.java:131)
          	at at.gv.bmi.zmr_su.bf.data.logs.filesystem.LogDirectoryImpl.parseDirectory(LogDirectoryImpl.java:105)
          	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          	at java.lang.reflect.Method.invoke(Method.java:597)
          	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
          	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
          	at $Proxy20.parseDirectory(Unknown Source)
          	at at.gv.bmi.zmr_su.bf.LogEval.readDirectory(LogEval.java:155)
          	at at.gv.bmi.zmr_su.bf.LogEval.run(LogEval.java:125)
          	at at.gv.bmi.zmr_su.bf.LogEval.main(LogEval.java:54)
          [2008-08-05 10:27:17,796] INFO main - at.gv.bmi.zmr_su.bf.LogEval.main(67) - End application
          The old exception stack (without using an interface) was:
          Code:
          [2008-08-05 10:34:19,671]DEBUG main - org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(318) - Opening Hibernate Session
          [2008-08-05 10:34:19,703]DEBUG main - org.springframework.orm.hibernate3.SessionFactoryUtils.closeSession(774) - Closing Hibernate Session
          No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
          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:544)
          	at at.gv.bmi.zmr_su.bf.data.persistence.hibernate.GenericDaoHibernateImpl.find(GenericDaoHibernateImpl.java:89)
          	at at.gv.bmi.zmr_su.bf.data.logs.filesystem.LogDirectoryImpl.isFileAlreadyImported(LogDirectoryImpl.java:156)
          	at at.gv.bmi.zmr_su.bf.data.logs.filesystem.LogDirectoryImpl.parseFile(LogDirectoryImpl.java:131)
          	at at.gv.bmi.zmr_su.bf.data.logs.filesystem.LogDirectoryImpl.parseDirectory(LogDirectoryImpl.java:105)
          	at at.gv.bmi.zmr_su.bf.data.logs.filesystem.LogDirectoryImpl$$FastClassByCGLIB$$3428d3bf.invoke(<generated>)
          	at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
          	at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:628)
          	at at.gv.bmi.zmr_su.bf.data.logs.filesystem.LogDirectoryImpl$$EnhancerByCGLIB$$eedb076c.parseDirectory(<generated>)
          	at at.gv.bmi.zmr_su.bf.LogEval.readDirectory(LogEval.java:156)
          	at at.gv.bmi.zmr_su.bf.LogEval.run(LogEval.java:126)
          	at at.gv.bmi.zmr_su.bf.LogEval.main(LogEval.java:55)
          [2008-08-05 10:34:19,718] INFO main - at.gv.bmi.zmr_su.bf.LogEval.main(68) - End application
          So it definitly looks better, but still there is no currentSession.
          Christian

          Comment


          • #6
            Your transactional method is being called internally, so no interception, no transaction. Your parseDirectory method should be transactional.

            Comment


            • #7
              In the class org.springframework.orm.hibernate3.SessionFactoryU tils in the function doGetSession Spring thinks that no Spring transaction management is active:

              Code:
              		// Use same Session for further Hibernate actions within the transaction.
              		// Thread object will get removed by synchronization at transaction completion.
              		if (TransactionSynchronizationManager.isSynchronizationActive()) {
              			// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
              ...
              		}
              		else {
              			// No Spring transaction management active -> try JTA transaction synchronization.
              			registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
              		}
              
              		// Check whether we are allowed to return the Session.
              		if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {
              			closeSession(session);
              			throw new IllegalStateException("No Hibernate Session bound to thread, " +
              			    "and configuration does not allow creation of non-transactional one here");
              		}
              So the question is: what is wrong on my transaction configuration?
              Christian

              Comment


              • #8
                Sorry, posted twice.

                Yes now it works. Oringinally parseDirectory was transactional, but I removed it because I run out of memory. I have to solve this on another way.

                Thanks very much for your help!
                Christian

                Comment


                • #9
                  If you want the parseFile method to be transactional I suggest a TransactionTemplate and wrap the call to the parseFile method in there. That way each file is in a seperate transaction. If you really want to have a transaction around the directory you will have to make the parseDirectory method transactional.

                  Comment

                  Working...
                  X