Enhydra enlist/delist/enlist woes...

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Enhydra enlist/delist/enlist woes...

James Carman
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?
Reply | Threaded
Open this post in threaded view
|

Re: Enhydra enlist/delist/enlist woes...

David Jencks
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?

Reply | Threaded
Open this post in threaded view
|

Re: Enhydra enlist/delist/enlist woes...

David Jencks
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?
>

Reply | Threaded
Open this post in threaded view
|

Re: Enhydra enlist/delist/enlist woes...

James Carman
Thanks, David!

So, I found tranql in the maven repository, but the docs on the site
(http://tranql.codehaus.org/) are quite spotty.  I see some
sqlserver-specific jars in the repo.  I'm wondering if I need those.
Anyway, do you know of any better docs out there for this?

Thanks,

James

On Thu, Sep 13, 2012 at 3:05 PM, David Jencks <[hidden email]> wrote:

> 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?
>>
>
Reply | Threaded
Open this post in threaded view
|

Re: Enhydra enlist/delist/enlist woes...

David Jencks
I don't think there are better docs :-)

I think I might have included the basics for @Datasource support in my geronimo tm sandbox, in which case I think you can set up a datasource using the "common" tranql bundle and a suitable configuration that specifies the info that would have come from the @Datasource annotation.  It's been a long time though and I can't look into it right now :-(

david jencks

On Sep 13, 2012, at 12:50 PM, James Carman wrote:

> Thanks, David!
>
> So, I found tranql in the maven repository, but the docs on the site
> (http://tranql.codehaus.org/) are quite spotty.  I see some
> sqlserver-specific jars in the repo.  I'm wondering if I need those.
> Anyway, do you know of any better docs out there for this?
>
> Thanks,
>
> James
>
> On Thu, Sep 13, 2012 at 3:05 PM, David Jencks <[hidden email]> wrote:
>> 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?
>>>
>>