Hi Gunnar/Emmanuel,
The Ne04j profile can either be "transaction=1pc" (JTA transaction
enlisted) or "transaction=none" (will not be enlisted into JTA
transaction). I think this covers what Emmanuel suggested (I didn't get
Emmanuel's email yet for some unknown reason).
It sounds like we aren't yet connecting on what the WF Neo4j profile is
doing, so I'll respond below and we can continue from there. :)
On 07/13/2016 01:16 PM, Gunnar Morling wrote:
Hi Scott,
I had a short look at the tests you pointed to; in the one using BMT,
why is it that the UserTransaction *and* the Neo4j TX API are used? I'd
have expected it to be only one *or* the other?
With both container managed transactions and bean managed transactions
(BMT), a JTA transaction is in control of the transaction. With BMT,
UserTransaction is used by the application code to start/end the
transaction. In either case (BMT or CMT), the Neo4j TX API is
controlled by the JTA transaction.
If there isn't an active JTA transaction, the Ne04j TX API is in control
of the Neo4j transaction. With one caveat, that the Ne04j transaction
should be ended by the application code, before entering into a JTA
transaction (since it won't be joined into the JTA transaction).
Users can also disable the JTA transaction enlistment by using a NoSQL
profile with "transaction=none", instead of "transaction=1pc".
In the one using CMT, there are also calls to the Neo4j TX API which
apparently are ignored.
With CMT + BMT, the JTA transaction is in control, when the JTA
transaction ends, the Neo4j transaction ends as well and not before
then. If the application calls the Neo4j TX API, our TXProxy ignores
calls to TX.success/failure/close, other calls are passed through to the
underlying Neo4j Transaction object (e.g. run(String statement)), since
that is where the work actually occurs.
When the JTA transaction commits, the underlying Neo4j tx.success() +
tx.close() are called. If the JTA transaction rolls back, the
underlying Neo4j tx.failure() + tx.close() are called.
What's the rationale behind that?
To enlist the Neo4j transaction into the JTA transaction via a one phase
wrapper.
Wouldn't it
make more sense to raise an exception, similar to when
EntityManager#getTransaction() is invoked for a JTA entity manager?
If the NoSQL profile is JTA enabled, it should be enlisted into the JTA
transaction, allowing the application to control all of the database
operations that occur within the JTA transaction.
We also have the equivalent of JPA RESOURCE_LOCAL, via NoSQL profiles
that are not JTA enabled ("transaction=none" in the profile definition).
In the CMT case, did you consider to inject the Neo4j Session instead of
Driver into the bean, again akin to injection of JTA entity managers?
It is possible that we could also look at TransactionScoped injection of
sessions, but not sure yet. We started with (RequestScoped) Session
injection but commented that out [1] when we added JTA enlistment.
TransactionScoped injection of Sessions could be yet another way to
write CMT/BMT code.
All in all, I'm wondering whether things couldn't be handled analogous
to the usage of entity managers:
* For a JTA-enabled NoSQL persistence unit, obtain the Session via
injection (its lifecycle is controlled by the container and bound to the
managed transaction), any manual interaction with the Neo4j TX API is
forbidden, instead the container manages transactions or the user is
(via UserTransaction)
* For a non-JTA-enabled NoSQL persistence unit, obtain the Driver via
injection, and the user is in charge of Session lifecycle and
transaction control
Well, you haven't yet seen the above responses yet, I think the
TransactionScoped Session injection idea is good but also introduces a
different way to write CMT/BMT code for Ne04j. I disagree on making the
current (WF NoSQL/Ne04j TX enlistment) approach illegal, as I don't yet
see a problem with the current approach.
Are there difficulties with Hibernate OGM that you anticipate with
either approach of JTA TX enlistment for Neo4j?
I hope that'd make sense for actually transactional stores such as
Neo4j, for non-TX stores such as MongoDB thinks look different.
Agreed, for MongoDB, we treat that as "transaction=none", meaning no JTA
transaction enlistment for MongoDB.
--Gunnar
Scott
[1]
https://github.com/scottmarlow/wildfly/blob/nosql-dev9/nosql/neo4j/src/ma...