Announcement Announcement Module
Collapse
No announcement yet.
HibernateTransaction and IllegalTransactionState Exception. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • HibernateTransaction and IllegalTransactionState Exception.

    Hi,

    I am trying to write a base class for integration testing. Unfortunately I can't extend the AbstractTransactionalSpringContextTest because I need to extend MockStrutsTestCase. So I decided to include the functionality in a base class which is essentially the same as AbstractTransactionalSpringContextTest.

    I want to be able to provide a 'hibernateTemplate' to specific implementations to use for setup of Integration testing. In this manner I can setup the database state, run the test case and then roll-back the transaction within the base class.

    I keep getting an IllegalTransactionStateException with the message
    Pre-bound JDBC connection found - HibernateTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single HibernateTransactionManager for all transactions on a single DataSource, no matter whether Hibernate or JDBC access.
    I've looked at the code and this exception is called if
    if (getDataSource() != null && TransactionSynchronizationManager.hasResource(getD ataSource())) {
    I am very confused by this error message and I was hoping someone could tell me what I am doing wrong. My appContext is
    Code:
    	<!-- Local DataSource that works in any environment -->
    	<bean id="myDataSource" name="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    		<property name="driverClassName"><value>$&#123;jdbc.driverClassName&#125;</value></property>
    		<property name="url"><value>$&#123;jdbc.url&#125;</value></property>
    		<property name="username"><value>$&#123;jdbc.username&#125;</value></property>
    		<property name="password"><value>$&#123;jdbc.password&#125;</value></property>
    	</bean>
    	<bean id="mySessionFactory"
    		class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
    		<property name="dataSource">
    			<ref bean="myDataSource"/>
    		</property>
    		<property name="mappingResources">
    			<list>
    				<value>
    					program.hbm.xml</value>
    				<value>
    					budgetallocation.hbm.xml</value>
    				<value>
    					bonusallocation.hbm.xml</value>
    				<value>
    					programguideline.hbm.xml</value>
    				<value>
    					notification.hbm.xml</value>
    			</list>
    		</property>
    		<property name="hibernateProperties">
    			<props>
    				<prop key="hibernate.dialect">$&#123;hibernate.dialect&#125;</prop>
    				<prop key="hibernate.query.substitutions">true=1 false=0</prop>
    				<prop key="hibernate.show_sql">true</prop>
    			</props>
    		</property>
    	</bean>
    	
    	<bean id="transactionManager"
    		class="org.springframework.orm.hibernate.HibernateTransactionManager">
    		<property name="sessionFactory">
    			<ref local="mySessionFactory"/>
    		</property>
    	</bean>
    	
    		
    	<bean id="hibernateTemplate"
    		class="org.springframework.orm.hibernate.HibernateTemplate"
    		>
    		<property name="sessionFactory">
    			<ref local="mySessionFactory"/>
    		</property>
    	</bean>
    I am using Declared Transactions using TransactionProxy when wiring up my real transactions.

    Code:
    	<bean id="programInfo"
    	class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager">
    			<ref bean="transactionManager"/>
    		</property>
    		<property name="target">
    			<bean id="programInfoTarget"
    				class="ProgramInfoDAO">
    				<property name="sessionFactory">
    					<ref bean="mySessionFactory"/>
    				</property>
    			</bean>
    		</property>
    		<property name="transactionAttributes">
    			<props>
    				<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
    				<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
    				<prop key="load*">PROPAGATION_NESTED,readOnly</prop>
    				<prop key="store*">PROPAGATION_REQUIRED</prop>
    			</props>
    		</property>
    	</bean>
    My BaseTestClass does the following:

    Code:
    		this.transactionStatus = transactionManager.getTransaction&#40;new DefaultTransactionDefinition&#40;&#41;&#41;;
    		&#40;&#40;AbstractPlatformTransactionManager&#41;transactionManager&#41;.setNestedTransactionAllowed&#40;true&#41;;
    
    		hibernateTemplate = &#40;HibernateTemplate&#41;applicationContext.getBean&#40;"hibernateTemplate" &#41;;
    		logger.info&#40;"Began transaction&#58; transaction manager=&#91;" + this.transactionManager +
    		    "&#93;; defaultCommit=" + this.complete&#41;;
    Since HibernateTransactionManager is managing everything, I thought everything work ok. Can someone help?

    Take Care
    Jason

  • #2
    Solved.. I think.

    For the benefit of those who may be interested I've managed to narrow the problem down to how MockStrutsTestCase works. I forgot that Struts will initialize it's own copy of ApplicationContext.

    This means a whole new set of singletons. Transaction management uses ThreadLocal to store the context. The new singletons are not aware of this and try to initialize a new Transaction manager. The hibernate sees the old transaction state on ThreadLocal and raises an exception.

    This looks like it's the reason for getting the error. Can somebody more adept at Spring confirm this theory?

    Can transaction managers (specfically Hibernate) exist accross multiple BeanFactories/ApplicationContexts?

    Take Care
    Jason

    Comment


    • #3
      Can transaction managers (specfically Hibernate) exist accross multiple BeanFactories/ApplicationContexts?
      I think not but I might be mistaken. However, I think you are trying to solve the wrong problem .
      Try to get a hold of the TransactionManager/AppContext used by MockStrutsTestCase especially if you are extending it. It appears to me that you are thinking against the TestCase...

      Comment

      Working...
      X