help getting new HSQLDB XA DataSource working
blaine Mar 3, 2006 1:19 PM
I'm a developer in the HSQLDB Development Group. An associate and I have
made an XADataSource according to the javax.sql API spec and chapters 11
and 12 of the JDBC 3.0 Spec, but it is not working with JBoss. I have put
a lot of work into this, and I would greatly appreciate any advice or
assistance to help get it working.
According to the JBoss JCA FAQ, JBoss should drive "custom/thirdparty"
XADataSources "using the standard api". But the pooling callback mechanism
isn't working. I see that JBoss registers its ConnectionEventListeners as
it should, but it is impossible for my JDBC Driver's Connection
implementation to do its part, because
org.jboss.resource.adapter.jdbc.WrappedConnection seems to intercept
end-user calls to close(). My problems are specifically with javax.sql
pooling, not with XA-related classes, but if I understand the docs, JBoss
does not support straight javax.sql pooling other than through the
XAConnection subinterface. It would be great if I could work on the
PooledConnection problems directly without the unnecessary complexity of
global transactions.
Quoting the relevant statements from the JDBC spec:
The driver invokes the ConnectionEventListener methods
connectionClosed and connectionErrorOccurred when the corresponding
events occur. [Impossible for me to do if my driver's
Connection.close() is never invoked.]
The application server calls the method
PooledConnection.getConnection to get a logical Connection object...
The logical Connection object is returned to the JDBC client.
[JBoss is not returning my logical Connection object to the JDBC
client, but it's own WrappedConnection].
Here is exactly what I see:
In a JSP page, I get a UserTransaction from JNDI, get a Connection
from my XADataSource, execute some SQL, commit ut, close connection;
repeat. The connections are ConnectionWrappers holding Connection
instances from my driver. The Connections are "pooled" in that my
second getConnection reuses the physical connection from the first--
but the connection is not reset in between as it should be, because
my driver was never informed about the JSP's Connection.close().
The second JDBC session is the same as if I had continued to use
the original connection, instead of closing and re-opening (a bad
thing since Schemas and various back end resources need to be reset).
I then bypassed your ConnectionWrapper's interception of
Connection.close() by extracting my "logical Connection" from your
wrapper and invoking close() on that (as the JDBC spec says to do in
the second quote above). My JDBC driver then invokes your
connection manager's connectionClosed() method, as it should. But
your connection manager does no pooling in this case. According to
the JDBC Spec, the connection manager uses connectionClosed() to
find out that a LOGICAL connection is closed and then should use
its pooling algorithm to determine whether to reuse a connection or
get another physical connection from the ConnectionPoolDataSource or
XADataSource. Again, from the JDBC 3.0 Spec:
When the JDBC application closes its logical connection, the
JDBC driver notifies the connection pool manager (the listener)
by calling the listener's implementation of the method
connectionClosed. At htis point, the connection pool manager
can return the PooledConnection object to the pool for reuse.
but no connections are ever reused. Every time I run this modified
JSP (which avoids ConnectionWrapper's close() interceptions), your
connection manager requests two additional XA/PooledConnections
(which correspond to physical connections).