9 Replies Latest reply on Jun 21, 2007 11:44 AM by tek no

    Why is jboss closing my connection?

    tek no Novice

      I have written a JCA connection factory which works fine. I use it in a stateful session bean. On first use I always get

      2007-06-15 18:39:42,746 TRACE [org.jboss.resource.connectionmanager.CachedConnectionManager] popped object: org.jboss.resource.connectionmanager.CachedConnectionManager$KeyConnectionAssociation@5522e1
      2007-06-15 18:39:42,746 INFO [org.jboss.resource.connectionmanager.CachedConnectionManager] Closing a connection for you. Please close them yourself: com.Connection@ec76fa
      java.lang.Throwable: STACKTRACE
       at org.jboss.resource.connectionmanager.CachedConnectionManager.registerConnection(CachedConnectionManager.java:290)
       at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:417)
       at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:842)
      
      


      Now my question is why? I have not called close on the connection for a reason - I want the bean to reuse it. What is going on here? I return the connection to the pool when I am done with it but jboss appears to try to pre-empt this. How do I fix this?

      thanks

        • 3. Re: Why is jboss closing my connection?
          tek no Novice

          Ok, thanks. Is there a way to switch this off on a per connection factory level? I would like to get the benefits of the checking for database connections but not on my own session based connections.

          Also, just out of curiosity, what is the heuristic that jboss uses to decide that a connection has been checked out of the pool long enough and needs closing?

          cheers

          • 4. Re: Why is jboss closing my connection?
            Adrian Brock Master

             

            "teknokrat" wrote:
            Ok, thanks. Is there a way to switch this off on a per connection factory level? I would like to get the benefits of the checking for database connections but not on my own session based connections.


            As per the docs:
            debug=false in jbossjca-service.xml

            But then avoiding connection leakage becomes your problem. :-)

            As stated many times in this forum. Holding one connection per ejb instance
            is an anti-pattern and a totally inefficient use of resources.

            The connections are already pooled (and cached at the transaction level)
            by JCA which leads to a much more efficient use of resources.

            // CMT Required Transaction
            public void doSomething()
            {
             ConnectionFactory cf = ...
             Connection c1 = cf.getConnection(); // Handle
             Connection real1 = c1.getRealConnection(); // Real
            
             Connection c2 = cf.getConnection(); // Handle
             Connection real2 = c2.getRealConnection(); // Real
            
             assert c1 != c2; // Handles are not the same instance
             assert real1 == real2; // But you always use the same real/underlying connection in the same transaction
            }
            


            "teknokrat" wrote:

            Also, just out of curiosity, what is the heuristic that jboss uses to decide that a connection has been checked out of the pool long enough and needs closing?


            In a transaction - the end of the transaction
            Otherwise the end of request (EJB method/Web invocation)

            • 5. Re: Why is jboss closing my connection?
              tek no Novice

              I would love to do things that way. Here lies my problem. I have a stateful service. The service needs to keep a TCP connection open to an external resource. Everytime I get a connection from the pool, it must be exactly the same one I used before for this session. I tried to play around with the BySubject and ByApplication settings but found it easier to just open a connection at the beginning and close it on remove.

              If there are better ways to do this I am all ears.

              thanks for the help.

              • 6. Re: Why is jboss closing my connection?
                Adrian Brock Master

                 

                "teknokrat" wrote:

                If there are better ways to do this I am all ears.


                Use a transaction.

                What you have is a unit of work.
                startWork();
                doStuff();
                endWork();

                JTA Transactions are natural units of work.
                You can mark when the work starts and when it finishes.
                More importantly, you can decide when it should timeout and resources get released.

                Don't get confused about performance. A JTA transaction is just a thread
                local marker, its not "heavy" like a real jdbc transaction.
                It can become "heavy" if you enlist something like a jdbc connection
                in the JTA transaction.

                Stateful sessions are also units of work
                but they have some bad semantics in terms of resource allocation.

                e.g. Suppose the client starts a session, you allocate a tcp/ip connection
                (a limited resource) per session, but the client then vanishes, e.g. if it is a user
                interface they go to lunch or go home without ending the session (properly).

                After a certain period of inactivity JBoss will passivate the session (write it to disk)
                after a further period of inactivity it will remove the session altogether.

                Question: How are you going to recover the tcp/ip connection if the session is passivated
                and then reactivated? You certainly can't serialize a tcp/ip socket.
                For the same reason, you can't replicate the session across a cluster if you
                want the session to failover.

                Another bad feature of SFSB is that a serious error (an EJB/RuntimeException)
                will mean that ejbRemove() is NOT invoked. That means there is no
                way for the EJB instance to tell the server to release the resources it allocated.
                You will leak connections!
                The EJB spec says you need to do some extra work to cater for this situation,
                but this is usually hard to do.

                What this shows is that in general it is bad idea to have the EJBs control
                resource allocation. You should let the server do it. If you need to use the
                same connection across requests, use the JTA transaction notion
                to define what those requests are and let the server "cache" the connection
                against the transaction.
                It's called "Transaction Stickiness" on the WIKI page describing the pooling.

                Anyway, that's enough free consulting. :-) All I can say is that you have been
                warned that what you are doing is anti-pattern and I've listed some of the
                main reasons why, plus given you an idea of how to redefine what you
                are doing as a "unit of work" with better semantics.

                And I didn't even mention the horrible BMT SFSB semantics. :-)

                • 7. Re: Why is jboss closing my connection?
                  tek no Novice

                  Ok, OK, you've convinced me ;) I will look into using the container connection management to find me the right connection when I need it.

                  The reason I never considered transaction stickiness is that I am unsure whether using a transaction to demarcate a long-lasting-over-serveral-requests session is good form or not. Think of a telnet session here. Is it acceptable to use a tranasction to demaracate user activity from logon to logoff? That is the situation I effectively have.

                  Thank you

                  • 8. Re: Why is jboss closing my connection?
                    Adrian Brock Master

                    The point I'm making is that you wouldn't do it that way (demarcate logon/logoff).
                    A user can logon and not do anything. You are wasting resources.

                    Instead you would allocate a connection for a unit of work (e.g. upload/download some files).
                    For each unit of work, you would "reauthenticate" based on the CRI or Subject.

                    That way you get maximum sharing of connections and you don't have
                    unused connections lying around when they are not being used.
                    The number of open connections is directly related to the number of active units of work,
                    not the number of SFSBs a lot of which could be idle.

                    This would be most efficient if the backend supports something like session suspension
                    as some telnet servers do.
                    Related to that is (if you are writing the back end yourself), you would be better using the
                    XAResource interface and storing the session against the XID on the backend server.
                    That way you can use "interleaving" where you start the session on one connection
                    suspend it (close() - returning the connection to the pool for somebody else to use)
                    and resume it on a different physical connection (or the same connection)
                    when you need it again.

                    e.g. psuedo code

                    ConnectionFactory cf = ...
                    Connection c = cf.getConnection(); // Allocate connection from pool - start the session - XAResource.start(xid, TMNOFLAGS);
                    Object data;
                    try
                    {
                     data = c.download();
                    }
                    finally
                    {
                     // Return the connection to the pool - suspend the session - XAResource.suspend(xid);
                     c.close();
                    }
                    
                    // Do some long running process, we don't need to have the connection for this
                    // so let somebody else use it!
                    Object result = calc(data);
                    
                    Connection c = cf.getConnection(); // Reget a connection - resume the session - XAResource.start(xid, TM_RESUME);
                    try
                    {
                     c.upload(result);
                    }
                    finally
                    {
                     c.close();
                    }
                    


                    Finally, you also have greater ability to reap connections that are idle during low load periods.

                    • 9. Re: Why is jboss closing my connection?
                      tek no Novice

                      This is very interesting Adrian. I appreciate the time you have taken to explain all of this to me. However, let me state my problem more concretely so that this discussion doesn't become too theoretical.

                      I am developing a JCA connector to be used against a third-party's system. This system is a game server that plays various well known card games. The system is a legacy system that I have no control over. Whereas the system does support session disconnects/reconnects these are very expensive. The protocol is very chatty and requires you to do things like look up various servers for information, do public key exchange, etc. As such, i feel that doing a re-authentication on every request would be too costly ( I must run some benchmarks of course ).

                      Thats why I can't think of anything better than partitioning the connection pool ByApplication with max/min connections per sub pool being 1.

                      Thanks for the help