Announcement Announcement Module
Collapse
No announcement yet.
Problem in managing Transaction with AbstractRoutingDataSource Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem in managing Transaction with AbstractRoutingDataSource

    Hi,

    We are facing problem in transaction management while using AbstractRoutingDataSource.

    Problem Description: Connection used by DataSourceTransactionManager while starting the transaction is different than connection used by DAO; although, the Datasource are same at both point.

    Scenario: We are using custom Routing Data Source extending the AbstractRoutingDataSource to pick data source dynamically based on Application context. However, for a single transaction, Data source never change. TransactionManager used is DataSourceTransactionManager. Requirement is, we have two different data sources in application. We have many legacy code methods which can be invoked in context of any of above data sources. Data sources (target DB) is decided based on application contextual value and vary from Use case to Use case. So we need a provision where same transaction manager can work with any of the data source, which will be picked based on application logic. Application logic decides the data source before entering into transaction boundary.

    Data Source Definition:

    [/FONT][/COLOR]

    <bean id="dataSourceOltp" name="oltpDataSource" class="org.springframework.jdbc.datasource.Transac tionAwareDataSourceProxy">
    <property name="targetDataSource">
    <jee:jndi-lookup jndi-name="jdbc/DB" cache="true" />
    </property>
    </bean>
    <bean id="dataSourceReportDb" name="dataSourceReportDb" class="org.springframework.jdbc.datasource.Transac tionAwareDataSourceProxy">
    <property name="targetDataSource">
    <jee:jndi-lookup jndi-name="jdbc/ReportDB" cache="true" />
    </property>
    </bean>

    <bean id="customDataSource" class="com.a.b.common.db.DBCustomRoutingDataSource ">
    <property name="targetDataSources">
    <map key-type="com.a.b.util.DataSourceConstants">
    <entry key="OLTP_DB" value-ref="dataSourceOltp"/>
    <entry key="REPORT_DB" value-ref="dataSourceReportDb"/>
    </map>
    </property>
    <property name="defaultTargetDataSource" ref="dataSourceOltp"/>
    </bean>

    <bean id="CustomTxManager" class="org.springframework.jdbc.datasource.DataSou rceTransactionManager">
    <property name="dataSource" ref="customDataSource" />
    </bean>

    [COLOR=#333333][FONT=Arial]

    Same Data source has been injected in DAO classes.


    Observations:
    > DataSourceTransactionManager is having special handling if TransactionAwareDataSourceProxy is set as DS. It picks the target data source, instead of using the TransactionAwareDataSourceProxy. However, there is no special handling for Custom Routing Data Source.
    > In DataSourceTransactionManager > doBegin > Connection is stored in TransactionSynchronizationManager against the current data source, which is CustomRoutingDataSource. However, later in DAO, when we ask the connection from same custom data source (tx aware), TransactionSynchronizationManager search for the connection for nested DS, which is Pooled Data Source (in DataSourceUtils). Hence it does not find it, and get a new connection from Pooled Data Source.

    Question:
    > Are we missing something while using AbstractRoutingDataSource with DataSourceTxManager, any configuration needs to make
    > Do we need to extend DataSourceTransactionManager to return the right target data source, instead of Custom Data Source
    >> However, overriding TxManager is not straight forward, seems Connection Holder is not designed to be used for extension.

    Any insight will help. Thanks.

  • #2
    Hi,

    Looking forward for any suggestions. Thanks.

    Comment


    • #3
      We found the solution and good part is that solution is very simple.

      Solution: If we are using TransactionAwareDataSourceProxy with DataSourceTransactionManager, then TADataSourceProxy should be the outer most proxy. Reason, as mentioned above, DataSourceTransactionManager has special handling for TransactionAwareDataSourceProxy to work with actual DataSource wrapped in it. DataSourceTransactionManager will never work with TransactionAwareDataSourceProxy. So a simple change in above configuration can help, which is, create the DataSource + Proxy in a way that TransactionAwareDataSourceProxy be the outer most proxy in the hierarchy.

      <bean id="dataSourceOltp" name="oltpDataSource" class="..PooledDataSource">
      <property name="targetDataSource">
      <jee:jndi-lookup jndi-name="jdbc/DB" cache="true" />
      </property>
      </bean>
      <bean id="dataSourceReportDb" name="dataSourceReportDb" class="..PooledDataSource">
      <property name="targetDataSource">
      <jee:jndi-lookup jndi-name="jdbc/ReportDB" cache="true" />
      </property>
      </bean>

      <bean id="customDataSource" class="com.a.b.common.db.DBCustomRoutingDataSource ">
      <property name="targetDataSources">
      <map key-type="com.a.b.util.DataSourceConstants">
      <entry key="OLTP_DB" value-ref="dataSourceOltp"/>
      <entry key="REPORT_DB" value-ref="dataSourceReportDb"/>
      </map>
      </property>
      <property name="defaultTargetDataSource" ref="dataSourceOltp"/>
      </bean>

      <bean id="txAwareCustomDS" name="txAwareCustomDS" class="org.springframework.jdbc.datasource.Transac tionAwareDataSourceProxy">
      <property name="targetDataSource" ref="customDataSource">
      </property>
      </bean>

      <bean id="CustomTxManager" class="org.springframework.jdbc.datasource.DataSou rceTransactionManager">
      <property name="dataSource" ref="txAwareCustomDS" />
      </bean>

      Keep data sources as:

      TransactionAwareDataSourceProxy > Routing Data Source > Lazy Data Source > Pooled Data Source

      Following this, DataSourceTransactionManager will strip the TransactionAwareDataSourceProxy from the top and will work with the actual data source. Flow should work fine.

      Comment


      • #4
        Solution and generic approach has been posted at following blog also -http://www.vedantatree.com/2014/05/spring-routingdatasource-to-work-with.html

        Comment

        Working...
        X