Looking a little farther into the geronimo tm code enlist method...
TransactionBranch manager = suspendedXaResources.remove(xaRes);
if (manager != null) {
//we know about this one, it was suspended
xaRes.start(manager.getBranchId(), XAResource.TMRESUME);
activeXaResources.put(xaRes, manager);
return true;
}
//it is not suspended.
for (Iterator i = resourceManagers.iterator(); i.hasNext();) {
manager = (TransactionBranch) i.next();
boolean sameRM;
//if the xares is already known, we must be resuming after a
suspend.
if (xaRes == manager.getCommitter()) {
throw new IllegalStateException("xaRes " + xaRes + " is a
committer but is not active or suspended");
}
(ending with what you quoted) note that if the xaresource had been suspended
we would already have returned true.
The "happy" sequence of calls to the tx is supposed to be like this:
tx.enlist(xares) >> xares.begin(xid, TMNOFLAGS or TMJOIN)
tx.delist(xares, TMSUSPEND) >>xares.end(xid, TMSUSPEND)
repeat as often as desired:
tx.enlist(xares) >> xares.begin(xid, TMRESUME)
tx.delist(xares, TMSUSPEND) >> xares.end(xid, TMSUSPEND)
when you are done
tx.delist(xares, TMSUCCESS) >> xares.end(xid, TMSUCCESS)
commit.
Note the end(TMSUSPEND) immediately followed by end(TMSUCCESS).
Geronimo's connection pooling together with the tranql jdbc wrappers do it
correctly, but the released versions may not be that easy to set up in osgi by
themselves. I have a sandbox version that is a lot more osgi friendly but
haven't worked on it in a long time - not even sure if it builds at the moment.
https://svn.apache.org/repos/asf/geronimo/sandbox/djencks/txmanager
hope this helps
david jencks
On Sep 13, 2012, at 11:30 AM, David Jencks wrote:
> Hi James,
>
> An XAConnection is required to always use the same XAResource, so that part
> of their code is good.
>
> I think the problem is here:
>
> tx.delistResource(xac.getXAResource(), XAResource.TMSUCCESS);
>
>
> on connection handle close.
> The TMSUCCESS flag means the next thing you're going to do on the tx is end
> it (commit or rollback). If you then try to re-enlist it that's an error
> (IIRC).
>
> I think they should be using a different flag here. Haven't had time to look
> into it in detail though....
>
> david jencks
>
>
> On Sep 13, 2012, at 4:41 AM, James Carman wrote:
>
>> I am trying to use enhydra's connection pool/XA support for our
>> project. It's a ServiceMix-based project, so we're using Aries'
>> "wrapper" around Geronimo's transaction manager. Anyway, what I'm
>> seeing is that their XA code seems to be trying to re-enlist the same
>> connection. Unfortunately, they re-use the same XAResource instance,
>> so I run into this bit of code causing me an error:
>>
>> if (xaRes == manager.getCommitter()) {
>> throw new IllegalStateException("xaRes " + xaRes + " is a committer
>> but is not active or suspended");
>> }
>>
>> Their connection code looks like this:
>>
>>
>> public class StandardXAConnection
>> extends StandardPooledConnection
>> implements XAConnection, XAResource, Referenceable, Runnable {
>>
>> ...
>>
>> /**
>> * We are required to maintain a 1-1 mapping between an XAConnection
>> * and its corresponding XAResource. We achieve this by implementing
>> * both interfaces in the same class.
>> */
>> public XAResource getXAResource() {
>> return this;
>> }
>> }
>>
>> What I'm trying to understand is if they're attempting to do something
>> silly here or if I have something mis-configured. We're using OpenJPA
>> and when it goes to close the connection (after it uses it for a
>> query), enhydra delists it from the current transaction. Inside their
>> DataSource's "connectionClosed" method:
>>
>> if ((tx != null) && (((StandardXAConnection)
>> xac).connectionHandle.isReallyUsed)) {
>> try {
>> tx.delistResource(xac.getXAResource(), XAResource.TMSUCCESS);
>> // delist the xaResource
>> log.debug(
>> "StandardXAPoolDataSource:connectionClosed the resourse is
>> delisted");
>> } catch (Exception e) {
>> log.error(
>> "StandardXAPoolDataSource:connectionClosed Exception in
>> connectionClosed:"
>> + e);
>> }
>> }
>>
>> Does this all make sense? Is there something I need to configure to
>> allow re-enlistment of resources or are they just doing something
>> bone-headed here?
>