Hi,
On 05/10/2016 09:58 AM, Scott Marlow wrote:
On 05/05/2016 01:48 PM, Jesper Pedersen wrote:
>> 6. transaction enlistment
>>
>
> This will vary for each store, and there are many loopholes that you may
> want to plug, f.ex. sharing a connection between 2 transactions.
>
> For 1-phase, you will have to insert a LocalXAResource instance into the
> transaction when the "connection" is obtained, and return it on the
> boundary (afterCompletion). Same deal for 2-phase basically.
>
> The LocalXAResource implementation will of course be different for each
> store.
Any links to existing IronJacamar code to share here? I think that we
could prototype new transaction enlistment handling code, based on what
we currently have.
The IronJacamar code is here for Narayana:
https://github.com/ironjacamar/ironjacamar/tree/master/core/src/main/java...
However, that is based on the Java EE Connector Architecture
specification, so we have a *much* easier job.
Lets take an example from the NoSQL world using Neo4J:
http://neo4j.com/docs/api/java-driver/current/org/neo4j/driver/v1/Driver....
...neo4j.LocalXAResource implements XAResource, org.jboss.tm.LastResource
public void start(Xid xid, int flags) throws XAException {
tx = session.beginTransaction();
}
public void commit(Xid xid, boolean onePhase) throws XAException {
tx.success();
}
public void rollback(Xid xid) throws XAException {
tx.failure();
}
And the app, f.ex. in a SLSB method
public class MySLSB ...
@Resource(mappedName="java:jboss/nosql/neo4j")
private Driver neo4j;
public void myMethod() {
#1 Session s = neo4j.createSession();
s.run( "CREATE (n {name:'Bob'})" );
#2 Transaction tx = s.beginTransaction();
tx.run( "CREATE (n {name:'Alice'})" );
tx.run( "CREATE (n {name:'Tina'})" );
#3 tx.success();
#4 tx.close();
#5 s.close();
#6 neo4j.close();
}
However, as you can see there are a number of hidden things going on
here if ".../neo4j" is deployed as "transaction=1phase".
#1: Here you have to intercept the call, create the LocalXAResource
instance and enlist it in the active transaction
#2: Here you have to a delegator instance that only executes the run() calls
#3: No-op call, happens upon EE transaction completion
#4: No-op call. happens upon EE transaction completion
#5: No-op call, happens in an enlisted Synchronization instance
(afterCompletion) (done in #1 too)
#6: No-op call, handled by subsystem
The value-add is that #3 is tied into the overall EE transaction.
If ".../neo4j" is deployed as "transaction=none", then all calls are
on
the "real" Neo4J objects.
As you can see it isn't as simple as it may appear, and application flow
could be different from what the developer expects, as #3 could be a
real tx.failure() call in case of MARKED_FOR_ROLLBACK.
There are def pros/cons of doing tx enlistment for this area...
>
> You may want a transaction option for the stores that supports this such
> that people can choose the "level" of enlistment (ala
jta="false").
>
> One task I see is that people will have access to the transactional
> methods in the API, and you don't want them to call these methods in
> their apps unless the transaction setting allows this.
>
> I think you can leave out the corner-cases in the 1st iteration, like
> deferred enlistment (get connection, start transaction).
Best regards,
Jesper