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

  • Using Spring Transaction Management in Struts2

    I am trying to execute update statements for two databases (both oracle) in a single transaction. I found this code on the net. I am getting an error when I execute the code -
    HTML Code:
    public class TrialDao {	
        private DriverManagerDataSource dataSource;
        private DriverManagerDataSource dataSource2;
        private JtaTransactionManager jtaTransactionManager;
    
        public DriverManagerDataSource getDataSource2() {
            return dataSource2;
        }
    
        public void setDataSource2(DriverManagerDataSource dataSource2) {
            this.dataSource2 = dataSource2;
        }
    
        public JtaTransactionManager getJtaTransactionManager() {
            return jtaTransactionManager;
        }
    
        public void setJtaTransactionManager(JtaTransactionManager jtaTransactionManager) {
            this.jtaTransactionManager = jtaTransactionManager;
        }
    
        public DriverManagerDataSource getDataSource() {
            return dataSource;
        }
    
        public void setDataSource(DriverManagerDataSource dataSource) {
            this.dataSource = dataSource;
        }
    
        public void insertItem(){    	
    
            TransactionTemplate tt = new TransactionTemplate(jtaTransactionManager);
            System.out.println(" data source " + dataSource);
            System.out.println(" data source 123 " + dataSource2);
            MyCallBack mycallback = new MyCallBack(dataSource,dataSource2);
            tt.execute(mycallback);
        }
    }
    class MyCallBack implements TransactionCallback
    {
    	private DriverManagerDataSource dataSource;
        private DriverManagerDataSource dataSource2;
        
    	 public MyCallBack(DriverManagerDataSource dataSource,DriverManagerDataSource dataSource2){
    		 this.dataSource = dataSource;
    		 this.dataSource2 = dataSource2;
    	 }
    	 
    	 @Override
    	public Object doInTransaction(TransactionStatus arg0) {
    		 System.out.println(" REACHED DO IN TRANSACTION");            	
             JdbcTemplate jt = new JdbcTemplate(dataSource);
             System.out.println(" JT " + jt);
             String sql = "insert into ProductType(ID,ProductType) values (9,'MYTYPE');";
             jt.setDataSource(dataSource);
             jt.update(sql);
             sql = "insert into ProductType(ID,ProductType) values (9,'MYTYPE');";
             jt.setDataSource(dataSource2);
             jt.update(sql);
             return null;
    	}	
    }
    The exception I am getting is -
    HTML Code:
    java.lang.NullPointerException
    	org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:125)
    	net.xxx.xxxxx.backend.content.TrialDao.insertItem(TrialDao.java:49)
    	net.xxx.xxxxx.ui.login.LoginAction.authenticate(LoginAction.java:79)
    	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	java.lang.reflect.Method.invoke(Method.java:597)
    	com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:453)
    	com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:292)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:255)	com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
    	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)	org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
    	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
    	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)	org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
    	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)	com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236)
    	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236)
    	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)	com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:90)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)	com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
    	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    	com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:192)
    	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)	com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
    	............
    	org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter.doFilter(StrutsPrepareFilter.java:82)
    	org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
    The beans I have injected through applicationcontext.xml in struts -
    HTML Code:
    <bean id="parentDataSource"
             class="org.springframework.jdbc.datasource.DriverManagerDataSource"
             abstract="true">
       		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>   		
    	</bean>
    	<bean id="firstDataSource" parent="parentDataSource">
       		<property name="url" value="jdbc:oracle:thin:@firstdatabase.xxx.net:1521:sid1"/>
       		<property name="username" value="username1"/>
       		<property name="password" value="password1"/>
    	</bean>
    	<bean id="secondDataSource" parent="parentDataSource">
       		<property name="url" value="jdbc:oracle:thin:@seconddatabase.xxx.net:1521:sid2"/>
       		<property name="username" value="username2"/>
       		<property name="password" value="password2"/>
    	</bean>
    	<bean id="jtaTransactionManager"  
            class="org.springframework.transaction.jta.JtaTransactionManager">
    	</bean>  
    	<bean id="trialDao" class="net.xxx.xxxxxx.backend.content.TrialDao">
    	    <property name="dataSource">
    	        <ref local="firstDataSource"/>
    	    </property>
    	    <property name="dataSource2">
    	        <ref local="secondDataSource"/>
    	    </property>
    	    <property name="jtaTransactionManager">
    	        <ref local="jtaTransactionManager"/>
    	    </property>
    	</bean>
    I am not sure why this error is happening, the datasource objects are both populated with the connection url, username and password properties(they are getting populated). Is there anything else that I am missing?

  • #2
    Something is null in your class... And judging from the stacktrace you aren't using the spring configured bean but are using a new one instead.

    Also I probably wouldn't use this code... I would create a service annotate that with @Transactional (and use <tx:annotation-driven in the context) and inject 2 daos into that service and from struts call the service method... Saves you a lot of ugly code IMHO... And makes it transparent to whatever transactionmanager etc. you use.

    Final note the DriverManagerDataSource shouldn't be considered production quality and shouldn't be used for that, you want a proper connection pool for that.

    Comment


    • #3
      Originally posted by Marten Deinum View Post
      Something is null in your class... And judging from the stacktrace you aren't using the spring configured bean but are using a new one instead.

      Also I probably wouldn't use this code... I would create a service annotate that with @Transactional (and use <tx:annotation-driven in the context) and inject 2 daos into that service and from struts call the service method... Saves you a lot of ugly code IMHO... And makes it transparent to whatever transactionmanager etc. you use.

      Final note the DriverManagerDataSource shouldn't be considered production quality and shouldn't be used for that, you want a proper connection pool for that.
      Marten, Thank you very much for your reply. The beans do get populated from spring, I did not paste that part of the code. I however started with the approach that you mentioned and I referred to mybatis-spring-1.0.2-reference.pdf. I am constantly getting this error -

      HTML Code:
      org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext-infrastructure.xml]: Initialization of bean failed; nested exception is java.lang.reflect.MalformedParameterizedTypeException
      I googled for it and from what I understood, the dependencies should point to mybatis-3.1.1 and spring 3 jars. I added them accordingly and still I see the same error. I am not sure why this is happening. I am pasting the applicationContext-infrastructure.xml file below. Other than the dependency issues, what could be the possible causes of this error? - could it be another instance of sqlsessionfactory being created elsewhere in the code?
      HTML Code:
      <?xml version="1.0" encoding="UTF-8"?>
      <!--
          Copyright 2010-2012 The MyBatis Team
      
          Licensed under the Apache License, Version 2.0 (the "License");
         ......................
      -->
      
      <!--
          The base sample context containing commnon beans shared by all the
          MyBatis-Spring sample contexts.
      
          version: $Id$
      -->
      <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:jdbc="http://www.springframework.org/schema/jdbc"
           xsi:schemaLocation="
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
      
      	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      	    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
      	    <property name="url" value="jdbc:oracle:thin:@myserver:1521:sid"/>
      	    <property name="username" value="username"/>
      	    <property name="password" value="password"/>
      	</bean>
      
          <!-- transaction manager, use JtaTransactionManager for global tx -->
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource" />
          </bean>
          
          <!-- enable transaction demarcation with annotations -->
          <tx:annotation-driven />
          
          <!-- simplest possible SqlSessionFactory configuration -->
          <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
              <property name="dataSource" ref="dataSource" />
              <!-- Directly specify the location of the MyBatis mapper xml file. This
                   is NOT required when using MapperScannerConfigurer or
                   MapperFactoryBean; they will load the xml automatically if it is
                   in the same classpath location as the DAO interface. Rather than
                   directly referencing the xml files, the 'configLocation' property
                   could also be used to specify the location of a MyBatis config
                   file. This config file could, in turn, contain &ltmapper&gt
                   elements that point to the correct mapper xml files.
               -->
              <property name="mapperLocations" value="classpath:net/xxx/xxxxxxxx/FileBinaries/*.xml" />
          </bean>
          
      </beans>
      This is being referenced by applicationContext.xml which contains the Service class specifications.
      Last edited by siribg; Apr 1st, 2013, 10:29 AM.

      Comment

      Working...
      X