I haven't been following this thread closely, but with JBoss at least, you have the option of configuring datasources as no-transaction: no-tx-datasource. With this type of datasource, you are free to call commit and rollback yourself. With container-managed transactions, you should not be calling commit or rollback. I've erroneously done so, and JBoss generates an error saying that these methods are illegal on a container managed transaction.

Regarding your thoughts about a smart resource manager, that is indeed what happens. Remember that datasource may be retrieved and closed any number of times during the processing of a single EJB method. During the execution of single EJB method, the container is required by the spec to return the same physical connection each time getConnection() is invoked, so that all database activity within that method (which can of course call other methods) is guaranteed to be within the same transaction.

Only when the EJB method completes does the container do the commit or rollback and then returns the connection to the pool as available for use.

Since iBATIS can't possible determine that it is being used in a container-managed transaction, if you want to support that, I would think the only possibility is to provide an optional parameter in the data source configuration to indicate that. In such cases, iBATIS should probably no-op commit and rollback.

On 4/19/2010 11:15 AM, Clinton Begin wrote:
Thanks Adinath.

This will all help.  Let's figure this out together.

The odd thing for me is this.  A typical transaction lifecycle (be it
global or otherwise would be:

*  Open Connection
*  Do Work
*  Commit or Rollback
*  Close Connection (even if this implies a return to the connection pool)

The problem with calling close on a connection that's globally managed
is that it changes the lifecycle to:

*  Open Connection
*  Do Work
* >> Close Connection (even if this implies a return to the connection pool)
*  Commit or Rollback

Now I suppose a smart resource manager controlling the transaction would
know better than to actually return the connection to the pool until the
worker thread is finished and the transaction is either committed or
rolled back, but I'm not entirely confident that all app servers are
that smart.  As you noted, glassfish doesn't even warn you when you call
commit in a managed transaction (most resource managers would throw an
exception if commit or rollback were called).  I wouldn't be surprised
if this is the reason you're getting intermittent IllegalStateExceptions.

I'm going to do a little more reading tonight on JEE 6 standard behavior
to see if there's one approach we can trust.

The most empirical evidence of the proper behavior would be iBATIS 2,
which calls close.  But I normally don't remove code without reason
(although it has happened ;-).

I'll check into this tonight or tomorrow at the latest.

Cheers,
Clinton


On Mon, Apr 19, 2010 at 1:26 AM, Adinath <adin...@acciente.com
<mailto:adin...@acciente.com>> wrote:

    Clinton,

    On Sun, Apr 18, 2010 at 2:45 PM, Clinton Begin
    <clinton.be...@gmail.com <mailto:clinton.be...@gmailcom>> wrote:

        You did the right thing... iBATIS transaction managers are meant
        to be easy to implement yourself.


    Yes, they are easy to implement!

        That said, this was a matter of constant debate back in the good
        old days when none of the standards were implemented
        consistently.  I'm still not sure if they are.

        Some app servers would complain if iBATIS closed the connection,
        because if some downstream process needed a connection,
        theoretically it was supposed to use the same one (which would
        be closed by that time). I think the trick is to ensure that
        you're using a container managed DataSource.  Are you retrieving
        a DataSource configured by GlassFish from a JNDI context (in
        other words, a container manged DataSource)?  Or are you just
        using the iBATIS built-in SimpleDataSource?


    Yes I am using using a container managed datasource (GlassFish v3
    managing a DB2 v9.7 connection), looked up via JNDI. I create the
    iBATIS session factory using SqlSessionFactoryBuilder and the
    related classes (i.e. no XML config file).
    I

        I would expect a container managed DataSource to lazily
        initialize a connection for any one worker thread, and continue
        to provide that same connection to any requester for that
        particular DataSource.  Then I'd expect it to close that
        connection at the end of the entire workflow.


    My experience with GlassFish is that the connection needs to be
    closed to be returned to the pool.

    With GlassFish I wrote a set of tests and established that if you
    call commit() on a JDBC connection returned by the container managed
    datasource it causes an commit (thru to the driver), defeating the
    EJB transaction.

    There are 2 other issues I ommitted in my original post, for
    clarity. I suspect these 2 issues have nothing to do with IBATIS,
    but I am just sharing FYI (just in case).

    *Issue #1*
    In the close() method of my custom iBATIS transaction class I would
    transiently (about every 4 times) get IllegalStateException with
    "state.isBusy() : false" in the message when I call
    connection.close(). Some posts pointed that this happens when the
    connection is already closed. But I have verified using the debugger
    that this does not apply, the connection is open and isClosed()
    returns false. The fix for now is to catch the IllegalStateException
    the close() and ignore it! :(

    *Issue #2*
    The other issue is rather unnerving, I am reluctant to share it
    since it is a little winded, but thought perhaps it may help someone
    else. This too I suspect has nothing to do with iBATIS. It is as
    follows:

    - there is a stateful session bean (sfsb) A that has a reference to
    another sfsb B
    - there is a method in sfsb A, say methodOfA, which inserts a row
    using iBATIS
    - there is a method in sfsb B, say methodOfB, which inserts a row
    using direct JDBC
       - methodOfB() also uses a container managed DataSource to
    retrieve a connection and does connection.close() before returning
    - now the logic in methodOfA() looks like below:

    public void methodOfA()
    {
       session = sessionFactory.openSession()

       boolean commit = false;
       try
       {
          mapper = session.getMapper( UserMapper.class);

          someID = beanB.methodOfB();

          // set value for user
          user = new User();
          user.setOtherStuff() ...
          user.setSomeID( someID );

          // insert row for new user
          mapper.insertUser( user );

          commit = true;
       }
       finally
       {
           sessionclose();

           if ( ! commit )
           {
              sessionCtx.setRollbackOnly();
           }
       }
    }

    The issue here is that if I set a debug breakpoint at the line with
    mapper.insertUser( user ),I sometimes see the update by
    referenceToB.methodInB() get commited to the database!! (checked via
    a DB2 SQL console) This happened late Friday and I have not had a
    chance to look at since. I think the culprit here is GlassFish, I
    suspect that this happens only during debugging (need to verify this).

    On a final note, I have used iBATIS 2 on a previous project and
    iBATIS 3 on the current one. Even with IBATIS 2 I thought it was an
    incredible piece of work, well-thought out and a pleasure to use.
    Especially love the support for dynamic SQL, and the type handler
    callbacks. Excellent work!

    Best,

    Adi

    --
    Acciente, LLC
    Systems Architecture and Software Design

    www.acciente.com <http://www.acciente.com>
    www.inductionframework.org <http://www.inductionframework.org>




--
Guy Rouillier

---------------------------------------------------------------------
To unsubscribe, e-mail: user-java-unsubscr...@ibatis.apache.org
For additional commands, e-mail: user-java-h...@ibatis.apache.org

Reply via email to