Dmitiri Maximovich: Is JTA support broken in most J2EE servers?

Discussions

Blogs: Dmitiri Maximovich: Is JTA support broken in most J2EE servers?

  1. Dmitri Maximovich, in "Is JTA support broken in most J2EE servers?," says that WebLogic is handling a rollback condition properly, but that JBoss and WebSphere are not.

    Threaded Messages (10)

  2. Nope[ Go to top ]

    Not so. The Connection object that you're passing to the second EJB is merely a handle to a 'virtual' connection using that DataSource.

    The vconnection is associated with a physical one in the context of T1 in BeanA. When you pass the vconnection to the second B which has a new transaction then the app server allocates a new physical connection for that transaction.

    So, calling setRollBack only has no impact on T1 in Bean or its physical connection.

    WebSphere is working correctly, it's WebLogic which appears to have a bug and I've no idea where the JBoss guys came up with their explanation which is wrong also.

    An application can get a connection once, store it in static variable and then share it between threads in different concurrent transactions and it's fine, at least in WebSphere....

    Billy (IBM)
    http://www.billynewport.com
  3. Nope[ Go to top ]

    The behavior you're describing, i.e. the record in BeanA should be inserted and the one in BeanB should rollback is correct. If WebSphere doesn't do this then we've a bug.

    Billy
  4. So after some digging[ Go to top ]

    Been knocking this around the block here and here is what I can come up with.

    Your scenario is actually illegal according to the J2EE 1.4 spec. Look at section 4.2.3. It states that a connection cannot be shared between two transactions.

    However, the JCA 1.5 spec in section 6.5.4.2 indicates that it may be allowed if the underlying JCA RA supported it but shouldn't be counted on.

    So, in a nutshell, my previous statement about sharing a connection between threads depends heavily on the RA and can't be counted on. The only safe thing to do is get a new connection for each transaction.

    I'm now not even sure that passing a connection allocated in component A to component B even in the same transaction is guaranteed safe by the spec.

    The ploy thickens...
    Billy (IBM).
  5. Actually[ Go to top ]

    Whats strange here is that the servers including our own don't report this usage as an error. This is usually a trade off of performance against support cost. High performance code usually costs more to support because it usually don't do a lot of error checking or diagnostics etc.
  6. I don't read it this way[ Go to top ]

    Ok, here is excerpt from J2EE 1.4 spec, section 4.2.3 you're referring to:

    "Transactional resource objects (for example, JDBC Connection objects)
    should not be stored in static fields. Such objects can only be associated with
    one transaction at a time. Storing them in static fields would make it easy to
    erroneously share them between threads in different transactions."

    Please note "_at a time_" in the paragraph above.

    Since nested transactions are not supported in JTA/EJB, in my original example resource is always associated with at most one transaction at any given time - in BeanB execution thread would be disassociated with TxA and TMSUSPEND called by container on transactional resource before execution even entered BeanB.

    Are you reading this any differently?
  7. I don't read it this way[ Go to top ]

    I read it as saying that a jdbc connection cannot be associated with two transactions at the same time. You are doing this in your example. The connection is already associated with Bean A and you pass it to Bean B. Thats two transactions at a time and hence the is busted claim.

    Of course, the defacto standard isn't the text, it's what ever passes CTS and clearly this aspect is not tested by CTS at the moment which means each vendor can interpret any way they want which is what you're seeing right now. No one can claim a correct interpretation but I'd argue that mine looks valid :)
  8. Your scenario is actually illegal according to the J2EE 1.4 spec. Look at section 4.2.3. It states that a connection cannot be shared between two transactions.

    Billy, if we are speaking about EJB there is a passage in 2.1 spec at the end of 5.3 section:


    The Bean Provider must also exercise caution in determining which objects to pass across the local
    interface. This caution applies particularly in the case where there is a change in transaction or security
    context.


    So, EJB spec doesn't really prohibit, but rather don't recommend it. However in some cases it could be really necessary to pass allocatted transactional resource such as JDBC connection, JMS session, etc. trough the transaction boundary in order to allow to reuse these instances (some MOM such as Tibco are using per-connection licensing). More over, application has better knowledge when resource is not being used, e.g. while parent transaction is suspended upon component B will complete its business.

    The above indicate some inflexibility of the EJB-based transactional demarcation and may lead to custom transactional handling in some particular cases (e.g. using Spring-based tx proxies or custom advices).
  9. So after some digging[ Go to top ]

    we used performausre from quest software
  10. Broken JTA support in WebLogic[ Go to top ]

    Just reading the headline, I'm tempted to agree. I would assume some aspect of some JTA scenario is likely to be broken in every server. The scenario outlined in the article does not have any spec support unless we assume the XADataSource in action, is deployed as a XA-capable Connector (not sure about connector 1.5, but for 1.0 it was a definite requirement to implement the associateConnection callback).
    The following example could be part of justifying the headline. At least WLS is listed among those having problems complying with every aspect of the JTA spec:

    Deploy a BMT message-driven bean.
    The MDB looks up a UserTransaction, invokes begin() and starts business logic processing.
    The business logic invokes JDBC operations in a way that the transaction timeout is violated.
    The MDB catches the timeout exception and invokes rollback() on the user transaction.
    WebLogic violates the JTA spec in that the rollback() call doesn't block until the transaction is in a state that a call to begin() would be allowed.
    onMessage() returns and WebLogic puts the worker thread back into the pool. Meanwhile, the asynchronous rollback() is still waiting for its enlisted resource managers to rollback.
    Another request arrives at the container. The request requires a new transaction (be it the same MDB, an CMT EJB or a servlet with programmatic transaction control). This request is handed the same thread that previously executed the failed MDB transaction. The asynchronous rollback() (spec requires synchronous rollback()) is still fighting its resource managers. The thread that has now been reused to serve a new request, is still associated with the transaction that is still not in a valid state to receive a begin(). The new request will fail with an exception stating that a new transaction cannot be started, since the current thread is already associated with an active transaction.
    /Johan
  11. I've been working with wls, was & jboss for the last 5 years. I never had unexpected transactional behavior with wls and jboss, but I had a few surprises with was. For example, write a session bean and configure it in supports mode, and put a method in it to so something with the DB - read, write, doesn't matter. deploy it on was 5. call it from another bean with an ongoing transaction, it'll work ok. Call it from a bean with no ongoing transaction, and you'll find the DB connection will hang.

    Cheers,
    Emil (http://www.thekirschners.com/)