Results 1 to 10 of 10

Thread: Transaction Management Using Spring

  1. #1
    Join Date
    May 2006
    Posts
    142

    Default 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. #2
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    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 at 05:31 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  3. #3
    Join Date
    May 2006
    Posts
    142

    Default

    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

  4. #4
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    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 at 05:31 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  5. #5
    Join Date
    May 2006
    Posts
    142

    Default

    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]

  6. #6
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    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 at 05:31 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  7. #7
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    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 at 05:31 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  8. #8
    Join Date
    May 2006
    Posts
    142

    Default

    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

  9. #9
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    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 at 05:31 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  10. #10
    Join Date
    May 2006
    Posts
    142

    Default

    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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •