Announcement Announcement Module
Collapse
No announcement yet.
mixing raw JDBC and O/R-mapper access in same transactions Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • mixing raw JDBC and O/R-mapper access in same transactions

    We have an app running in WebSphere 5 where we access different databases (Oracle and Informix) and the Oracle DB is accessed via JDBC/StoredProcedures for legacy data and via JDO (Libelis/Xcalia LiDO) for our new stuff.

    Currently we don't use Spring and have setup JDO as an JCA adapter, but there are several issues with it, so we think about switching to Spring, if it provides enough advantages.

    - Tests outside WebSphere don't have the same transaction behaviour as inside, even when there is only one of the databases involved in the business service (which is true for 90% of our business methods)
    - Is JCA deployment of JDO the only option in a XA transaction environment? Or can we use normal DataSources and still have XA transactions in a managed environment?
    - For the stored procedures we get the connection from the LiDO managed PersistenceManager, not from a normal DataSource. Is this still necessary with Spring?

    Could Spring be a solutions for that and how would the configuration then look like (i.e. which TransactionManager, deployment option etc. inside and outside WebSphere)? (btw: switching to Hibernate is not an option for political reasons)

    The most important issue is that for the business cases where only one DB is accessed, I would like to have JUnit (integration) tests with the same transaction behaviour as in the deployed application.

    Thanks in advance for your time and support!

    Regards,
    Felix

  • #2
    Tests outside WebSphere don't have the same transaction behaviour as inside, even when there is only one of the databases involved in the business service (which is true for 90% of our business methods)
    Spring solves this very nicely. The org.springframework.test package (in spring-mock.jar) even gives you convenient JUnit test superclasses that create and rollback transactions for you around test cases, so you don't need to clean up your database...

    Is JCA deployment of JDO the only option in a XA transaction environment? Or can we use normal DataSources and still have XA transactions in a managed environment?
    I think you need to ask your JDO vendor this question. Hopefully they provide a JTA transaction synchronization implementation that will work even if you don't configure their product by JCA. Where "local" configuration is possible, we generally recommend it rather than JCA, for ORM tools.

    For the stored procedures we get the connection from the LiDO managed PersistenceManager, not from a normal DataSource. Is this still necessary with Spring?
    Spring uses a normal javax.sql.DataSource. So you should be able to use a JTA DataSource.

    Rgds
    Rod

    Comment


    • #3
      Thanks Rod, that helps a lot. Our JDO vendor (we use Xcalia/Libelis LiDO-JDO) does support local JTA-transactions, so probably we can (and should) switch.

      Assuming this, which TransactionManager do we have to use for our JUnit tests? I guess because we don't have a JTA provider when running outside WebSphere, we can't use JtaTransactionManager? So combining JDBC access and JDO access in the same test cases, which TransactionManager is best here? Or is WebSphere's JTA implementation just a jar file that we can include in our tests classpath?

      Thanks!

      Felix

      Comment


      • #4
        Hi Felix,

        I wouldn't bother with setting up a JTA environment outside WebSphere. You should be able to achieve analogous behavior with Spring's JdoTransactionManager, driving local JDO transactions on LiDO.

        For exposing JDO-driven transactions to JDBC access code (letting JDO and JDBC access code participate in the same transaction), you need to specify a JdoDialect on JdoTransactionManager, because standard JDO 1.0 does not cover access to a PersistenceManager's JDBC Connection.

        Essentially, you need to implement a LidoJdoDialect, with "getJdbcConnection(PersistenceManager)" delegating to LiDO-specific API for Connection retrieval. JdoTransactionManager will then call this method to retrieve transactional Connections for JDBC access code.

        The easiest way to implement such a LidoJdoDialect is to derive from Spring's DefaultJdoDialect, just overriding "getJdbcConnection". You don't need to care about the rest of JdoDialect's capabilities if all you want to achieve is JDBC Connection exposure.

        By default, JdoTransactionManager auto-detects the JDBC DataSource that the PersistenceManagerFactory uses (PersistenceManagerFactory.getConnectionFactory). If that doesn't work, specify the DataSource explicitly as "dataSource".

        The only problem I could imagine is that Lido might not expose the DataSource that is uses, in case of Lido's internal connection pool. There should be way to pass a Spring-defined DataSource to Lido's PersistenceManagerFactory in that case; I've done the same with JPOX.

        Juergen

        Comment


        • #5
          As example, setup options with JPOX. All of those make a PersistenceManagerFactory available in the Spring context, allowing to pass it to JDO-based DAOs.

          Option 1: Spring's LocalPersistenceManagerFactoryBean, using standard property-driven JDO setup. Usually combined with a JDO implementation's internal connection pool or a JNDI DataSource. Should also work with local JTA-aware configuration.

          Code:
          <bean id="persistenceManagerFactory" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
            <property name="jdoProperties">
              <props>
                <prop key="javax.jdo.PersistenceManagerFactoryClass">org.jpox.PersistenceManagerFactoryImpl</prop>
                <prop key="javax.jdo.option.ConnectionDriverName">com.mysql.jdbc.Driver</prop>
                <prop key="javax.jdo.option.ConnectionURL">jdbc&#58;mysql&#58;//localhost/imagedb</prop>
                <prop key="javax.jdo.option.ConnectionUserName">root</prop>
                <prop key="javax.jdo.option.ConnectionPassword"></prop>
                <prop key="javax.jdo.option.NontransactionalRead">true</prop>
              </props>
            </property>
          </bean>
          Option 2: Setting up an instance of the PersistenceManagerFactory implementation class directly. Should allow to link in an existing DataSource as "connectionFactory", no matter if a local DataSource (like Commons DBCP BasicDataSource) or a JNDI DataSource reference (with Spring's JndiObjectFactoryBean). JDO configuration properties are usually available as JavaBean properties on the PersistenceManagerFactory implementation class.

          Code:
          <bean id="persistenceManagerFactory" class="org.jpox.PersistenceManagerFactoryImpl">
            <property name="connectionFactory"><ref bean="dataSource"/></property>
            <property name="nontransactionalRead"><value>true</value></property>
          </bean>
          Option 3: Linking in a JCA PersistenceManagerFactory via Spring's JndiObjectFactoryBean. All configuration resides in the corresponding JCA deployment descriptor, managed by the J2EE server.

          Code:
          <bean id="persistenceManagerFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName"><value>java&#58;comp/env/...</value></property>
          </bean>
          We should probably add a discussion of these options to the reference docs or the wiki... We should also gather feedback on these options for various JDO implementations.

          Juergen

          Comment

          Working...
          X