Announcement Announcement Module
Collapse
No announcement yet.
Declarative transaction management in Spring Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Declarative transaction management in Spring

    Hi friends!!
    I'm trying to use the declarative transaction management with Hibernate in Spring. But i can't obtain a rollback at my wrong actions on BBDD.

    This is my applicationContext-Hibernate.xml:
    Code:
    ?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
    
    <beans>
    	<!-- ========================= GENERAL DEFINITIONS ========================= -->
    	<!-- Referencia al fichero de propiedades "messages.properties" -->
    	<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    		<property name="basename"><value>messages</value></property>										
    	</bean>
    
    	<!-- ========================= RESOURCE DEFINITIONS ========================= -->
      
    	<!-- DataSource a utilizar en la aplicacion -->
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="driverClassName"><value>oracle.jdbc.driver.OracleDriver</value></property>
    		<property name="url"><value>jdbc&#58;oracle&#58;thin&#58;@192.168.24.13&#58;1521&#58;oradesa</value></property>
    		<property name="username"><value>dqtfinf</value></property>
    		<property name="password"><value>dqtfinf</value></property>
    		
    	</bean>
    	
    	<!-- SessionFactory de Hibernate-->
    	<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
    		<property name="dataSource"><ref local="dataSource"/></property>
    		<!-- Fichero donde se encuentra el mapeo a los objetos relaciones en BBDD -->
    		<property name="mappingResources">
    			<value>com/acotelsa/transactions/hibernate/spring_hibernate.xml</value>
    		</property>
    		<property name="hibernateProperties">
    			<props>
    				<prop key="hibernate.dialect">net.sf.hibernate.dialect.Oracle9Dialect</prop>
                    <!-- <prop key="hibernate.cglib.use_reflection_optimizer">false</prop>-->
                    <prop key="hibernate.show_sql">true</prop>
    			</props>
    		</property>
    	</bean>
    	
    	<!-- Manager de transacciones para el SessionFactory de Hibernate &#40;alternativo a JTA&#41; -->
    	<!-- probar también con "org.springframework.transaction.jta.JtaTransactionManager"-->
    	<bean id="txManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
    		<property name="sessionFactory"><ref local="sessionFactory"/></property>
    	</bean>
    	
    	<!-- ========================= BUSINESS OBJECT DEFINITIONS ========================= -->
    	<!-- Proxy transaccional para el objeto de negocio principal de la aplicacion -->
    	<bean id="blankProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager"><ref local="txManager"/></property>
    		<property name="target"><ref local="blankTarget"/></property>
    		<property name="transactionAttributes">
    			<props>
    				<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
    			</props>
    		</property>
    	</bean>
    	
    	<!-- Objeto de negocio principal de SpringHibernateBlank. Implementación con Hibernate -->
    	<bean id="blankTarget" class="com.acotelsa.transactions.hibernate.HibernateProductoManager">
    		<property name="sessionFactory"><ref local="sessionFactory"/></property>
    	</bean>
    </beans>
    My HibernateManager is:
    Code:
    package com.acotelsa.transactions.hibernate; 
    
    import java.util.List;
    
    
    import org.springframework.orm.hibernate.HibernateTemplate;
    import org.springframework.orm.hibernate.support.HibernateDaoSupport;
    
    import com.acotelsa.transactions.hibernate.Producto;
    
    /**
     * TODO &#40;Comentario Explicativo de la Clase&#41; 
     * @autor [email protected]
     */
    public class HibernateProductoManager extends HibernateDaoSupport&#123;
        private HibernateTemplate template=null;
        
        public HibernateProductoManager&#40;&#41;
        &#123;
        &#125;
        
        /**
         * Crea el producto especificado
         * @param producto El producto a crear en BBDD
         * @return El identificador del producto creado
         */
        public Integer createProducto&#40;Producto producto&#41;
        &#123;
            Integer id= &#40;Integer&#41; getHibernateTemplate&#40;&#41;.save&#40;producto&#41;;
            return id;
        &#125;
    &#125;
    When i call to "createProducto" by this way:
    Code:
    Producto producto=&#40;Producto&#41;command;
            
    //Se procede a crear el producto
    producto.setId&#40;new Integer&#40;55&#41;&#41;;
    Integer id=PM.createProducto&#40;producto&#41;;
    id=PM.createProducto&#40;producto&#41;;
    I can't obtain any rollback or an advice because is "readOnly" method. Is something wrong in the configuration?? :shock:

  • #2
    Umm... Why do you use a readonly transaction for something that is clearly not readonly?

    Comment


    • #3
      Because i believe that my application isn't looking at my TransactionProxyFactoryBean: it still insert the fisrt record on database. So i put the "readonly" property to prove that maybe it give me an exception because it, but it is inserting the record!!!! :shock:
      I've the same result if i put the "readOnly" that if i remove it.

      Comment


      • #4
        Where do you think it should make a rollback? Single insert is an atomic operation in itself - and there is no place after the insert where rollback can be initiated that I can see.

        Comment


        • #5
          Ok. I had tried to insert a "throw new RuntimeException" on the "createProducto" method, and i doesn't do the rollback. I don't know if my configuration is wrong or i've i testing it with wrong things. :?: :?:

          Comment


          • #6
            You mean something like

            Code:
             public Integer createProducto&#40;Producto producto&#41;
                &#123;
                    Integer id= &#40;Integer&#41; getHibernateTemplate&#40;&#41;.save&#40;producto&#41;;
                    throw new RuntimeException&#40;""&#41;;
                    return id;
                &#125;
            actually commits?

            Can you post your PM class from

            Code:
            Integer id=PM.createProducto&#40;producto&#41;;
            Edit: sorry, I meant the place where PM is created.

            Comment


            • #7
              Actually my "createProducto" is like:
              Code:
              public Integer createProducto&#40;Producto producto&#41;
                  &#123;
                      Integer id= &#40;Integer&#41; getHibernateTemplate&#40;&#41;.save&#40;producto&#41;;
                      if &#40;true&#41;
                          throw new RuntimeException&#40;&#41;;
                      return id;
                  &#125;
              And it still commits.

              Comment


              • #8
                And PM is created on the "applicationContext-hibernate.xml":
                Code:
                <bean id="blankTarget" class="com.acotelsa.transactions.hibernate.HibernateProductoManager">
                		<property name="sessionFactory"><ref local="sessionFactory"/></property>
                	</bean>

                Comment


                • #9
                  I meant in your code, not in the context.

                  Comment


                  • #10
                    Code:
                    public class AltaProductoFormController extends SimpleFormController&#123;
                    
                        protected final Log logger = LogFactory.getLog&#40;getClass&#40;&#41;&#41;;
                        /**
                         * Valor del campo <code>PM</code> que representa el Manager del Producto
                         */
                        private HibernateProductoManager PM;
                    
                        public ModelAndView onSubmit&#40;Object command&#41;
                                throws DataAccessException &#123;
                    
                            logger.info&#40;"Ha entrado en el AltaProductoFormController"&#41;;
                            Producto producto=&#40;Producto&#41;command;
                            
                            //Se procede a crear el producto
                            producto.setId&#40;new Integer&#40;55&#41;&#41;;
                            Integer id=PM.createProducto&#40;producto&#41;;
                            
                            //Se vuelve a la pantalla de inicio
                            return new ModelAndView&#40;new RedirectView&#40;getSuccessView&#40;&#41;&#41;&#41;;
                        &#125;
                    
                        protected Object formBackingObject&#40;HttpServletRequest request&#41; throws ServletException &#123;
                            //Objecto a devolver si falla
                            Producto producto=new Producto&#40;&#41;;
                            producto.setNombre&#40;""&#41;;
                            producto.setDescripcion&#40;""&#41;;
                            return producto;
                    
                        &#125;
                        
                        public void setPM&#40;HibernateProductoManager prodM&#41;
                        &#123;
                            PM=prodM;
                        &#125;
                        public HibernateProductoManager getPM&#40;&#41;
                        &#123;
                            return PM;
                        &#125;
                    &#125;
                    I don't have nothing else.

                    Comment


                    • #11
                      Ok, then we need to see your context where you declare the AltaProductoFormController class.

                      Comment


                      • #12
                        This is my springHibernateTransactions-servlet.xml:
                        Code:
                        <?xml version="1.0" encoding="UTF-8"?>
                        <!-- edited with XMLSPY v5 U &#40;http&#58;//www.xmlspy.com&#41; by Registred &#40;Registred&#41; -->
                        <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
                        <beans>
                        
                        	<!--  Controllador para la pagina inicial "Hello" -->
                        	<bean id="springHibernateTransactionsController" class="com.acotelsa.transactions.opr.SpringHibernateTransactionsController">
                        		<property name="PM">
                        			<ref bean="blankTarget"/>
                        		</property>
                        	</bean>
                        	
                        	<!--  Validador correspondiente al formulario de alta de un producto -->
                        	<bean id="altaProductoValidator" class="com.acotelsa.transactions.jsp.AltaProductoValidator"/>
                        	
                        	<!--  Controlador del formulario correspondiente al alta de un producto-->
                        	<bean id="altaProductoForm" class="com.acotelsa.transactions.opr.AltaProductoFormController">
                        		<property name="sessionForm"><value>true</value></property>
                        		<!-- Nombre del objeto comando &#40;Ejem&#58; como se le llamará con JSTL&#41;-->
                                <property name="commandName"><value>producto</value></property>
                                <!-- Clase correspondiente al objeto comando -->
                                <property name="commandClass"><value>com.acotelsa.transactions.hibernate.Producto</value></property>
                                <!-- Referencia al validador correspondiente -->
                                <property name="validator"><ref bean="altaProductoValidator"/></property>
                                <!-- Nombre de la vista correspondiente -->
                                <property name="formView"><value>altaProducto</value></property>
                                <!-- Vista destino, cuyo uso dependerá de la implementación del controlador -->
                                <property name="successView"><value>hello.htm</value></property>
                                <!-- Referencia al Manager de Producto -->
                                <property name="PM">
                        			<ref bean="blankTarget"/>
                        		</property>
                        	</bean>
                        	
                        	<!-- Mapeo de cada vista con su correspondiente controlador -->
                        	<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
                        		<property name="mappings">
                        			<props>
                        				<prop key="transactions/hello.htm">springHibernateTransactionsController</prop>
                        				<prop key="transactions/altaProducto.htm">altaProductoForm</prop>
                        			</props>
                        		</property>
                        	</bean>
                        	
                        	<!-- Referencia al fichero de propiedades &#40;messages.properties&#41; -->
                        	<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
                        		<property name="basename">
                        			<value>messages</value>
                        		</property>
                        	</bean>
                        
                        	<!--  "Resolvedor de vistas" Indica de que tipo será la vista &#40;JSTL, JSP simple, Velocity ..., así como
                        		el prefijo o sufijo correspondiente cada vez que se hace ref a una vista -->
                        	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                        		<property name="viewClass">
                        			<value>org.springframework.web.servlet.view.JstlView</value>
                        		</property>
                        		<property name="prefix">
                        			<value>/transactions/</value>
                        		</property>
                        		<property name="suffix">
                        			<value>.jsp</value>
                        		</property>
                        	</bean>
                        </beans>

                        Comment


                        • #13
                          Code:
                          <property name="PM">
                                   <ref bean="blankTarget"/>
                          </property>
                          should be

                          Code:
                          <property name="PM">
                                   <ref bean="blankProxy"/>
                          </property>

                          Comment


                          • #14
                            Uagggg, what stupid error. Thanks!!!

                            Comment


                            • #15
                              Umm....it doesn't run at all...If i do two "createProducto", and cause and exception on the second, the rollback only affect to the last one.
                              I have been reading about OpenSessionInViewInterceptor...I don't know if my configuration is wrong or i need another utilities to have a rollback of some operations in the same session :?:
                              I haven't the "setSessionFactory" on my Manager, is it the problem?? Or i have to use the xxxTemplate.execute(new TransactionCallbackWithoutResult(.....)) method??

                              Comment

                              Working...
                              X