No, process B would see the modified data. TreeCache's locking semantics control access to nodes in the cache, but once you have retrieved the data from a node it is up to you to control concurrent use of it.
I'm somewhat surprised by your answer. What's the purpose of transactions if changes are automatically reflected?
If you need the cache to enforce fine-grained control over the internals of mutable cached objects, you need to use PojoCache (fka TreeCacheAop).
As ajoe stated, otherwise enforcing such control would mean the cache would have to clone all objects before returning them. But who knows if cached objects are Clonable? And how do they implement cloning -- is it a shallow copy or a deep one?
What seems to be missing here is some kind of analogue to SELECT FOR UPDATE -- i.e. a getForUpdate() for Step 2 of the sequence which would then acquire a write lock on the node instead of a read lock. The presence of the WL would then prevent Process B reading the node until the tx commits.
So then I guess I have to ask the stupid question...
What if A rollsback the transaction instead of committing it in step 5? Will B have the modified (incorrect) data, or the unmodified (correct) data?
only to clarify my understanding, if I change the CacheMode to REPL_SYNC and the Process B in another JVM than, the Process B doesn't 'see' the modified Object x, instead it would get an unmodified Object x. After Process A has committed, also Process B would 'see' the modified Object x.
Is this correct?
Thanks a lot
PS: It looks like I could/should write the next wiki page ;-)
PPS: @bruce76: I don't think that is a stupid question, because as far as I know, there is only little documentation about this topic and you have to guess how JBoss Cache works in this cases.
The key thing is there is only one copy of the object. If one thread makes a change to the object, and code executing in another thread has a reference to that object, the 2nd thread immediately sees changes made by the 1st.
An ordinary object is not a transactional resource; if changes are made to it during a tx, and the tx rolls back, the changes will only be reversed if the application that made them detects the rollback and reverses the changes.
Any other thread with a reference to the same object would see any changes immediately.
Yes, with REPL_SYNC or REPL_ASYNC, changes are replicated around the cluster as part of transaction commit, so Process B would not see any changes until Process A's tx commits.
Actually, with the sequence you initially wrote, the changes would not be replicated at all. TreeCache does not know Process A changed the object; to get replication to occur you would need to do a put to the cache:
1. Process A starts a new Transaction.
2. Process A calls get(Fqn for x, key for Object x)?.
3. Process A modifies Object x (e.g x.setAttribut(?abc?)).
3.5 Process A calls put(Fqn for x, key for x, x);
4. Process B calls get(Fqn for x, key for Object x).
5. Process A commits the Transaction.
Note that step 3.5 aquires a write lock. In LOCAL mode, this WL would block Process B from doing a read until Process A commits. But, there is a race condition here -- what if Process B does its read in between 3 and 3.5? That race is the reason I mentioned the need for a getForUpdate() concept.
With replication, the put() in 3.5. would be replicated around the cache as part of committing the tx in step 5. If Process B did its read before the replication it would see the old state. If after the replication, it sees the new state. If it tries to read in the middle of the replication, it blocks briefly as the replicated put has a WL on the node. Then its read goes through and it sees the new state.
A cool side effect of instrumenting your classes for use with TreeCacheAop is that once an object is placed in the cache, changes made to it are transparently transactional. So, if changes are made to the object in a tx, and then the tx rolls back, the changes are reversed by TreeCacheAop.
This can only happen with instrumented classes and TreeCacheAop; without the instrumentation the cache has no way to know an object stored within it has been modified.