DB connections not closing in OSGi - osgi

I have an OSGi bundle which needs to persist data in a database. As described in a previous stackoverflow question I have found that in order for transactions to work as expected I need to use an XADataSource to connect to the database. When I do so however I see that the connections to the database that are opened by my application are never closed, which of course results in the database not being able to accept any more connections after a while.
My setup is the following:
I have a bundle which creates the datasource and which only includes a blueprint.xml file with the following content
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="dataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/myschema"/>
<property name="user" value="user"/>
<property name="password" value="pass"/>
</bean>
<service interface="javax.sql.XADataSource" ref="dataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="jdbc/mysqlds"/>
</service-properties>
</service>
</blueprint>
Then in the bundle that persists my data I have a persistence.xml
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="mypu" transaction-type="JTA">
<jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/mysqlds)
</jta-data-source>
</persistence-unit>
</persistence>
And I specify that my service methods should run in a transaction in my blueprint.xml
<bean id="MyServiceImpl"
class="com.test.impl.MyServiceImpl">
<jpa:context property="em" unitname="mypu" />
<tx:transaction method="*" value="Required" />
</bean>
<service id="MyService" ref="MyServiceImpl" interface="com.test.api.MyService" />
I deploy by bundles in Karaf, using Aries and OpenJPA for persistence, while I have also deployed the Aries transaction wrapper bundle (org.apache.aries.transaction.wrappers) in order to enlist my XA resources with the transaction manager.
Any ideas what I am missing in my configuration?
Edit:
After some more searching I found this DBCP issue which suggests that the problem I'm having is a bug of DBCP with MySQL. However I'm at a loss on how to replace DBCP with some other Connection Pool implementation OpenJPA can work with. Any suggestions are more than welcome.

I used commons-dbcp to have a connection pool that also enlists XA Connections with the following configuration:
<bean id="myXAEnabledConnectionPoolDataSource" class="org.apache.commons.dbcp.managed.BasicManagedDataSource" destroy-method="close">
<property name="xaDataSourceInstance" ref="mysqlXADataSourceBean" />
<property name="transactionManager" ref="transactionManager" />
</bean>
You can get the transaction manager as a reference based on the interface javax.transaction.TransactionManager.
In this way commons-dbcp will handle the lifecycle of the connections properly. Please note that the destroy method is there so when the blueprint container stops the connection pool will be closed.
Edit:
1-2 years ago I had the same problem but with PostgreSQL. I debugged aries.transaction.wrapper at that time a lot but I cannot remember exactly the cause why I left it out. I think the motivation was behind that commons-dbcp is a solution that worked for me in previous projects while I could not fix aries.transaction.wrapper even after analyzing it's code a lot.
Please note that MysqlDataSource is not a connection pool. It gives back a new connection always when you need one. It is also not XA enabled. MysqlXADatasource is XA enabled so you should probably instantiate an object from that class. However, an XADataSource is responsible only to give back XAConnections for you but not for enlisting them. That is where a ManagedConnectionPool can help. A managed connection pool does the followings:
Wraps all provided Connection objects with a custom managed connection class
In case close is called on a connection, it is not closed if there is an ongoing transaction. It is only closed (added back to the pool) when a transaction commit or rollback is done
In case a connection is queried from the pool and there was a connection also provided in the same transaction, the same transaction will be returned (that was a difficult sentence :))
Sometimes JDBC drivers provide connection pools and even managed connection pools, however, it is better to use the JDBC driver only to get new connections and wrap it with a 3rdparty library that was tested in several projects and works for sure.

Related

Hibernate, Spring and c3p0 connection pooling cause JBoss to opens too many connections to database

I have a strange problem with my application, running on JBoss 6.1, which uses Hibernate and Spring. I'm also using c3p0 to have connection pooling.
I have a datasource defined under JBoss. The datasource is a C3P0PooledDataSource. Please note that maxpoolsize is 20 and initial pool size is also 20.
<mbean code="com.mchange.v2.c3p0.jboss.C3P0PooledDataSource"
name="jboss.jca:service=DataSourceBinding,name=db/MED_POOLED">
<attribute name="JndiName">java:db/MED_POOLED</attribute>
<attribute name="JdbcUrl">jdbc:oracle:thin:#dbhost:1521:SID</attribute>
<attribute name="DriverClass">oracle.jdbc.driver.OracleDriver</attribute>
<attribute name="User">xxx</attribute>
<attribute name="Password">xxx</attribute>
<attribute name="AutomaticTestTable">POOL_TEST</attribute>
<attribute name="CheckoutTimeout">30000</attribute>
<attribute name="Description">Pooled Datasource for med</attribute>
<attribute name="IdleConnectionTestPeriod">180</attribute>
<attribute name="InitialPoolSize">20</attribute>
<attribute name="MaxPoolSize">20</attribute>
<attribute name="MinPoolSize">20</attribute>
<attribute name="TestConnectionOnCheckin">true</attribute>
<attribute name="MaxIdleTime">3600</attribute>
<depends>jboss:service=Naming</depends>
</mbean>
In my spring configuration file, datasource is retrieved using the jndi name:
<bean id="defaultDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>db/MED_POOLED</value></property>
</bean>
and then used to build a LocalSessionFactoryBean
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="defaultDataSource"/>
<property name="namingStrategy" ref="namingStrategy"/>
<property name="configLocations">
<list>
<value>classpath:hibernate.cfg.xml</value>
<value>classpath:jbpm.hibernate.cfg.xml</value>
</list>
</property>
<property name="mappingDirectoryLocations">
<list><value>WEB-INF/classes</value></list>
</property>
</bean>
In hibernate.cfg.xml no datasource is defined, so the dataSource property of org.springframework.orm.hibernate3.LocalSessionFactoryBean should be used.
When I start my application server, something strange happens (al least, strange to me):
JBoss starts, I see in the log this line
[com.mchange.v2.c3p0.jboss.C3P0PooledDataSource] Bound C3P0 PooledDataSource to name'java:db/MED_POOLED'. Starting...
and if I check on database, 20 sessions are present.
When the LocalSessionFactoryBean is created, suddendly 40 connections are present on Db, but in my datasource configuration I specified to create at maximum 20 connections.
I think that, in some way, the datasource is reinitialized when the LocalSessionFactoryBean is created, but I don't understand why, and when JBoss is started I have exactly double the connections I want.
Do you know what's happening? Is there something wrong with my configuration?
I'm using JBoss 6.1, the latest available version of c3p0 (0.9.5), Spring 3.0.3.RELEASE and Hibernate 3.5.3-Final
There are two likely ways that the number of Connections might be twice your expected pool size.
You might somehow be initializing two c3p0 DataSources;
You might be acquiring Connections for under two distinct authentications, by calling dataSource.getConnection( user, password )
The easiest way to check these two possibilities is via JMX: if the C3P0Registry MBean shows two distinct PooledDataSources, there's your problem. Otherwise, look for the property numUserPools inside your DataSource: is it two?
I'd examine those possibilities first.
[If you don't have access to JMX, you can see whether multiple DataSources get initialized by looking for log entries at INFO level from the logger named com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource, entries that begin with "Initializing c3p0 pool..." and then display the configuration of the pool being initialized.]
Another possibility is that for some reason your application is hot-redeploying, but as the old instance of the application is torn down, your c3p0 DataSource has not been closed. That will be harder to debug and lead to quirky behavior in general if c3p0's classes are loaded by multiple distinct ClassLoaders. (I don't know enough about whether/how JBoss implements hot-redeploy to know whether this is likely to be a problem.) One way to avoid this kind of issue would be to be sure that c3p0's jar files are made available at the application server level, not subsidiary to any particular application, and then set the c3p0 [0.9.5] config parameter contextClassLoaderSource to library, see http://www.mchange.com/projects/c3p0/#contextClassLoaderSource

Unexpected problems with JBoss connection pooling

I've spend the last days trying to locate the cause of some new problem during development that raised a few days ago... and I've not found it yet. But I've found a workaround. But let's start with the problem itself.
We are using JBoss EAP 6.1.0.GA (AS 7.2.0.Final-redhat-8) as our application server for a quite large enterprise project. The JPA layer is handled by Hibernate Core {4.2.0.Final-redhat-1} using oracle.jdbc.OracleDriver (Version 11.2) connecting Oracle 11.2.0.3.0.
A few weeks ago everything worked as expected and we had no database related problems. We were using the following datasource:
<datasource jta="true" jndi-name="java:/myDS" pool-name="myDS" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:oracle:thin:#192.168.0.93:1521:DEV</connection-url>
<driver>oracle</driver>
<transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
<pool>
<min-pool-size>1</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
<use-strict-min>false</use-strict-min>
<flush-strategy>FailingConnectionOnly</flush-strategy>
</pool>
<security>
<user-name>MY_DB</user-name>
<password>pass</password>
</security>
</datasource>
Most of the time we had 5-10 open connections with 1-3 in use (single development environment)... the pool held that level and worked just fine.
But with some unknown changes to our code that pool stopped working... didn't release it connections anymore... even did not re-use them at all! It took a few simple requests to fill the pool up to the maximum of 20 connections and JPA refused any new database queries.
We've spend several days to find the relevant changes to our code... without success!
Today I've discovered a workaround. We changes persistence.xml a little bit:
<persistence-unit name="myPU">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/myDS</jta-data-source>
<properties>
<property name="jboss.entity.manager.factory.jndi.name" value="java:/myDSMF" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
<property name="hibernate.default_batch_fetch_size" value="1000" />
<property name="hibernate.jdbc.batch_size" value="0" />
<property name="hibernate.connection.release_mode" value="after_statement" />
<!-- <property name="hibernate.connection.release_mode" value="after_transaction" /> -->
<property name="hibernate.connection.SetBigStringTryClob" value="true" />
</properties>
</persistence-unit>
Changing hibernate.connection.release_mode from after_transaction to after_statement did the trick. But that setting has never been touched before. Now connections are released as expected and the pooling is usable again.
I don't get why after_transaction doesn't work anymore... because changes are committed. We see all these things in the database. And committing a transaction should end it - doesn't it?
Although I've found that simple workaround I'd really get to know the problem. I've no good feeling to delay that knowledge until production time. So any feedback is very well appreciated! Thanks!
You are using JTA . So after_transaction mode in never recommended for JTA transactions.
Here is the document from JBOSS site.
after_transaction - says to use
ConnectionReleaseMode.AFTER_TRANSACTION. This setting should not be
used in JTA environments. Also note that with
ConnectionReleaseMode.AFTER_TRANSACTION, if a session is considered to
be in auto-commit mode connections will be released as if the release
mode were AFTER_STATEMENT.
so you should either use auto or after_statement explicitly, to aggressively release the connection.
References
Connection Release Modes.

How do I access TomEE's JTA transaction manager?

I have an application that uses Spring's declarative transaction management. How can I deploy this in a TomEE+ container so that the application uses TomEE's JTA transaction manager?
More specifically, how can I refer to the built-in transaction manager from within Spring's "application-context.xml" file?
Spring's transaction management configuration seems to want to look up the transaction manager either by a bean reference or by JNDI lookup; I have spent a day researching this and looking at source code; I have found a lot of discussion of the issue (references below) but no definitive how-to.
What I have in the application's META-INF/persistence.xml is this:
<persistence-unit name="myPersistenceUnit" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>myDs-managed</jta-data-source>
<non-jta-data-source>myDs-unmanaged</non-jta-data-source>
<properties>
<property name="openjpa.jdbc.DBDictionary"
value="org.apache.openjpa.jdbc.sql.PostgresDictionary"/>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
<property name="openjpa.Run
<property name="openjpa.Log" value="slf4j" />
</properties>
</persistence-unit>
And, in the applications META-INF/spring/applicationContext.xml file I have this: (I have tried various values for transactionManagerName as suggested in various discussions of the topic, as it appears to be non-standard across application servers
<tx:annotation-driven mode="aspectj" transaction-manager="txManager" />
<bean class="org.springframework.transaction.jta.JtaTransactionManager"
id="txManager">
<property name="transactionManagerName"
value=" java:comp/TransactionManager"/>
</bean>
Here's an example that is claimed to work for JBoss: Spring JTA configuration - how to set TransactionManager?
Here's a near miss that won't work in an xml configuration file: https://issues.apache.org/jira/browse/TOMEE-38
Here's how to do it within java code if you have your hands on initialContext: http://osdir.com/ml/users.openejb.apache.org/2012-11/msg00110.html
[Edit: The Tomee documentation talks about how to declare a transaction manager, but it says to do it in Tomee.xml, which belongs to the server and not to the individual webapp; I want to configure the transaction manager for a single app and not for the whole server: http://tomee.apache.org/containers-and-resources.html]
Have you tried java:comp/env/TransactionManager for the transactionManagerName?
,
Also have you declared the TransactionManager and DataSource as described here: http://tomee.apache.org/containers-and-resources.html?

spring transactional cpool. Which one do I use?

I originally set up spring with xapool, but it turns out that's a dead project and seems to have lots of problems.
I switched to c3p0, but now I learn that the #Transactional annotations don't actually create transactions when used with c3p0. If I do the following it will insert the row into Foo even through an exception was thrown inside the method:
#Service
public class FooTst
{
#PersistenceContext(unitName="accessControlDb") private EntityManager em;
#Transactional
public void insertFoo() {
em.createNativeQuery("INSERT INTO Foo (id) VALUES (:id)")
.setParameter("id", System.currentTimeMillis() % Integer.MAX_VALUE )
.executeUpdate();
throw new RuntimeException("Foo");
}
}
This is strange because if I comment out the #Transactional annotation it will actually fail and complain about having a transaction set to rollback only:
java.lang.IllegalStateException: Cannot get Transaction for setRollbackOnly
at org.objectweb.jotm.Current.setRollbackOnly(Current.java:568)
at org.hibernate.ejb.AbstractEntityManagerImpl.markAsRollback(AbstractEntityManagerImpl.java:421)
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:576)
at org.hibernate.ejb.QueryImpl.executeUpdate(QueryImpl.java:48)
at com.ipass.rbac.svc.FooTst.insertFoo(FooTst.java:21)
at com.ipass.rbac.svc.SingleTst.testHasPriv(SingleTst.java:78)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.test.context.junit4.SpringTestMethod.invoke(SpringTestMethod.java:160)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTestMethod(SpringMethodRoadie.java:233)
at org.springframework.test.context.junit4.SpringMethodRoadie$RunBeforesThenTestThenAfters.run(SpringMethodRoadie.java:333)
at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:217)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:197)
at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:143)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:160)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:97)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
So, clearly it notices the #Transactional annotation. But, it doesn't actually set autocommit to off at the start of the method.
Here is how I have transactional stuff setup up in the applicationContext.xml. Is this correct? If not, what is this supposed to be?
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="jotm"/>
<property name="userTransaction" ref="jotm"/>
<property name="allowCustomIsolationLevels" value="true"/>
</bean>
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="false"/>
After a bunch of searching I found a connection pool called Bitronix, but their spring setup page describes stuff about JMS which doesn't even make any sense. What does JMS have to do with setting up a connection pool?
So I'm stuck. What am I actually supposed to do? I don't understand why the connection pool needs to support transactions. All connections support turning autocommit on and off, so I have no idea what the problem is here.
It took a lot of searching and experimentation, but I finally got things working. Here are my results:
enhydra xapool is a terrible connection pool. I won't enumerate the problems it caused because it doesn't matter. The latest version of that pool hasn't been updated since Dec 2006. It's a dead project.
I put c3p0 into my application context and got it working fairly easily. But, for some reason it just doesn't seem to support rollback even inside a single method. If I mark a method as #Transactional then do an insert into a table and then throw a RuntimeException (one that's definitely not declared in the throws list of the method because there is no throws list on the method) it will still keep the insert into that table. It will not roll back.
I was going to try Apache DBCP, but my searching turned up lots of complaints about it, so I didn't bother.
I tried Bitronix and had plenty of trouble getting it to work properly under Tomcat, but once I figured out the magic configuration it works beautifully. What follows is all the things you need to do to set it up properly.
I dabbled briefly with the Atomkos connection pool. It looks like it should be good, but I got Bitronix working first, so I didn't try using it much.
The configuration below works in standalone unit tests and under Tomcat. That was the major problem I had. Most of the examples I found about how to set up Spring with Bitronix assume that I'm using JBoss or some other full container.
The first bit of configuration is the part that sets up the Bitronix transaction manager.
<!-- Bitronix transaction manager -->
<bean id="btmConfig" factory-method="getConfiguration" class="bitronix.tm.TransactionManagerServices">
<property name="disableJmx" value="true" />
</bean>
<bean id="btmManager" factory-method="getTransactionManager" class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig" destroy-method="shutdown"/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="btmManager" />
<property name="userTransaction" ref="btmManager" />
<property name="allowCustomIsolationLevels" value="true" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
The major difference between that code and the examples I found is the "disableJmx" property. It throws exceptions at runtime if you don't use JMX but leave it enabled.
The next bit of configuration is the connection pool data source. Note that the connection pool classname is not the normal oracle class "oracle.jdbc.driver.OracleDriver". It's an XA data source. I don't know what the equivalent class would be in other databases.
<bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close">
<property name="uniqueName" value="dataSource-BTM" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="4" />
<property name="testQuery" value="SELECT 1 FROM dual" />
<property name="driverProperties"><props>
<prop key="URL">${jdbc.url}</prop>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
</props></property>
<property name="className" value="oracle.jdbc.xa.client.OracleXADataSource" />
<property name="allowLocalTransactions" value="true" />
</bean>
Note also that the uniqueName needs to be different than any other data sources you have configured.
The testQuery of course needs to be specific to the database that you are using. The driver properties are specific to the database class that I'm using. OracleXADataSource for some silly reason has different setter names for OracleDriver for the same value.
The allowLocalTransactions had to be set to true for me. I found recommendations NOT to set it to true online. But, that seems to be impossible. It just won't work if it's set to false. I am not sufficiently knowledgeable about these things to know why that is.
Lastly we need to configure the entity manager factory.
<util:map id="jpa_property_map">
<entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.BTMTransactionManagerLookup"/>
<entry key="hibernate.current_session_context_class" value="jta"/>
</util:map>
<bean id="dataSource-emf" name="accessControlDb" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="classpath*:META-INF/foo-persistence.xml" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect"/>
</bean>
</property>
<property name="jpaPropertyMap" ref="jpa_property_map"/>
<property name="jpaDialect"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/></property>
</bean>
Note the dataSource property refers to the id of the dataSource I declared. The persistenceXmlLocation refers to a persistence xml file that exists in the classpath somewhere. The classpath*: indicates it may be in any jar. Without the * it won't find it if it's in a jar for some reason.
I found util:map to be a handy way to put the jpaPropertyMap values in one place so that I don't need to repeat them when I use multiple entity manager factories in one application context.
Note that the util:map above won't work unless you include the proper settings in the outer beans element. Here is the header of the xml file that I use:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
Lastly, in order for Bitronix (or apparently any cpool which supports two phase commit) to work with Oracle you need to run the following grants as user SYS. (See http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/rtrb_dsaccess2.html and http://docs.codehaus.org/display/BTM/FAQ and http://docs.codehaus.org/display/BTM/JdbcXaSupportEvaluation#JdbcXaSupportEvaluation-Oracle)
grant select on pending_trans$ to <someUsername>;
grant select on dba_2pc_pending to <someUsername>;
grant select on dba_pending_transactions to <someUsername>;
grant execute on dbms_system to <someUsername>;
Those grants need to be run for any user that a connection pool is set up for regardless of whether you actually do any modifying of anything. It apparently looks for those tables when a connection is established.
A few other misc issues:
You can't query tables which are remote synonyms in Oracle while inside a Spring #Transactional block while using Bitronix (you'll get an ORA-24777). Use materialized views or a separate EntityManager which directly points at the other DB instead.
For some reason the btmConfig in the applicationContext.xml has problems setting config values. Instead create a bitronix-default-config.properties file. The config values you can use are found at http://docs.codehaus.org/display/BTM/Configuration13 . Some other config info for that file is at http://docs.codehaus.org/display/BTM/JdbcConfiguration13 but I haven't used it.
Bitronix uses some local files to store transactional stuff. I don't know why, but I do know that if you have multiple webapps with local connection pools you will have problems because they will both try to access the same files. To fix this specify different values for bitronix.tm.journal.disk.logPart1Filename and bitronix.tm.journal.disk.logPart2Filename in the bitronix-default-config.properties for each app.
Bitronix javadocs are at http://www.bitronix.be/uploads/api/index.html .
That's pretty much it. It's very fiddly to get it to work, but it's working now and I'm happy. I hope that all this helps others who are going through the same troubles I did to get this all to work.
When I do connection pooling I tend to use the one provided by the app server I'm deploying on. It's just a JNDI name to Spring at that point.
Since I don't want to worry about an app server when I'm testing, I use a DriverManagerDataSource and its associated transaction manager when I'm unit testing. I'm not as concerned about pooling or performance when testing. I do want the tests to run efficiently, but pooling isn't a deal breaker in that case.

Validating Connection Before Handing over to WebApp in ConnectionPooling

I have connection pooling implemented in spring using Oracle Data Source. Currently we are facing an issue where connections are becoming invalid after a period of time. (May be Oracle is dropping those idle connections after a while). Here are my questions:
Can Oracle database be configured to drop idle connections automatically after a specific period of time. Since we expect those connections to lie idle for a while; if there is any such configuration; it may be happening.
In our connection pooling properties in spring we didn't have "validateConnection" property. I understand that it validates the connection before handing it over to web application? But does that mean that if a connection passes validateConnection test then it'll always connect to database correctly. I ask this, as I read following problem here:
http://forum.springsource.org/showthread.php?t=69759
If suppose validateConnection doesn't do the whole 9 yards of ensuring that connection is valid, is there any other option like "testBeforBorrow" in DBCP , which runs a test query to ensure that connection is active before handing it over to webapp?
I'll be grateful if you could provide answers to one ore more queries listed above.
Cheers
You don't say what application server you are using, or how you are configuring the datasource, so I can't give you specific advice.
Connection validation often sounds like a good idea, but you have to be careful with it. For example, we once used it in our JBoss app servers to validate connections in the pool before handing them to the application. This Oracle-proprietary mechanism used the ping() method on the Oracle JDBC driver, which checks that the connection is still alive. It worked fine, but it turns out that ping() executes "select 'x' from dual' on the server, which is a surprisingly expensive query when it's run dozens of times per second.
So the moral is, if you have a high-traffic server, be very careful with connection validation, it can actually bring your database server to its knees.
As for DBCP, that has the ability to validate connections as their borrowed from the pool, as well as returned to the pool, and you can tell it what SQL to send to the database to perform this validation. However, if you're not using DBCP for your connection pooling, then that's not much use to you. C3PO does something similar.
If you're using an app server's data source mechanism, then you have to find out if you can configure that to validate connections, and that's specific to your server.
One last thing: Spring isn't actually involved here. Spring just uses the DataSource that you give it, it's up to the DataSource implementation to perform connection validation.
Configuration of data source "was" as follows:
<bean id="datasource2"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>org.apache.commons.dbcp.BasicDataSource</value>
</property>
<property name="url">
<value>ORACLE URL</value>
</property>
<property name="username">
<value>user id</value>
</property>
<property name="password">
<value>user password</value>
</property>
<property name="initialSize" value="5"/>
<property name="maxActive" value="20"/>
</bean>
have changed it to:
<bean id="connectionPool1" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
<property name="connectionCachingEnabled" value="true" />
<property name="URL">
<value>ORACLE URL</value>
</property>
<property name="user">
<value>user id</value>
</property>
<property name="password">
<value>user password</value>
</property>
<property name="connectionCacheProperties">
<value>
MinLimit:1
MaxLimit:5
InitialLimit:1
ConnectionWaitTimeout:120
InactivityTimeout:180
ValidateConnection:true
</value>
</property>
</bean>

Resources