users@glassfish.java.net

Re: Glassfish DB Connection Pool Bug in Local Transaction Case

From: Jagadish Prasath Ramu <Jagadish.Ramu_at_Sun.COM>
Date: Thu, 28 Jun 2007 00:07:53 +0530

Please find my responses in-line.

Thanks,
-Jagadish

On Wed, 2007-06-27 at 11:01 -0700, glassfish_at_javadesktop.org wrote:
> Thanks for the response Jagdish. But I think original question was not answered.
>
> If it is Bean Managed Transaction, why should Glassfish started container managed transaction care about the resource needed by the user transaction? Glassfish doesn't know about those transaction and It can' t make any assumptions about the transaction that is not its control. And the resources needed by the user transaction.

Bean Managed Transaction means, Bean (application) will decide the
transaction's state. It has the control of either committing or rolling
back. GlassFish will mediate/delegate the
begin()/end()/commit()/rollback() calls made by bean to the resource
manager.

>
> I understand the need to map connection, but I still think that Glassfish should not hold onto ResourceHandle with underlying ManagedConnection(which as physical connection to db) if it is not going to use it for any future calls because it is a Local Transaction. I still feel if Glassfish knows it needs to map underlying physical connection because it is local transaction, then it should not enlist more resources in that transaction's resource list. In local transaction having more than one transactional resource is any way not going to work because then you need XA/2PC semantics.
>
> Take a look at the code in:
> AbstractResourcePool.internalGetResource(ResourceSpec spec,
> ResourceAllocator alloc,
> Transaction tran) {
> //specifically this check
> if (spec.isXA() || isNonXAResourceAndFree(j2eetran, h)) {
> }
> }
>
> and see
> private boolean isNonXAResourceAndFree(J2EETransaction tran, ResourceHandle resource){
> boolean result = false;
> if(resource.getResourceState().isFree() && [b]resource.equals(tran.getNonXAResource()[/b])){
> result = true;
> }
> return result;
> }
>
> resource.getResourceState().isFree() will never be free for the ResourceHandle stored in the J2EETransaction object (this is the only resource ever used in the case of LocalTransaction) for the 2nd get connection() call, so Glassfish will always obtain a new ResourceHandle and alongwith it a new connection from the pool and it will never be used BUT enlisted in transaction and hold onto the underlying connection. And thus leaking connection until the local transaction is committed.
Suppose in a BMT for the following scenario, could you check what will
isNonXAResourceAndFree() will return ?
                                
                                UserTransaction uTx = entityContext.getUserTransaction();
                                uTx.begin();
                                        con1 = dataSource.getConnection();
                                        doDBOperation() using connection-1
                                        con1.close();
                                        con2 = dataSource.getConnection();
                                         doDBOperation() using connection-2
                                uTx.commit();
                                con2.close();
>
> I still this a bug. The correct behavior should be for Glassfish to return the same (and only resource ever used by glassfish for connection comparison) ResourceHandle. For local transaction case there is no need to allocation new ResourceHandle and then map the underlying connection to the connection stored in J2EETransaction's ResourceHandle's connection.

Suppose, if you are going to return the same resource handle (and hence
same physical connection) , how will you define the behavior for
"doDBOperation() using con2;" after uTx.commit() ?

        UserTransaction uTx = entityContext.getUserTransaction();
                                try{
                                        uTx.begin();
                                        con1 = dataSource.getConnection();
                                        doDBOperation() using con1;

                                        con2 = dataSource.getConnection();
                                        doDBOperation() using con2; //using physical connection of conn-1, connection sharing.
                                        uTx.commit();
                                }
                                catch(SQLException sqle){
                                        uTx.rollback();
                                }
                                        con1.close();
                                        doDBOperation() using con2; // currently using actual physical connection, no sharing involved.
                                        con2.close();
>
> I also think the code will work perfectly fine in the case of XA/2PC transactions because in that case the following check:
>
> AbstractResourcePool.internalGetResource(ResourceSpec spec,
> ResourceAllocator alloc,
> Transaction tran) {
> //specifically this check
> if (spec.isXA() || isNonXAResourceAndFree(j2eetran, h)) {
> }
> }
>
> will return any available ResourceHandle that is free and enlisted in resource list of current transaction (J2EETransaction). But in the case of local transaction it checks for one and only resource, the resource stored in nonXAResource member variable of J2EETransaction.
>
>
> --
> Sanjay
> [Message sent by forum member 'sanjaydwivedi' (sanjaydwivedi)]
>
> http://forums.java.net/jive/thread.jspa?messageID=224291
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: users-help_at_glassfish.dev.java.net
>