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

  • no rollback

    Hello,
    Being a newbie to Spring and
    for gaining some experience with the declarative transaction management, I started with the recommended pattern:
    transactional service calls several DAO methods. My service calls two
    DAO methods.
    Although I generate a runtime-exception in the second method there is no rollback of the previous insert.
    I hope, someone finds a "stupid" error.

    Here is the code:

    Code:
    public class SimpleDataDao extends HibernateDaoSupport {
    
        public SimpleData getSimpleData(Integer simpleDataId) {
    	    return (SimpleData) getHibernateTemplate().get(SimpleData.class,
    		    simpleDataId);
        }
    
        public Integer saveSimpleData(SimpleData simpleData) {
    	 Integer ret = (Integer) getHibernateTemplate().save(simpleData);
    	 return ret;
        }
        
        public void failingMethod() {
    	 if(true){
                 throw new RuntimeException("testing");
             }
        }
    }
    
    -----------------------------------------------------
    
    @Transactional  
    public class SimpleDataService  {
        private SimpleDataDao simpleDataDao;
    
        public void complexOp() {
    	SimpleData sp = new SimpleData();
    	sp.setName("dummy1");
    	simpleDataDao.saveSimpleData(sp);
    	simpleDataDao.failingMethod();
        }
      
        public SimpleDataDao getSimpleDataDao() {
            return simpleDataDao;
        }
    
        public void setSimpleDataDao(SimpleDataDao simpleDataDao) {
            this.simpleDataDao = simpleDataDao;
        }
    }
    
    -----------------------------------------------
    public class MainToTest {
    
        public static void main(String[] args) {
    	try {
    	    ClassPathResource res = new ClassPathResource("applicationContext.xml");
    	    XmlBeanFactory factory = new XmlBeanFactory(res);
    	    SimpleDataService service = (SimpleDataService)factory.getBean("simpleDataService");
    	 
    	    service.complexOp();
    	} catch (Exception e) {
    	    System.out.println(e);
    	}
        }
    }

    Here are the configurations:
    applicationContext.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           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.0.xsd"
           default-autowire="byType">
    
    	<import resource="databaseContext.xml"/>
    	<import resource="transactionContext.xml"/>
    
        <bean id="simpleDataDao" class="x.y.dao.SimpleDataDao">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
    
    	<bean name="simpleDataService" class="x.y.service.SimpleDataService">
    		<property name="simpleDataDao" ref="simpleDataDao"/>
        </bean>
    </beans>

    databaseContext.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:jee="http://www.springframework.org/schema/jee"
    	xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd"
    	default-autowire="byType">
    
    	<!-- Database -->
    	<bean id="sessionFactory"
    		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    		<property name="dataSource" ref="dataSource" />
    		<property name="annotatedClasses">
    			<list>
    				<value>x.y.domain.SimpleData</value>
    			</list>
    		</property>
    		<property name="hibernateProperties">
    			<props>
    				<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
    				<prop key="hibernate.hbm2ddl.auto">create</prop>
    				<prop key="hibernate.jdbc.batch_size">0</prop>
    				<prop key="hibernate.show_sql">true</prop>
    				<prop key="hibernate.format_sql">true</prop>
    				<prop key="hibernate.cache.use_second_level_cache">
    					false
    				</prop>
    				<!--prop key="hibernate.cache.use_second_level_cache">true</prop-->
    				<prop key="hibernate.cache.use_query_cache">false</prop>
    				<prop key="hibernate.autocommit">false</prop>
    				
    				<!--prop key="hibernate.cache.use_query_cache">true</prop-->
    				<prop key="hibernate.cache.provider_class">
    					net.sf.ehcache.hibernate.SingletonEhCacheProvider
    				</prop>
    			</props>
    		</property>
    	</bean>
    	 
    	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    		<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
    		<property name="jdbcUrl" value="jdbc:oracle:thin:@kfcorcl10:1521:fact" />
    		<property name="user" value="TS" />
    		<property name="password" value="TS" />
    	</bean>
    </beans>
    transactionContext.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans default-init-method="init" default-destroy-method="destroy" 
    	xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="
    	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
    	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
    	   
         
        <bean id="transactionManager"
              class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"/>
            <property name="dataSource" ref="dataSource"/> 
        </bean>
        
        <tx:annotation-driven transaction-manager="transactionManager"/>
    </beans>

  • #2
    Try not catching the exception in your test method.

    Bob

    Comment


    • #3
      I tried both versions (with and without catching). Behavior is the same (i.e. no rollback)

      Comment


      • #4
        Hello,
        Here are the log statements. Perhaps there one could find an explanation
        for the missing rollback

        Code:
        2009-03-23 10:10:14,184 DEBUG [com.mchange.v2.resourcepool.BasicResourcePool] - trace com.mchange.v2.resourcepool.BasicResourcePool@ef894ce [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@3c6833f2)
        2009-03-23 10:10:14,186 DEBUG [org.hibernate.tool.hbm2ddl.SchemaExport] - 
            drop table SimpleData
        2009-03-23 10:10:14,189 DEBUG [org.hibernate.tool.hbm2ddl.SchemaExport] - 
            drop sequence hibernate_sequence
        2009-03-23 10:10:14,190 DEBUG [org.hibernate.tool.hbm2ddl.SchemaExport] - 
            create table SimpleData (
                id int4 not null,
                commentary varchar(255),
                name varchar(255),
                primary key (id)
            )
        2009-03-23 10:10:14,247 DEBUG [org.hibernate.tool.hbm2ddl.SchemaExport] - 
            create sequence hibernate_sequence
        2009-03-23 10:10:14,249 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] - schema export complete
        2009-03-23 10:10:14,249 DEBUG [com.mchange.v2.resourcepool.BasicResourcePool] - trace com.mchange.v2.resourcepool.BasicResourcePool@ef894ce [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@3c6833f2)
        2009-03-23 10:10:14,249 DEBUG [org.hibernate.impl.SessionFactoryImpl] - Checking 0 named HQL queries
        2009-03-23 10:10:14,249 DEBUG [org.hibernate.impl.SessionFactoryImpl] - Checking 0 named SQL queries
        2009-03-23 10:10:14,250 DEBUG [org.springframework.beans.factory.xml.XmlBeanFactory] - Finished creating instance of bean 'sessionFactory'
        2009-03-23 10:10:14,250 DEBUG [org.springframework.beans.factory.xml.XmlBeanFactory] - Finished creating instance of bean 'sessionFactory'
        2009-03-23 10:10:14,256 DEBUG [org.springframework.beans.factory.xml.XmlBeanFactory] - Invoking afterPropertiesSet() on bean with name 'simpleDataDao'
        2009-03-23 10:10:14,256 DEBUG [org.springframework.beans.factory.xml.XmlBeanFactory] - Invoking afterPropertiesSet() on bean with name 'simpleDataDao'
        2009-03-23 10:10:14,256 DEBUG [org.springframework.beans.factory.xml.XmlBeanFactory] - Finished creating instance of bean 'simpleDataDao'
        2009-03-23 10:10:14,256 DEBUG [org.springframework.beans.factory.xml.XmlBeanFactory] - Finished creating instance of bean 'simpleDataDao'
        2009-03-23 10:10:14,257 DEBUG [org.springframework.beans.factory.xml.XmlBeanFactory] - Finished creating instance of bean 'simpleDataService'
        2009-03-23 10:10:14,257 DEBUG [org.springframework.beans.factory.xml.XmlBeanFactory] - Finished creating instance of bean 'simpleDataService'
        2009-03-23 10:10:14,264 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Opening Hibernate Session
        2009-03-23 10:10:14,264 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Opening Hibernate Session
        2009-03-23 10:10:14,284 DEBUG [org.hibernate.impl.SessionImpl] - opened session at timestamp: 12377994142
        2009-03-23 10:10:14,286 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
        2009-03-23 10:10:14,286 DEBUG [org.hibernate.jdbc.ConnectionManager] - opening JDBC connection
        2009-03-23 10:10:14,286 DEBUG [com.mchange.v2.resourcepool.BasicResourcePool] - trace com.mchange.v2.resourcepool.BasicResourcePool@ef894ce [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@3c6833f2)
        2009-03-23 10:10:14,287 DEBUG [org.hibernate.SQL] - 
            select
                nextval ('hibernate_sequence')
        Hibernate: 
            select
                nextval ('hibernate_sequence')
        2009-03-23 10:10:14,295 DEBUG [org.hibernate.id.SequenceGenerator] - Sequence identifier generated: 1
        2009-03-23 10:10:14,295 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
        2009-03-23 10:10:14,296 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - generated identifier: 1, using strategy: org.hibernate.id.SequenceGenerator
        2009-03-23 10:10:14,303 DEBUG [org.springframework.orm.hibernate3.HibernateTemplate] - Eagerly flushing Hibernate session
        2009-03-23 10:10:14,303 DEBUG [org.springframework.orm.hibernate3.HibernateTemplate] - Eagerly flushing Hibernate session
        2009-03-23 10:10:14,303 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - processing flush-time cascades
        2009-03-23 10:10:14,303 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - dirty checking collections
        2009-03-23 10:10:14,304 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushed: 1 insertions, 0 updates, 0 deletions to 1 objects
        2009-03-23 10:10:14,304 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
        2009-03-23 10:10:14,305 DEBUG [org.hibernate.pretty.Printer] - listing entities:
        2009-03-23 10:10:14,305 DEBUG [org.hibernate.pretty.Printer] - x.y.domain.SimpleData{id=1, commentary=null, name=dummy1}
        2009-03-23 10:10:14,307 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
        2009-03-23 10:10:14,307 DEBUG [org.hibernate.SQL] - 
            insert 
            into
                SimpleData
                (commentary, name, id) 
            values
                (?, ?, ?)
        Hibernate: 
            insert 
            into
                SimpleData
                (commentary, name, id) 
            values
                (?, ?, ?)
        2009-03-23 10:10:14,308 DEBUG [org.hibernate.jdbc.AbstractBatcher] - Executing batch size: 1
        2009-03-23 10:10:14,311 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
        2009-03-23 10:10:14,311 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session
        2009-03-23 10:10:14,311 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session
        2009-03-23 10:10:14,311 DEBUG [org.hibernate.jdbc.ConnectionManager] - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
        2009-03-23 10:10:14,312 DEBUG [com.mchange.v2.resourcepool.BasicResourcePool] - trace com.mchange.v2.resourcepool.BasicResourcePool@ef894ce [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@3c6833f2)
        2009-03-23 10:10:14,312 DEBUG [org.hibernate.jdbc.ConnectionManager] - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
        java.lang.RuntimeException: testing

        Comment


        • #5
          About your application, you can read the reference :

          "The Spring team's recommendation is that you only annotate concrete classes with the @Transactional
          annotation, as opposed to annotating interfaces. You certainly can place the @Transactional annotation on an
          interface (or an interface method), but this will only work as you would expect it to if you are using
          interface-based proxies. The fact that annotations are not inherited means that if you are using class-based
          proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj") then the transaction
          settings will not be recognised by the proxying/weaving infrastructure and the object will not be wrapped in a
          transactional proxy (which would be decidedly bad). So please do take the Spring team's advice and only
          annotate concrete classes (and the methods of concrete classes) with the @Transactional annotation.
          Note: In proxy mode (which is the default), only 'external' method calls coming in through the proxy will be
          intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method
          of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with
          @Transactional!
          Consider the use of AspectJ mode (see below) if you expect self-invocations to be wrapped with transactions as
          well. In this case, there won't be a proxy in the first place; instead, the target class will be 'weaved' (i.e. its byte
          code will be modified) in order to turn @Transactional into runtime behavior on any kind of method."

          Comment


          • #6
            Do I have any self-invocations? Sorry, I cannot see my mistake.

            Comment


            • #7
              Ok, now it works.
              One has to use ApplictationContext to get the beans (and use interfaces to get Proxies).

              Comment


              • #8
                Hi,

                I have been trying to do the same thing as you have done. But, for me it still doesn't work. Can you please post the code which helped you make it work.

                Thanks and Regards
                Ritesh

                Comment


                • #9
                  Here is the version that works.

                  applicationContext.xml (this time I put it all in one file):
                  Code:
                  <?xml version="1.0" encoding="UTF-8"?>
                  <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" xmlns:tx="http://www.springframework.org/schema/tx"
                  xsi:schemaLocation="
                   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
                  
                  	 
                      <bean id="simpleDataDao" class="x.y.dao.SimpleDataDao">
                          <property name="sessionFactory" ref="sessionFactory"/>
                      </bean>
                  
                  	<bean name="simpleDataService" class="x.y.service.SimpleDataService">
                  		<property name="simpleDataDao" ref="simpleDataDao"/>
                      </bean>
                      
                      <bean name="overService" class="x.y.service.Overservice">
                  		<property name="sds" ref="simpleDataService"/>
                      </bean>
                      
                      
                      <!-- database settings -->
                      
                      	<bean id="sessionFactory"
                  		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
                  		<property name="dataSource" ref="dataSource" />
                  		<property name="annotatedClasses">
                  			<list>
                  				<value>x.y.domain.SimpleData</value>
                  			</list>
                  		</property>
                  		<property name="hibernateProperties">
                  			<props>
                  				<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> 
                  				<prop key="hibernate.hbm2ddl.auto">create</prop>
                  				<prop key="hibernate.show_sql">true</prop>
                  				<prop key="hibernate.format_sql">true</prop>
                  			</props>
                  		</property>
                  	</bean>
                  	 
                  	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
                  		<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
                  		<property name="jdbcUrl" value="jdbc:oracle:thin:@kfcorcl10:1521:fact" />
                  		<property name="user" value="TS" />
                  		<property name="password" value="TS" />
                  	</bean>
                  	
                  	<!--  transaction settings  -->
                  	<tx:annotation-driven transaction-manager="transactionManager" />  
                  	 
                      
                      <bean id="transactionManager"
                            class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                          <property name="sessionFactory" ref="sessionFactory"/>
                      </bean>
                  </beans>

                  Use interfaces for your classes and use ApplicationContext instead of
                  Beanfactory:

                  Code:
                  package x.y.dao;
                  
                  import x.y.domain.SimpleData;
                  
                   
                  public interface ISimpleDataDao {
                      
                      public Integer saveSimpleData(SimpleData simpleData);
                      public void failingMethod();
                  }
                  
                  ----------------------------------------------------------------
                  
                  package x.y.dao;
                  
                  import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
                  
                  import x.y.domain.SimpleData;
                  
                   
                  public class SimpleDataDao extends HibernateDaoSupport implements ISimpleDataDao{
                  
                      public SimpleData getSimpleData(Integer simpleDataId) {
                  	    return (SimpleData) getHibernateTemplate().get(SimpleData.class,
                  		    simpleDataId);
                      }
                  
                      public Integer saveSimpleData(SimpleData simpleData) {
                  	 Integer ret = (Integer) getHibernateTemplate().save(simpleData);
                  	 return ret;
                      }
                      
                      public void failingMethod() {
                  	 if(true){
                               throw new RuntimeException("testing");
                           }
                      }
                  }
                  
                  --------------------------------------------------------------------
                  package x.y.domain;
                  
                  import javax.persistence.Entity;
                  import javax.persistence.GeneratedValue;
                  import javax.persistence.GenerationType;
                  import javax.persistence.Id;
                  import javax.persistence.Table;
                  
                   
                  @Entity
                  @Table(name = "SimpleData")
                  public class SimpleData {
                      private Integer id;
                      private String name;
                      private String commentary;
                      
                      
                      /**
                       * Default-Konstruktor fuer Hibernate.
                       */
                      public SimpleData() {
                      }
                      
                      @Id
                      @GeneratedValue(strategy = GenerationType.AUTO)
                      public Integer getId() {
                          return id;
                      }
                  
                      public void setId(Integer anId) {
                          this.id = anId;
                      }
                  
                      /**
                       * @return the name
                       */
                      public String getName() {
                          return name;
                      }
                  
                      /**
                       * @param name the name to set
                       */
                      public void setName(String name) {
                          this.name = name;
                      }
                  
                      /**
                       * @return the commentary
                       */
                      public String getCommentary() {
                          return commentary;
                      }
                  
                      /**
                       * @param commentary the commentary to set
                       */
                      public void setCommentary(String commentary) {
                          this.commentary = commentary;
                      }
                  }
                  
                  --------------------------------------------------------------------
                  
                  package x.y.service;
                  
                   
                  public interface ISimpleDataService {
                      public void complexOp();
                  }
                  
                  ---------------------------------------------------------------------
                  
                  package x.y.service;
                  
                  import org.springframework.transaction.annotation.Transactional;
                  
                  import x.y.dao.ISimpleDataDao;
                  import x.y.domain.SimpleData;
                  
                   
                  public class SimpleDataService implements ISimpleDataService{
                      private ISimpleDataDao simpleDataDao;
                  
                      
                      @Transactional
                      public void complexOp() {
                  	SimpleData sp = new SimpleData();
                  	sp.setName("dummy1");
                  	simpleDataDao.saveSimpleData(sp);
                  	simpleDataDao.failingMethod();
                      }
                    
                      public void setSimpleDataDao(ISimpleDataDao simpleDataDao) {
                          this.simpleDataDao = simpleDataDao;
                      }
                  }
                  
                  ----------------------------------------------------------------
                  
                  package x.y.test;
                  
                  import org.springframework.context.ApplicationContext;
                  import org.springframework.context.support.ClassPathXmlApplicationContext;
                  
                  import x.y.service.ISimpleDataService;
                  
                   
                  public class MainToTest {
                  
                      public static void main(String[] args) {
                  	try {
                  	    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
                  	    ISimpleDataService s = (ISimpleDataService)ctx.getBean("simpleDataService");
                  	    s.complexOp();
                  	} catch (Exception e) {
                  	    System.out.println(e);
                  	}
                      }
                  }

                  Comment


                  • #10
                    Hi,

                    Thanks for posting the code. It was immensely helpful. My JUnit test case now works fine and it is able to rollback on exception.

                    I have another weird problem though. When I use the same code in my application, the logs now say that the rollback was done. But when I check my database, the inserted record is still present. This is different from what I saw in my JUnit Test Case. In the JUnit Test case the record was not present which is what is expected.

                    I am using Spring 2.5.6, Hibernate 3.3.1GA, Oracle 10g and Tomcat 6.0.18.

                    Comment


                    • #11
                      First of all, I dare to ask a simple question: did you hit the reload/refresh button of your database tool?


                      Otherwise, please post your code (JUNIT-Test and application).

                      Comment


                      • #12
                        Hi, First of all, apologies for a late response. I was out sick.

                        Here is the scenario I was testing. I have two tables. User and Roles. Whenver a new user is created, one new record is inserted into the User table and one into the role table. (A user has a role (1:1)).

                        Both the insert operations are called one afrer the another in the same method.

                        JUnit Test Case:
                        I throw an exception on the insert role method in my Junit test case. It works fine. When I refresh the database tool, I dont a user object inserted into the database.

                        Application Environment:

                        I use the same code, same application context xml file and same hibernate properties. But when I refresh, I see no records are inserted to role table, which is as expected, but a new record is inserted into user table. This means, the rolback is not happening.

                        Code:
                        @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
                        public boolean createUser(Object userObject) {
                                try{
                                    insertUser(userObject);
                                    insertRole(userObject);
                                catch(Exception e) {
                                    throw e;
                                }
                        }
                        The insertUser and insertRole methods have the transactional annotation as well as defined below:
                        Code:
                        @Transactional(propagation=Propagation.REQUIRED)
                        public void insertRole(Object object) throws Exception{
                        .....
                        }
                        The logs are:
                        Code:
                        2009-04-03 13:11:42,656 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] - <Could not synchronize database state with session>
                        org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
                        	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
                        	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
                        	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
                        	at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:114)
                        	at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)
                        	at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244)
                        	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2252)
                        	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2688)
                        	at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
                        	at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
                        	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
                        	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
                        	at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
                        	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
                        	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
                        	at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:135)
                        	at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:72)
                        	at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:905)
                        	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:715)
                        	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
                        	at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
                        	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
                        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
                        	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
                        	at $Proxy6.createUser(Unknown Source)
                        	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:307)
                        	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)

                        Comment


                        • #13
                          Any ideas any body. I really need some help here. I have been struggling for past couple of days to solve this issue. I have tried several variations of different configurations and nothing seems to work.

                          Any help would be really appreciated.

                          Thanks..

                          Comment


                          • #14
                            Maybe the corresponding class XY of the method createUser was not instantiated via an Interface, i.e.

                            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext .xml");
                            IXYService s = (IXYService)ctx.getBean("nameOfClassXY");

                            Comment


                            • #15
                              Well, the class is being instantiated via an interface.

                              Here is the complete application code.

                              ApplicationContext.xml file. For the sake of brevity and testing, I had included all beans in one xml file.

                              Code:
                              <?xml version="1.0" encoding="UTF-8"?>
                              <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" xmlns:tx="http://www.springframework.org/schema/tx"
                              	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                              			           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
                              			           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
                              
                              	<!-- Transaction Management -->
                              	<tx:annotation-driven transaction-manager="txManager"/>
                              
                              	<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                              		<property name="sessionFactory" ref="sessionFactory"/>
                              	</bean>
                              	
                              	<bean id="smartDaoTarget" class="com.package.dao.impl.SmartWorkDaoImpl">
                              		<property name="sessionFactory" ref="sessionFactory"/>
                              	</bean>
                              
                              	<bean id="smartBaseBO" class="org.springframework.aop.framework.ProxyFactoryBean">
                              		<property name="proxyInterfaces" value="com.package.core.dao.SmartBaseBO" />
                              		<property name="target" ref="smartDaoTarget"/>
                              	</bean>
                              	
                              	<bean id="userManager" class="org.springframework.aop.framework.ProxyFactoryBean">
                              		<property name="proxyInterfaces" value="com.package.core.users.UserManager"/>
                              		<property name="target" ref="userManagerTarget"/>
                              	</bean>
                              	
                              	<bean id="userManagerTarget" class="com.package.core.users.impl.UserManagerImpl">
                              		<property name="smartBaseBO" ref="smartBaseBO"/>
                              	</bean>
                              	
                              	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                              		
                              		<property name="dataSource" ref="dataSource"/>
                              
                              		<property name="mappingLocations">
                              			<list>
                              				<value>/WEB-INF/hbm/security/Authorities.hbm.xml</value>
                              				<value>/WEB-INF/hbm/security/Users.hbm.xml</value>
                              			</list>
                              		</property>
                              
                              		<property name="hibernateProperties">
                              			<props>
                              				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
                              				<prop key="hibernate.show_sql">true</prop>
                              				<prop key="hibernate.max_fetch_depth">3</prop>
                              				<prop key="hibernate.connection.release_mode">auto</prop>
                              			</props>
                              		</property>
                              	</bean>
                              	
                              	<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy" destroy-method="close">
                              		<property name="targetDataSource" ref="dataSourceTarget"/>
                              		<property name="defaultAutoCommit" value="false"/>
                              	</bean>
                              	
                              	<bean id="dataSourceTarget" class="oracle.jdbc.pool.OracleConnectionPoolDataSource" destroy-method="close">
                              		<property name="URL" value="jdbc:oracle:thin:@192.168.1.100:1521:test"/>
                              		<property name="user" value="testuser" />
                              		<property name="password" value="testpwd" />
                              	</bean>	
                              	
                              </beans>
                              DAO Code
                              ========
                              Code:
                              //SmartBaseBO.java interface definition file.
                              public interface SmartBaseBO {
                              	public boolean add(Object aObject);
                              }
                              
                              public class SmartWorkDaoImpl implements SmartBaseBO {
                              
                              	private SessionFactory sessionFactory;
                              
                              	public boolean add(Object aObject) {
                              		boolean bRetVal = false;
                              		Session session = getSession();
                              		try {
                              			session.save(aObject);
                              			bRetVal = !bRetVal;
                              		} catch (HibernateException e) {
                              			throw SessionFactoryUtils.convertHibernateAccessException(e);
                              		} finally {
                              			session.flush();
                              		}
                              		return bRetVal;
                              	}
                              
                              	private Session getSession() {
                              		return SessionFactoryUtils.getSession(getSessionFactory(), true);
                              	}
                              
                              	public void setSessionFactory(SessionFactory sessionFactory) {
                              		this.sessionFactory = sessionFactory;
                              	}
                              
                              	public SessionFactory getSessionFactory() {
                              		return this.sessionFactory;
                              	}
                              }
                              
                              //UserManager Interface
                              package com.package.core.users;
                              
                              public interface UserManager {
                              	void createUser(Users user, String role) throws Exception;
                              }
                              
                              //UserManager Implementation
                              
                              package com.package.core.users.impl;
                              
                              public class UserManagerImpl implements UserManager {
                              
                              	private final static Log LOG = LogFactory.getLog(UserManagerImpl.class);
                              
                              	private SmartBaseBO smartBaseBO;
                              
                              	@Transactional(propagation=Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
                              	public void createUser(Users user, String role) throws Exception {
                              		try {
                              			smartBaseBO.add(user);
                              			Authorities auth = new Authorities();
                              			auth.setAuthority(role);
                              			auth.setUsername(user.getUsername());
                              			auth.setUsers(user);
                              			smartBaseBO.add(auth);
                              		} catch (Exception e) {
                              			LOG.error("------------------------------   EXCEPTION ----------");
                              			throw e;
                              		}
                              	}
                              
                              	public void setSmartBaseBO(SmartBaseBO smartBaseBO) {
                              		this.smartBaseBO = smartBaseBO;
                              	}
                              }
                              
                              //JUnit Test Case
                              
                              public class UserManagerTest {
                              
                              	@Test
                              	public void testAdd() {
                              		try {
                              			ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");
                              			UserManager userManager = (UserManager) appCtx.getBean("userManager");
                              			Users user = new Users();
                              			user.setUsername("junittest3");
                              			user.setFirstName("junittest1");
                              			user.setLastName("junittest1");
                              			user.setPassword("test");
                              			user.setUpdated(new Date());
                              			user.setPrimaryEMail("[email protected]");
                              			userManager.createUser(user, "DEFAULT_ROLE");
                              		} catch (Exception e) {
                              			System.out.println(e);
                              		}
                              	}
                              }
                              The Unit test case works fine. It doesn't create a user, if the role creation for the user fails. It rolls back properly. The database doesn't contain the record as expected. (the tool was refreshed).

                              But, same code doesnt work when used in the application. The logs show that the rollback was done, but the database has the new record, whereas the new record should not have been inserted. (again, the tool was refreshed).

                              My guess, is it has something to do with Spring Transaction Synchronization and Spring Session management.

                              Database: Oracle 10g
                              AppServer: Tomcat 6.0.18
                              Spring 2.5.6
                              Hibernate 3.3.1 GA

                              Thanks for the help.
                              Last edited by ritesh; Apr 9th, 2009, 01:35 PM.

                              Comment

                              Working...
                              X