I recently changed from using Spring's local transactions to Jencks' JTA transactions and I've run into a problem where the number of database connections that are open explodes as my unit and integration tests run. I made the change because I'm using both JDO and JCA (Apache's Jackrabbit) in my project, and I'd like them to participate in the same transaction, while still running in Tomcat 5.5. I've tried changing the settings for the pooling and thread/ transaction caching, but nothing has worked yet.

My integration tests are set up in some 15 files, with each file having anywhere from 1 to more than 20 tests. Some files have a setup and teardown process that requires transactions to put data into the JDO or JCA store (to test queries); in many cases, two transactions are used both setup and tear down, plus a separate transaction for the actual test. By the time my unit tests finish, I'm seeing more than 50 open connections to PostgreSQL (based on the number of postgresql processes running). In some build situations (such as generating the maven site), I'm running out of database connections (the unit tests are run twice) which causes the tests to lock until a connection becomes available (occasionally maven crashes with a bus error at this point). When maven exits, all the connections are closed.

I've included the configuration I'm using below. You can see that both JDO and Jackrabbit are configured to use Spring's JtaTransactionManager, which in turn is configured to use Jencks' GeronimoTransactionManagerFactoryBean and TransactionManagerFactoryBean.

If anyone could point me in the right direction on this, I'd really appreciate it. Also, if Jecnks isn't the best way to accomplish this, and it would be better in this case for me to use a full app server like JBoss or Geronimo, that'd be good to know too.

Thanks,
Mark

<bean id="connectionTracker"
class="org.apache.geronimo.connector.outbound.connectiontracking.Connect ionTrackingCoordinator"
    />

<bean id="transactionContextInitializer"
    class="org.jencks.interceptor.TransactionContextInitializer">
    <property name="associator">
        <ref local="connectionTracker" />
    </property>
</bean>

<bean id="transactionManagerImplementation"
    class="org.jencks.factory.TransactionManagerFactoryBean">
    <property name="defaultTransactionTimeoutSeconds">
        <value>600</value>
    </property>
    <property name="transactionLog">
<bean class="org.apache.geronimo.transaction.log.UnrecoverableLog" />
    </property>
</bean>

<bean id="transactionContextManager"
    class="org.jencks.factory.TransactionContextManagerFactoryBean">
    <property name="transactionManager">
        <ref local="transactionManagerImplementation" />
    </property>
</bean>

<bean id="userTransaction" class="org.jencks.factory.GeronimoTransactionManagerFactoryBean">
    <property name="transactionContextManager">
        <ref local="transactionContextManager" />
    </property>
</bean>

<!-- The global transaction manager -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="userTransaction">
        <ref local="userTransaction" />
    </property>
    <property name="transactionManager">
        <ref local="transactionManagerImplementation" />
    </property>
</bean>

<bean id="transactionSupport" class="org.jencks.factory.XATransactionFactoryBean">
    <property name="useTransactionCaching">
        <value>true</value>
    </property>
    <property name="useThreadCaching">
        <value>true</value>
    </property>
</bean>

<bean id="poolingSupport" class="org.jencks.factory.SinglePoolFactoryBean">
    <property name="maxSize">
        <value>1</value>
    </property>
    <property name="minSize">
        <value>1</value>
    </property>
    <property name="blockingTimeoutMilliseconds">
        <value>60</value>
    </property>
    <property name="idleTimeoutMinutes">
        <value>1</value>
    </property>
    <property name="matchOne">
        <value>true</value>
    </property>
    <property name="matchAll">
        <value>true</value>
    </property>
    <property name="selectOneAssumeMatch">
        <value>true</value>
    </property>
</bean>

<bean id="connectionManager" class="org.jencks.factory.ConnectionManagerFactoryBean">
    <property name="transactionSupport">
        <ref local="transactionSupport" />
    </property>
    <property name="poolingSupport">
        <ref local="poolingSupport" />
    </property>
    <property name="transactionContextManager">
        <ref local="transactionContextManager" />
    </property>
    <property name="connectionTracker">
        <ref local="connectionTracker" />
    </property>
</bean>

<!-- Define the Persistance Manager Factory -->
<bean id="persistenceManagerFactoryTarget"
class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
    <property name="configLocation">
        <value>classpath:jdo.properties</value>
    </property>
</bean>

<bean id="persistenceManagerFactory"
class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFac toryProxy">
    <property name="targetPersistenceManagerFactory">
        <ref local="persistenceManagerFactoryTarget" />
    </property>
    <property name="allowCreate">
        <value>false</value>
    </property>
</bean>

<!-- The generic DAO Transaction Proxy bean. All DAO instances are children of this bean. -->
<bean id="daoTransactionProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFacto ryBean"
        abstract="true">
    <property name="transactionManager">
        <ref local="transactionManager" />
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="store*">PROPAGATION_REQUIRED</prop>
            <prop key="find*">PROPAGATION_REQUIRED</prop>
            <prop key="delete*">PROPAGATION_REQUIRED</prop>
            <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
        </props>
    </property>
</bean>

<!-- All DAO beans here -->
...

<!-- JCA (Jackrabbit) configuration -->
<bean id="repositoryManagedConnectionFactory"
    class="org.apache.jackrabbit.jca.JCAManagedConnectionFactory">
    <property name="homeDir">
        <ref bean="repositoryDirectoryLocation" />
    </property>
    <property name="configFile">
<bean factory-bean="repositoryConfigurationResource" factory- method="getPath" />
    </property>
</bean>

<bean id="whisperContentRepository"
    class="org.springframework.jca.support.LocalConnectionFactoryBean">
    <property name="managedConnectionFactory">
        <ref local="repositoryManagedConnectionFactory" />
    </property>
    <property name="connectionManager">
        <ref bean="connectionManager" />
    </property>
</bean>

Reply via email to