|The MI change is quite simple: A new property
|for the TPC is added. A new constructor taking
|a TPC instead of a Transaction is added. Method
|MI.getTransaction() is changed so that if TX
|is null and TPC is not null, the TPC Importer
|is called to get a Transaction that the TX
|property is set to and that is returned.
|
|If the MI should be serializable, it could not
|hold the Transaction TX attribute, as we do not
|know if the particular TM delivers Transaction
|instances that are serializable. Also MI holds
|a reference to an EntityContext instance that
|would also not be serializable.
fair enough...
\
|In most systems the transaction import, export
|and thread association is done completely
|transparent to all code outside the TM and
|object invocation transport layer.
|This is how JTS operates when it is cooperating
|with a CORBA object request broker.
|If we should go this route, the import and
|thread association would happen in the
|RemoteMethodInvocation, and containers
|would use the thread associated TX for the
|incoming TX context.
|This is possible, and would make the code for
|optimized local calls a bit simpler.
|But it would also mean that an incoming TX
|context would always be imported, even if
|never used.
|
|
|> Yes, suspend and resume "suspend" the Transaction AND disassociate (of
|> course). But a "disassociation" does not suspend the transaction. Do we
|> agree on that?
|
|I think we can agree that conceptually the
|transaction suspend means that it is disassociated
|from the thread and its enlisted resources are
|suspended.
|
|But when reading JTA section 3.2.3 (less than
|one page), it is pretty clear that the resource
|suspension is the responsibility of the
|application server, *not* the JTA implementation.
|This is why I think that the method names
|suspend() and resume() are misleading.
|
|But if the suspension of resources should not
|be done in these methods, only the thread
|association remains.
|
|Please note that the notion of transaction
|suspension doesn't really exist outside JTA.
|XA doesn't know about it, and for JTS it is
|only defined as two methods suspend() and
|resume() that does thread association only.
|Also, resource suspension is specific to JTA.
I argued from the very beginning that the notion of "tx suspension" is a bit
empty to me. In fact I left the API implementation empty in favor of a
clear "associate thread" "disassociateThread". There is a notion of
Transaction-thread association but this one doesn't need to appear in a spec
API just a system API.
I am tired of explaining this over and over.
|> Well at least we are further than we were with Rickard :)
|> Ok this sentence also clearly shows the separation between "suspend" and
|> suspend Association. Many thread can be associated to a
|transaction and you
|> can "suspend" the association on each one individually. Suspend on the
|> "transaction" would suspend teh "Global" transaction and of
|course propagate
|> to the other "local" associations.
|>
|> "suspend" is a global notion on the "global transaction" whereas
|association
|> doesn't affect teh liveliness of the TM just the local VM association.
|
|I guess we should be careful about the definition
|of "global" here. For a distributed TM this could
|have two meanings:
|- Everything on all nodes that know about the TX.
|- Everything on a local node that know about the TX.
By global I mean world, unique XID.
|In the following I assume you mean the last definition,
|since we are talking JTA and JTA defines VM-local
|interfaces only. (And X/Open DTM and CORBA OTS has
|no remote interface for tx suspension.)
hence the emptiness of the "suspension" in specs.
|You say that suspend on the "transaction" (I read:
|transaction associated with local thread) would
no, I mean "suspend global transaction". The fact that it is associated is
irrelevant, it is a system hack.
|suspend the "global transaction" (I read: Any
|thread local transaction representing the same global
|transaction in the local VM) and propagate to the
|other "local" associations.
|But what exactly do you mean by this?
I mean "suspend the transaction". If you have many objects reprensenting
the transaction or many resources that need to be notified of this lifecycle
event on the transaction then you propagate that since they need to be
called back.
|If you mean the thread association (I don't
|really think so), it would mean that the tx
|is disassociated from all threads when one of
|them calls TM.suspend().
Yes it is disassociated, just like there is disassociation on other life
cycle events.
|If you mean the resource suspension: Yes this
|touches the entire tx, as seen from any
|thread. But JTA says it this is the
|responsibility of the application server (not
|the TM) to do this.
I guess the TM doesn't keep track of who is listening to the global
transaction.
I don't understand why JTA has anything to do with it...
|> Thread association has no "web meaning" it just is an
|engineering trick to
|> propagate context by the thread.
|
|Yes. A simple trick to make programming
|easier. Nothing more.
not easier, just don't pass the tx explicitely but implicitely with the
thread identifier.
|In JTS the tx thread association is only
|done in interface Current, an special
|local interface designed only to make tx
|programming easier.
|
|
|> What has meaning is the global transaction. Suspend and resume apply to
|> these, not the local ones.
|>
|> |I cannot really read this as anything but:
|> |"Thread association done here".
|>
|> I read as "Thread association ALSO done here"
|
|So we can agree that thread association *is*
|done here, and disagreement is about if
|something else is also done here.
|
I think it is deeper than that I would say a suspend() method does the
following
suspend() {
suspendLocal() // cleans up resources in TM
disassociateThread()
}
because commit does
commit() {
doSomeCommitStuff();
disassociateThread()
}
And then you have
disassociateThread() {}
the first 2 are JTA the last one is system and introduced for portability.
Let me be MUCH MUCH clearer. WHY IN THE HECK DO YOU NEED TO NOTIFY A
LISTENER THAT A PARTICULAR CONTAINER IS DONE WITH A PARTICULAR THREAD. IT
IS NOT A TX LIFECYCLE EVENT IT IS JUST A "please disassociate this thread".
But if you do it with "suspend" a valid TM will actually SUSPEND the global
TX this is not what you want you just want to tell the TM about threads.
|> |And since section 3.2.3 (about these two
|> |methods) also says "Thread association done
|> |here" and "Resource tx suspension is caller's
|> |responsibility", I find it hard to read the
|> |JTA spec any other way than "the method names
|> |are misleading", and "these methods do (almost)
|> |what the JBoss-specific thread association
|> |does".
|>
|> hmmmm I think it is due to the fact that most people missread this (few
|> people understand TX). To me it is pretty clear. I did factor out the
|> "Thread association" as a portability layer in propagation context... you
|> put them back as one, in my opinion it is misleading.
|
|I think that I am about to understand your point
|here. Some kind of layer of code is needed for
|keeping track of:
|- Which components are executing in which TXs.
|- Which resource connections are open, and
| which components have them open.
|I just cannot read JTA as saying that this
|functionality should belong to the JTA
|implementation.
It does not and in fact I do not talk about that.
yes that is needed and it is I believe somewhat covered in the JCA arch?
(correct me if I am wrong). It doesn't belong in JTA (I agree). I am
talking about thread association and disassociation in a container nothing
more nothing less. You keep wanting to put a MINOR system event (please
associate thread) at the level of the TX awareness where it clearly doesn't
belong. Suspend, is a Tx level event, associate is not. The TX or any
participating module (through any participating mechanism to register them
as listeners) should NOT be notified of this MINOR event taht only concerns
the container (EJB) and teh thread going through at the time....aaarrrrgh!
|An example: Component Ca is holding a reference
|to an open resource connection Ra, and component
|Cb is holding a reference to an open resource
|connection Rb. Component Ca is executing in a
|transaction Ta, and is about to call a method on
|Cb with tx attribute REQUIRES_NEW.
|Question is: When interposing on this call, what
|should be done by the application server, and
|what should be done by the JTA implementation.
|IMO, the answer is:
|1) The application server should suspend Ra from
|its association to Ta by calling Ra.end(TMSUSPEND).
|This tells Ra that any work done on it is not done
|in the context of Ta.
|2) The application server calls TM.suspend() to
|suspend the thread association with Ta.
|3) The application server calls TM.begin() to
|start the new transaction that Cb needs. Lets
|call this transaction Tb.
|4) The application server enlists Rb with Tb
|by calling Tb.enlistResource(Rb). This ensures
|that work done on Rb is done in the context of
|Tb.
|5) The application server calls the method on
|Cb.
|6) Cb method returns sucessfully.
|7) The application server calls TM.commit() to
|commit Tb.
|8) The JTA implementation checks to see if any
|enlisted resources have not yet been delisted,
|and delists these resources. Rb was not delisted
|from Tb, so the JTA impl calls Rb.end(TMSUCCESS).
|(I am not sure if JTA mandates this. It seems to
|say that the AS should do Tb.delistResource(Rb),
|but doing this check doesn't hurt.)
|9) The application server calls Ra.start(RESUME).
|This tells Ra that any work done on it is now
|again done in the context of Ta.
|10) The application server calls TM.resume(Ta) to
|re-associate the thread with Ta.
|11) The application server returns to Ca.
wa wa wa wa wa I don't even WANT to talk about the gymnastics you do for
suspend and resume. I want to talk about (please look at the container TX
interceptor code) that associates a thread to a TX.. how do you do that
code, you resume? (I hope not...) how do you associate the Tx to the
thread... upon "import" ? then we are back to the first discussion about the
fact that the TX is just a field in a message invocation when it travels.
Doing it at import is OK, certainly not at suspend. I believe this is where
we are missing each other?
|
|JTA spec, section 3.2.3 says that steps 1 and 9
|must be performed by the application server, but
|does not explain why. My guess it that these two
|steps do not always have to be done, and the AS
|is the only one who really knows. In the example
|above steps 1 and 9 could be avoided if (and only
|if) the AS knows for sure that Ra will not be
|used at all between these two steps.
Ok then your are talking about the propagation of suspend resume to all
global listeners. I should sit down and think through WHO is responsible
for that... did you look at the JCA spec I believe it touches upon it
briefly ?
But I was making another point right?
|> btw that is why I love "Mark Hapner" as a spec writer, (EJB/JMS) local is
|> his building block... global notions are constructs... very powerful very
|> clean very clear... JTA and XA aren't as clear.
|
|IMHO, XA is hard to understand simply because it
|is complicated.
|But JTA is not the best written specification I've
|seen. I saw a comment that describes this nicely
|on a public mailing list archive: "This looks like
|it was written overnight, in a hurry".
Susan cheung ... yeah... well she was either really genius or really sloppy,
either way it a tough spec to grasp.
|For example, JTA section 4.2 illustrates how the
|application, AS and JTA implementation cooperate,
|but completely forgets to show anything about
|tx suspension.
|
Tx "suspension" is a small event, i believe it is there to say "guys are
REALLY going to take a leak now, so don't go anywhere and don't "TIME-OUT"
my transaction OK??? ifyou need to clean some stuff ok then, do it now until
I call resume but don't remove it.
I view it as the equivalent of a "ejbPassivate" on stateful beans. The bean
is still logically there, just not phisically.
I don't know...
BUT IT IS CERTAINLY NOT THE LOCAL ASSOCIATION METHODS
|
|If we should be independent of the actual JTA
|implementation used we will have to do with the
|API that JTA provides. We could have as many
JTA doesn't provide an API for association and disassociation nor should it.
That is the reason for my API for "associateThread" and "disthread", suspend
and resume ? no.
|intermediary layers on top of the JTA implementations
|as we like, but even these would have to do with
|the API provided by JTA.
|Otherwise we are not independent from the JTA
|implementation, and would have to do special
|programming to use non-JTA calls that are specific
|to the JTA implementation we use, and that would
|mean a JTA implementation specific intermediary
|layer for each different JTA implementation we
|support.
thread association and disassociation are JTA specific, they are local
system event. They MUST NOT propagate to other listeners on the Tx. (while
Suspend does as you point out)
|
|
|> Sure, well lets' get it working and then we will worry about
|"research"...
|> first things first
|
|Yes, lets get this working.
|
|I thought this was working, but during a long
|load test I got the message:
| [daniel_22] error in setOtherField () on bean #3
| in loop 342: java.lang.reflect.UndeclaredThrowableException
|No further message. Server console logging may
|have scrolled off the screen.
|I have so far been unable to reproduce this,
|and it only occurred once. I guess I have to
|test a bit further before committing.
|
|If anybody is interested in seeing the changes
|I did, I've uploaded a tarball to
|http://www.sparre.dk/unpublished/jboss-tmhack.tar.gz
Well please answer clearly where I can associate the thread with the
transaction (we do that quite a lot in the containers, all the time, almost
every entity call)... ***HOW*** do you implement that call, with resume?
marc
|
|
|Best Regards,
|
|Ole Husgaard.
|