Marc,
No apologies needed. You focus on exactly
what needs to be focused: The places where
we do not agree. Disagreement means that
one of us may be wrong or have misunderstood
something, so this _is_ where discussion is
needed.
Besides, I find this discussion quite
interesting.
About committing: I have done a lot of
testing to reproduce the bug I saw once
earlier. It seems to happen only once
about every 500,000 transactions on the
load test. This time I got a server
stack trace, and it looks like Minerva
is trying to delist a null XAResource.
I catch that in TxCapsule to protect
against anybody doing wierd things.
Server stack trace below, in case anybody
is interested.
I hope to incorporate my change in latest
CVS, and commit tomorrow.
Best Regards,
Ole Husgaard.
Server stack trace:
[nextgen.EnterpriseEntity] java.rmi.ServerException: Store failed; nested exception is:
[nextgen.EnterpriseEntity] java.lang.RuntimeException: Unable to deregister with
TransactionManager: java.lang.IllegalArgumentException: null xaRes
[nextgen.EnterpriseEntity] java.lang.RuntimeException: Unable to deregister with
TransactionManager: java.lang.IllegalArgumentException: null xaRes
[nextgen.EnterpriseEntity] at
org.opentools.minerva.jdbc.xa.XAConnectionFactory$2.closeConnection(XAConnectionFactory.
java:103)
[nextgen.EnterpriseEntity] at
org.opentools.minerva.jdbc.xa.XAConnectionFactory$2.connectionClosed(XAConnectionFactory.java:82)
[nextgen.EnterpriseEntity] at
org.opentools.minerva.jdbc.xa.wrapper.XAConnectionImpl.clientConnectionClosed(XAConnectionImpl.java:126)
[nextgen.EnterpriseEntity] at
org.opentools.minerva.jdbc.xa.wrapper.XAClientConnection.close(XAClientConnection.java:250)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.jaws.jdbc.JDBCCommand.jdbcExecute(JDBCCommand.java:178)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.jaws.jdbc.JDBCStoreEntityCommand.execute(JDBCStoreEntityCommand.java:97)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.jaws.JAWSPersistenceManager.storeEntity(JAWSPersistenceManager.java:156)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.CMPPersistenceManager.storeEntity(CMPPersistenceManager.java:388)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.EntitySynchronizationInterceptor$InstanceSynchronization.beforeCompletion(EntitySynchronizationInterceptor.java:343)
[nextgen.EnterpriseEntity] at
org.jboss.tm.TxCapsule.doBeforeCompletion(TxCapsule.java:1220)
[nextgen.EnterpriseEntity] at org.jboss.tm.TxCapsule.commit(TxCapsule.java:322)
[nextgen.EnterpriseEntity] at
org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:75)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:318)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:99)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:137)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:195)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.EntityContainer.invoke(EntityContainer.java:323)
[nextgen.EnterpriseEntity] at
org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker.invoke(JRMPContainerInvoker.java:
384)
[nextgen.EnterpriseEntity] at java.lang.reflect.Method.invoke(Native Method)
[nextgen.EnterpriseEntity] at
sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:241)
[nextgen.EnterpriseEntity] at
sun.rmi.transport.Transport$1.run(Transport.java:142)
[nextgen.EnterpriseEntity] at java.security.AccessController.doPrivileged(Native
Method)
[nextgen.EnterpriseEntity] at
sun.rmi.transport.Transport.serviceCall(Transport.java:139)
[nextgen.EnterpriseEntity] at
sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:443)
[nextgen.EnterpriseEntity] at
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:643)
marc fleury wrote:
>
> Ole,
>
> Also I was rereading your first mail where you describe the work you have
> done and I want to apologize. I am a bit of a dick for focusing JUST on the
> spot where I don't agree... frankly I believe you have done an outstanding
> job and encourage you to keep it up, these points we are discussing are
> frankly almost details compared to the work you have already done.
>
> My apologies for being a pain :)
>
> (feel free to keep the discussion going or kill it :)
>
> again bravo for your outstanding work on the TM, Please commit asap under a
> new module for the JBossTM project.
>
> Regards
>
> marc
>
> |-----Original Message-----
> |From: [EMAIL PROTECTED]
> |[mailto:[EMAIL PROTECTED]]On Behalf Of marc fleury
> |Sent: Wednesday, February 07, 2001 11:07 AM
> |To: jBoss Developer
> |Subject: RE: [jBoss-Dev] Upcoming TM changes
> |
> |
> ||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)
> |
> ||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.
> |
> ||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...
> |
> ||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. Again suspend resume are methods that live in the realm of
> |"transaction demarcation semantics" thread association doesn't.
> |
> |We must NOT properly delist the suspended transaction, because the
> |call I am
> |talking about from the container IS NOT A SUSPENSION OF THE TRANSACTION the
> |transaction is STILL VERY ACTIVE, it is just a DISASSOCIATION of the thread
> |to the Transaction.
> |
> ||A resource delist operation triggers the Transaction
> ||Manager to inform the resource manager to
> ||disassociate the transaction from the specified
> ||resource object (XAResource.end(TMSUSPEND)).
> ||When the application s transaction context is
> ||resumed, the application server ensures that the
> ||resource in use by the application is again enlisted
> ||with the transaction. Enlisting a resource as a
> ||result of resuming a transaction triggers the
> ||Transaction Manager to inform the resource manager
> ||to re-associate the resource object with the resumed
> ||transaction (XAResource.start(TMRESUME))."
> |
> |That is fine that is the semantics of "suspend/resume" we argued and it was
> |pointed out that there was no support for distributed "suspend/resume".
> |
> |End of story.
> |
> |Bottom line: JTA is at best misleading at worst poorly written.
> |
> ||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 ...
> |
> |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. Never was there a
> |"suspend transaction" demarcation in its life cycle.
> |
> |yes?
> |
> ||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.
> |
> |
> ||> 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?
> ||
> ||Well, I haven't changed any of that code, but
> ||I would like the container to get rid of any
> ||non-JTA calls to the TM.
> ||
> ||J2EE-RI and JonAS use TM.resume() for this.
> |
> |"mal de muchos remedio de tontos" (spanish equivalent of "3 trillion flies
> |eat shit so you too should")
> |
> |and it's a miss-interpretation of simple facts. JTA is buggy in its text,
> |blame it on Susan cheung. It was an amazing piece of spec she was
> |trying to
> |put together in a hurry.
> |
> ||In both cases, the code is a little hard to
> ||read because resource suspension/resumption
> ||is done in the JTA impl (JonAS), or in a
> ||layer on top of it (J2EE-RI). In neither
> ||case there is special thread association
> ||methods.
> |
> |I agree that the code to do it is a couple of lines if YOU DON'T DO THE
> |PROPAGATION. Please go ahead and forget this discussion :)
> |
> |however
> |
> ||
> ||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.
> |
> |
> |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?
> |
> |marc
> |
> |
> |
> ||Best Regards,
> ||
> ||Ole Husgaard.
> ||
> |
> |