Hi,

marc fleury wrote:
> |I think you are wrong here.
> |Quoting JTA 1.0.1 specification, section 3.2.3:
> |"A call to the TransactionManager.suspend method
> |temporarily suspends the transaction that is
> |currently associated with the calling thread.
> 
> Ok the spec makes no sense :)
> 
> Ok that sentence says nothing about "disassociation" but "suspend the
> transaction" . The action is to "suspend" the target the transaction.  Which
> one? the one that you can retrieve from the thread association.
> 
> We don't know what the "suspend" operation is, and it doesn't say anything
> about disassociation, however (see below)

I guess this clearly spells out our main
disagreement here, and how JTA is unclear.


> |If the thread is not associated with any
> |transaction, a null object reference is returned;
> 
> ok
> 
> |otherwise, a valid Transaction object is returned.
> |The Transaction object can later be passed to the
> |resume method to reinstate the transaction context
> |association with the calling thread.
> |The TransactionManager.resume method re-associates
> |the specified transaction context with the calling
> |thread. If the transaction specified is a valid
> 
> This is inconsistent as the "suspend" and "resume" are not symetrical.  This
> part ONLY talks about association and nothing about "resuming the
> transaction".  SO that the action done on resume is "associate" thread, the
> action done on suspend is "temporaly suspend the transaction".
> 
> Do you see the inconsistency.

Yes. I think that the first part (suspend)
needs some editing as to not introduce an
undefined term "transaction suspend". And
my guess is that what the spec. authors
really wanted to write was something like:
"A call to the TransactionManager.suspend method
temporarily suspends the association of the
calling thread with a transaction."
Apart from section 3.2.3 heading that also has
to be changed, that would make sense, and no
undefined terms would be introduced.

Too bad computers are not good at the english
language yet. Otherwise a parser would have
complained: "Undefined term [tx suspend] in JTA,
section 3.2.3" ;-)


> |transaction, the transaction context is associated
> |with the calling thread; otherwise, the thread is
> |associated with no transaction."
> |
> |So thread association *is* done in these methods.
> 
> No, in THIS method (resume) nothing is said in "suspend" in fact suspend
> cleanly says that it is a "TX" lifecycle event.  The spec is non
> symetrical...

You are right. I cannot conclude like that
without assuming that my guesswork above is
correct.


> |Further quoting section 3.2.3:
> |"The application server is responsible for ensuring
> |that the resources in use by the application are
> |properly delisted from the suspended transaction.
> 
> Ok end of story.  When I finish my invocation in the container I
> disassociate the thread that is going in because it could be reused for
> another invocation.  THIS ISN"T A "SUSPENSION" and I CERTAINLY DON"T WANT
> THE JDBC DRIVER TO BE DELISTED, the JDBC driver should remain there since
> other threads associated with this transaction will commit/rollback at some
> point.

Delisting a resource from the transaction does not
make the TM forget that the resource was involved
in the transaction. In any case, a reference to the
XAResource is held in TxCapsule until the transaction
terminates.
This is the case even if no work was done on the
resource within the transaction. But if this is the
case, the resource can vote read-only in the prepare
phase so that it does not have to get involved in
the second phase.


> |So JTA says that resource suspension/resumption
> |is *not* the responsibility of the JTA
> |implementation when suspending/resuming with
> |TM.suspend()/TM.resume().
> |
> |But besides thread association suspension and
> |resource suspension, what is in a tx suspension?
> |IMO nothing.
> 
> ah ah, well ok we don't agree there.  In fact the "propagation" we are
> talking about does apply in a suspension.
> 
> Again imagine the following scenario:
> 
> You start a big transaction and you do work.  Then you say "before I buy the
> car I want to talk to my wife" and so you tell the system "will decide
> later" what can teh system do? it can "suspend the transaction" so that the
> resource manager of JDBC to the bank approving the loan will not hold to the
> transaction and TIME OUT and ROLLBACK in 20 minutes.  You clean up the
> resources enrolled in teh TX with this suspend call (if distribution, let's
> even assume "no distribution" it is irrelevant to the discussion).  So you
> come back and you say "i buy" and it "RESUMES" the tx and enroll everybody
> so that the play can finish with everybody in a transactional aware state.
> 
> Now if this was to take place at once?  you would time out ...

