On 06/21/2012 08:47 AM, Christian Romberg wrote:
> Hi Jonathan,
>
> I agree, that extending XAResource or the enlistResource call are far
> superior to what I have suggested, however IMO it would also mean
> more work for all existing implementation. (Btw. I'm curious to know,
> how many implementations, which have really seen
> production use, are there at all?)
The JTA impl is really split betweem TM and RM.
Current implementations of a transaction manger? one from IBM, two or
three from Oracle (mostly by acquisition), one from JBoss and around
four from smaller players.
The number of XAResource implementations is larger though. Perhaps a
hundred spread over JDBC drivers, JMS and JCA connector implementations?
The cross product of those TMs and RMs is large enough to cause
headaches for sure, but it should be possible to do recovery wiring in a
backwards compatible way so the implementations can take place
incrementally.
Much as I'd like to get recovery wiring fixed I can't help thinking the
solution would be more elegant if we wait for the Java SE changes that
will facilitate extending interfaces by providing default method
implementations. Without that we'll wind up back in
TransactionSynchronizationRegistry territory, which is not a
particularly pleasant prospect.
>
> I could imagine, that all ResourceManagers in a system could be required
> to register similar to e.g. either the mechanism used
> for JDBC drivers or for different JPA implementations, and they could
> implement something like this
>
> interface Recovery {
> XAResource getXAResource(byte[] recoveryInformation); //returns
> null, if recoveryInformation is from a different implementation
> }
>
> XAResource could be extended as follows:
>
> interface XAResource {
> //...
> byte[] getRecoveryInformation()
> }
>
> The result of getRecoveryInformation() would be opaque and stored in the
> transaction log file of the transaction manager.
> Each Resource Manager would be responsible to include all information it
> needs in there.
>
> Through the "resource manager registry" they could be probed later with
> exactly this information and be required, to
> determine, is it their information or that of a different resource manager.
> If it's their information, they are required to return an XAResource
> instance that can be used for recovery.
> If they return null, the next registered resource manager is probed.
I'm averse to anything that requires additional bytes to be forced to
disk on each transaction. It's not necessary for obtaining the in-doubt
list from an RM. For that you need only one XAResource for the entire
RM, not one per tx.
TransactionManager.registerForRecovery(XAResource xaResource)
to be called y the container at datasource deployment time appears at
first glance to be reasonable. Turns out it's not sufficient though.
First up you also need to cope with deregistration so that
datasources/connectors can be undeployed without a restart of the
container. Then you need to cope with XAResources that get stale over
time e.g. because the RM bounced and the TCP connection they are sitting
on is now invalid. We could force RM implementers to mask that, but
better to allow the TM to retrieve a fresh XAResource as needed
TransactionManager.registerForRecovery(XARecovery recovery)
TransactionManager.unregisterFromRecovery(XARecovery recovery)
interface XARecovery {
XAResource getXAResource(); // to be called by the TM's recovery system.
}
which then leaves you with thorny questions about how and when to
release the XAResource so they don't leak. Still, you see where I'm
going with this - it avoids any additional logging so the recovery
overhead is not proportional to the transaction rate.
Of course for cases where you want to automatically recognise and delete
a TM log entry for a branch the RM has already committed, then you do
need data that will associate a recovery XAResource with the log entry.
That's where the JNDI name thing comes in, although it may also be
possible to do clever things with Xid encoding in some cases. Right now
we basically extend XAResource
interface AnnotatedXAResource extends XAResource {
byte[] getJNDIName()
}
clearly with interface extension methods we'd be able to put that new
method direct on XAResource rather than needing a subclass, but we have
to work with what we've got.
Jonathan.
--
Registered in England and Wales under Company Registration No. 03798903
Directors: Michael Cunningham (USA), Mark Hegarty (Ireland), Matt Parson
(USA), Charlie Peters (USA)