Announcement Announcement Module
Collapse
No announcement yet.
Transaction Management Using Spring Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Transaction Management Using Spring

    I am working on persisting associated objects in single transaction .
    Got started with declaring following attributes in applicationContext.xml using TransactionProxy which in turn uses HibernateTransactionManager as shown below
    Code:
    <bean id="txProxyTemplate" abstract="true"
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager">
                <ref bean="transactionManager"/>
            </property>
            <property name="transactionAttributes">
                <props>
                    <prop key="save*">PROPAGATION_REQUIRED</prop>
                    <prop key="store*">PROPAGATION_REQUIRED</prop>
                    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                    <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                    <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
                    <prop key="*">PROPAGATION_REQUIRED</prop>
                </props>
            </property>
    
            <property name="preInterceptors">
                <list>
    
                </list>
            </property>
    
            <property name="postInterceptors">
                <list>
    
                </list>
            </property>
        </bean>
    
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory">
                <ref local="sessionFactory"/>
            </property>
        </bean>
    As i am newbie to using Transaction management not sure what should be my next steps. I am thinking of the following
    1. Declare the methods to be in transaction similar to EJB2.0 . But not seen an example of such kind on google search. Their are examples declaring bean to be in transaction like
      Code:
      <bean id="manufManager" parent="txProxyTemplate">
          	<property name="proxyInterfaces">
          		<value>com.example.service.ManufacturerManager</value>
          	</property>
              <property name="target">
                 <bean class="com.boeing.nmt.nams.service.impl.ManufacturerManagerImpl">
                      <property name="manufDao" ref="manufDao"/> 
                      <property name="namsUserDao" ref="namsUserDao"/>
                 </bean>
              </property>
          </bean>
      So i am not sure how to declare calling and called methods in Transaction as similar to in EJB2.0
    1. I am not sure how to design one method calling the other in single Transaction in code .
    Any pointers/suggestions will be highly appreciated

    Regards
    Bansi

  • #2
    The configuration you've posted looks fine (having a quick glance at it) to me. Any method called from within ManufacturerManager will be contained within the same transaction that this bean defines. Therefore if you call into serveral daos and save, update and delete some data it will be contained within the same transaction (unless you've delcared more transaction attributes on the DAO).
    http://www.springframework.org/docs/...decl-explained
    Last edited by karldmoore; Aug 30th, 2007, 06:31 AM.

    Comment


    • #3
      Hi karldmoore
      Thanks for sharing. I read the article http://www.springframework.org/docs/...decl-explained
      Could you pl provide your thoughts on the following
      • The article uses tx:advice to define the context of Transaction whereas i am using Dependency Injection thru my applicationContext.xml file to define transaction attributes i.e. bean id="txProxyTemplate"
        So i am really confused which is the right way
      • Currently i am working on Persisting associated Objects (in my case are DeviceType and Role). Not sure how to put them in Single Transaction i.e. both parent & child objects should be persisted in same transaction. In case of Exception the entire transaction should rollback (i.e. ACID).

        Here is snippet from my applicationContext.xml file
        <bean id="txProxyTemplate" abstract="true"
        class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
        <property name="transactionManager"> <ref bean="transactionManager"/> </property>
        <property name="target"><ref bean="deviceTypeDao"/></property>

        <property name="transactionAttributes">
        <props>
        <prop key="save*">PROPAGATION_REQUIRED</prop>
        <prop key="persist*">PROPAGATION_REQUIRED</prop>
        <prop key="update*">PROPAGATION_REQUIRED</prop>
        <prop key="delete*">PROPAGATION_REQUIRED</prop>
        <prop key="remove*">PROPAGATION_REQUIRED</prop>
        <prop key="store*">PROPAGATION_REQUIRED</prop>
        <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
        <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
        <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
        <prop key="*">PROPAGATION_REQUIRED</prop>
        </props>
        </property>

        <property name="preInterceptors">
        <list>

        </list>
        </property>

        <property name="postInterceptors">
        <list>

        </list>
        </property>
        </bean>

        Please note the usage of "deviceTypeDao" i.e. <property name="target"><ref bean="deviceTypeDao"/></property>

        Not sure what should be my next steps.
        Do i need to declare Exceptions in applicationContext.xml file as shown in the article rollback-for="NoProductInStockException" ??
        Do i need to write any code in Spring bean except try, catch block for handling exceptions
        Finally how do i test the Transaction is running, i looked at the Logs but it has nothing related to Transaction

      Any pointers/suggestions will be highly appreciated

      Comment


      • #4
        Ok, firstly tx:advice and TransactionProxyFactoryBean are going to be doing the same thing for you. It's just another way of configuring it.
        http://forum.springframework.org/showthread.php?t=37178

        If you want your items commited or rolled back together then just ensure they are inserted in the same transaction. A typical solution when working with multiple DAOs is to add the transaction boundary at the service layer. It's typical to leave the target property out of the abstract transaction been and instead fill this in when you extend it. This is shown in the thread I posted earlier. As for adding exceptions, this describes the format. Only checked exceptions need to be named though.
        http://www.springframework.org/docs/...uteEditor.html

        There should be something in the logs, ensure you've got it set on debug. Lastly, [code] [ /code] tags, it's soooo much easier to read!
        Last edited by karldmoore; Aug 30th, 2007, 06:31 AM.

        Comment


        • #5
          Thanks for sharing.
          • I am still not sure how to specify Exceptions in the applicationContext.xml configuration file.
            Do i need to define Exceptions at the TransactionAtrributes level OR at the bean level in applicationContext.xml file ???

            A snippet will be highly appreciated
          • I have following try, catch block in Spring bean for save/update/delete methods but it doesn't do anything.
            Am i missing something here ???

            Code:
            try { 
            				
                          deviceTypeDao.persist(deviceType);
            	//deviceTypeDao.saveOrUpdate(deviceType);
                         //deviceTypeDao.remove(deviceType);
            
              } catch(Exception ex){
            		System.out.println("catching Exception In Spring Bean");				
            		Throwable lastCause = ex;   
            		while (lastCause.getCause() != null){     
            		lastCause = lastCause.getCause(); 
            		System.out.println("Exception Cause="+lastCause);
            		}
            		System.out.println("Exception Message="+lastCause.getMessage());
            		if (lastCause.getMessage().contains("detached entity passed to persist"))
            		throw  new DetachEntityException("detached entity passed to persist.");     
            		else
            		 throw new ServiceException(); //BaseException class  
            			}
            		}
          • Sorry i didnt understood your point on
            It's typical to leave the target property out of the abstract transaction been and instead fill this in when you extend it
            Currently i have the target property set to DAO object i.e. deviceTypeDao hoping the methods in DAO object will be in transaction as defined in transaction attributes
          [LIST]
          I totally agree with you on defining transaction boundary at the service layer while dealing with multiple DAOs. Could you please show me with a snippet how to do this. Wondering if this is the way to do in applicationContext.xml file
          Code:
          <bean id="manufManager" parent="txProxyTemplate">
              	<property name="proxyInterfaces">
              		<value>com.boeing.nmt.nams.service.ManufacturerManager</value>
              	</property>
                  <property name="target">
                     <bean class="com.boeing.nmt.nams.service.impl.ManufacturerManagerImpl">
                          <property name="manufDao" ref="manufDao"/> 
                          <property name="namsUserDao" ref="namsUserDao"/>
                          <property name="baseManager" ref="baseManager"/>
                     </bean>
                  </property>
              </bean>
          [LIST]

          Comment


          • #6
            The reference manual has examples of how to declare exceptions. If you have a look at that in conjunction with the JavaDoc that should be all you need. In this example it's configured to rollback for MyCheckedException when calling the insert* method.
            Code:
            <bean id="petStore" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
              <property name="transactionManager" ref="txManager"/>
              <property name="target" ref="petStoreTarget"/>
              <property name="transactionAttributes">
                <props>
                  <prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop>
                  <prop key="update*">PROPAGATION_REQUIRED</prop>
                  <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
                </props>
              </property>
            </bean>
            http://static.springframework.org/sp...n.html#d0e5690

            This code shows what I was trying to explain, leave the target out of the abstract bean and add it to the children. It makes it much easier to code. The link provided has more discussion on this. As for put the transaction boundary at the service layer, this example does that. The example would be the same if it was at the DAO layer, it's just a case of which classes you want to be transactional.
            Code:
            <bean id="baseTxProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
              <property name="transactionManager" ref="txManager"/>
              <property name="transactionAttributes">
                <value>
                  get*=PROPAGATION_SUPPORTS,readOnly
                  *=PROPAGATION_REQUIRED
                </value>
              </property>
            </bean>
            
            <bean id="serviceA" parent="baseTxProxy">
              <property name="target">
                <bean class="com.mycompany.myapp.service.ServiceA"/>
              </property>
            </bean>
            
            <bean id="serviceB" parent="baseTxProxy">
              <property name="target">
                <bean class="com.mycompany.myapp.service.ServiceB"/>
              </property>
            </bean>
            http://forum.springframework.org/showthread.php?t=37178
            Last edited by karldmoore; Aug 30th, 2007, 06:31 AM.

            Comment


            • #7
              Ok I missed one of the answers out. As for why your code doesn't do anything, have you named the ServiceException as requiring a rollback? If it's not unchecked you'll have to do this. When you say it doesn't do anything though, what does this actually mean?
              Last edited by karldmoore; Aug 30th, 2007, 06:31 AM.

              Comment


              • #8
                Thank you so much.
                Here is my ServiceException, the base exception class for Service Layer

                Code:
                package com.XXX.service.exception;
                
                import com.XXX.exception.BaseException;
                
                /**
                 * Base checked exception for the Middle Tier.
                 * 
                 * 
                 */
                
                public class ServiceException extends BaseException{
                	
                	/**
                	 * Constructor 
                	 */
                	public ServiceException() {
                	    super();
                		}
                	
                	
                	/**
                	 * Constructor with error message.
                	 * 
                	 * @param msg the error message associated with the exception
                	 */
                	
                	public ServiceException(String msg) {
                		super(msg);		
                	}
                	
                	
                	/**
                	 * Constructor with root cause.
                	 * 
                	 * @param cause the root cause of the exception
                	 */
                	
                	
                	public ServiceException(Throwable cause) {
                        super(cause);
                    }
                	
                	
                	
                	/**
                	 * Constructor with error message and root cause.
                	 * 
                	 * @param msg the error message associated with the exception
                	 * @param cause the root cause of the exception
                	 */
                	public ServiceException(String msg, Throwable cause) {
                		super(msg, cause);
                	}
                	
                	
                
                
                }
                
                
                package com.XXX.exception;
                
                public class BaseException extends RuntimeException {
                	
                	public BaseException() {
                        super();
                    }
                    
                	/**
                	 * Constructor with error message.
                	 * 
                	 * @param msg the error message associated with the exception
                	 */
                    public BaseException(String message) {
                        super(message);
                    }    
                   
                    /**
                	 * Constructor with root cause.
                	 * 
                	 * @param cause the root cause of the exception
                	 */
                    public BaseException(Throwable cause) {
                        super(cause);
                    }
                    
                    /**
                	 * Constructor with error message and root cause.
                	 * 
                	 * @param msg the error message associated with the exception
                	 * @param cause the root cause of the exception
                	 */
                    public BaseException(String message, Throwable cause) {
                        super(message, cause);
                    }
                
                }
                In my earlier posting, the code snippet in Spring bean try/catch block looks for Exception Message for example specific exception like "DetachEntityException" and if it occurs its handled in the Spring/JSF layer, otherwise it throws ServiceException as shown below

                Code:
                try { 
                				
                              deviceTypeDao.persist(deviceType);
                	//deviceTypeDao.saveOrUpdate(deviceType);
                             //deviceTypeDao.remove(deviceType);
                
                  } catch(Exception ex){
                		System.out.println("catching Exception In Spring Bean");				
                		Throwable lastCause = ex;   
                		while (lastCause.getCause() != null){     
                		lastCause = lastCause.getCause(); 
                		System.out.println("Exception Cause="+lastCause);
                		}
                		System.out.println("Exception Message="+lastCause.getMessage());
                		if (lastCause.getMessage().contains("detached entity passed to persist"))
                		throw  new DetachEntityException("detached entity passed to persist.");     
                		else
                		 throw new ServiceException(); //BaseException class  
                			}
                		}
                The reason i say the above code doesnt do anything is maybe i am missing something like i have to write a test-code which generate Exception and eventually Rollback the transaction. Any pointers/suggestions will be highly appreciated

                Comment


                • #9
                  Your exception is unchecked so you don't need to do any mappings for this, it will rollback anyway. If you want to test rollback then simply try an exception after the persist, that should tell you straight away if it's working. In the long term, you could maybe provide a mock for the DAO, or add an interceptor on the DAO that generates an exception.
                  Last edited by karldmoore; Aug 30th, 2007, 06:31 AM.

                  Comment


                  • #10
                    Any pointers/suggestions on how to
                    provide a mock for the DAO, or add an interceptor on the DAO that generates an exception
                    will be highly appreciated

                    Comment

                    Working...
                    X