I disagree quite a bit here. The scenario above is
generally solved with "business transactions", and
that is an entirely different beast than ACID
transactions. If the transaction above is an ACID
transaction, the "tx suspend" cannot release locks,
as that would violate the isolation requirement.
But what happens if person B comes to buy the car
while you are talking to your wife?
B's thread would have to wait for the lock that your
long transaction had to hold. No error message, or
"please wait until someone else decides", simply a
thread waiting for a lock to be released. Eventually
B's transaction will time out.
The transaction timeout is our only defense against
threads holding transaction locks for too long, and
if the timeout could be suspended in a tx suspend
(whatever that is), we no longer have this defense.
Imagine what would happen in the scenario above if
you decide not to buy the car, and forget to return
to say "no, thanks" and terminate your transaction.

In general long ACID transactions is a no-no.
And ACID transactions while waiting for user
input is a NO-NO.


> So what is disassociation? well imagine the stuff is done at once and the 3
> components talk in a container.  First thread is going through then it calls
> another bean, when that bean is done it "disassociates" the thread because
> the bank bean is done with this work and moves on the next one, but the
> state is still part of the transaction (with a JDBC driver under it).  THAT
> DISASSOCIATION (that happens 30 times a second) DOESN"T SUSPEND THE
> TRANSACTION, it just disassociates a thread in a corner of the application
> and transaction.  The transaction goes on and commits.

I agree here, except that the thread association
and disassociation is done by the container, not
the bean.


> Never was there a
> "suspend transaction" demarcation in its life cycle.

Well, here again we have the problem that
"transaction suspension" isn't really defined.


> |But that leaves *only* thread association
> |suspension/resumption to be done in the TM
> |suspend()/resume() methods.
> 
> yes,
> 
> Since there isn't support for the scenario I put above, Ie a clear
> understanding of "suspend and resume" and propagation, there is no code to
> support that (and no interface to distribute it I understand).  So it leaves
> Tx association and disassociation, yes.  These can legally be different
> methods, I argue that they are since as shown above we disassociate
> INDENPENDENTLY of the suspend event in the lifecycle.

I think I can follow you here. But I don't think
that "transaction suspension" really exist, and
I think that JTA really mean "transaction thread
suspension" when using this undefined term.

The term "suspension" when used with transactions
is unique to JTA. The only other place I have
seen it is in the JTS Current interface, and
there it means "thread transaction suspension"
only.

I see why JTA introduced "resource suspension".
This is needed if a resource must participate
in several transactions, and we should not wait
until the first tx terminate until the resource
can be used in the second tx. I think the idea
here is that the application server knows the
components, the resources they have open and the
transactions they are working in.

For example, consider a stateless session bean
instance B that keeps open a resource connection
R across method invocations:
A transaction T1 is started, and a method on B is
invoked. The AS knows that B has R open, so when
interposing the invocation, it does T1.enlist(R).
After the invocation is done, the AS does
T1.delist(R) to tell R that its work is no longer
done in the context of a transaction.
Since we have this resource suspension, another
invocation in context of transaction T2 can be
done on the same instance B before T1 is done:
When interposing the invocation, the AS does
T2.enlist(R), and after return the AS does 
T2.delist(R). (Unless B closed R within this
invocation: But the AS interposes this too, so
it will do T2.delist(R) on R.close() (since it
knows the transaction B executes in), and at
return the AS knows R was closed so no
T2.delist(R) should be done here.)

I guess this example also explains why the
JTA specification says that the AS is
responsible for the enlistment and delistment:
The AS is the only one that knows which
resource connections bean B has open.


> |But if JTA TM suspend()/resume() do thread
> |association only as I am arguing, it would
> |not be that bad to use this, would it?
> |
> 
> it would be bad.  A properly implemented suspend will disenlist the
> resources... that is wrong.

But JTA specifically leaves the delisting to
the application server:
"The application server is responsible for ensuring
that the resources in use by the application are
properly delisted from the suspended transaction."

Please note that in the context of the JTA
specification, the JTA implementation and
application server are disjunct.


> The only reason it works is because we don't implement 3.2.3 properly.   If
> the implementation as you claim you did it, doesn't do that propagation then
> it is innocuous.  A properly implemented TM will disenlist the JDBC driver I
> was talking about and when your container calls commits, since the JDBC
> driver isn't listening on the TX demarcation, and you have killed part of
> teh state of your TX.
> 
> yes?

I don't think so.
JTA specifically says that the delist of the
JDBC driver is done by the AS, *not* the JTA
implementation.
And even though the JDBC driver is delisted
from the transaction, the transaction still
remembers the JDBC driver so that it can
participate in the commit.
Propagation (within local VM) is done on
enlistment and delistment of resources, but
the thread tx association is thread-local, and
does not propagate (ie. disassociating a tx
from one thread does not make it disassociated
from other threads, and associating a tx with
a thread does not make the tx associated to
any other threads that it was not already
associated with).


Best Regards,

Ole Husgaard.

Reply via email to