2 Replies Latest reply on Mar 29, 2006 4:45 AM by koen.aers

    Question about DbPersistenceService

    jesse_sweetland

      We're trying to troubleshoot a connection leak that we think might be associated with our recent adoption of JTA and I ran across something interesting in DbPersistenceService.java. The getConnection(boolean resolveSession) method calls getDataSource(), which checks to see if there is a JNDI data source name registered on the DbPersistenceService. If so, then it gets a connection from that DataSource and returns it to open a Hibernate session with a user-supplied connection. My first question is: how does one register a JNDI data source name on the DbPersistenceService? We've specified a hibernate.connection.datasource property in Hibernate.cfg.xml, but I since the getDataSource() method is checked first I want to make sure that there is no other overriding configuration that might prevent Hibernate from using its data source.

      My second question concerns the following block of code from the getSession() method:

      Connection connection = getConnection(false);
      if (connection!=null) {
       log.debug("creating hibernate session with connection "+connection);
       session = getSessionFactory().openSession(connection);
       mustSessionBeClosed = true;
       mustSessionBeFlushed = true;
       mustConnectionBeClosed = false;
      } else {
       log.debug("creating hibernate session");
       session = getSessionFactory().openSession();
       mustSessionBeClosed = true;
       mustSessionBeFlushed = true;
       mustConnectionBeClosed = false;
      }
      


      If a JNDI data source name was registered on the DbPersistenceService, and a connection was retrieved from that DataSource, then the first block is taken (user-supplied connection to the Hibernate session). I looked in the Hibernate ConnectionManager.java class and it looks like if a connection is supplied, then Hibernate does not close the connection. This being the case, it would seem that the mustConnectionBeClosed field should be set to "true" in top branch. The close() method of DbPersistenceService will not call connection.close() if it is false, and Hibernate does not close the connection since it was supplied to the session factory, so the connection is never closed and leaks. Is that accurate?

      As an aside, has anyone had an issue using JTA in jBPM 3.1 on JBoss 4.0.3 with Oracle? The leak does not seem to happen in non-JTA environments, and it only happens from web services that are not backed by Session beans (web applications and session-bean-backed web services do not appear to leak).

      Thanks,

      - Jesse

        • 1. Re: Question about DbPersistenceService
          jesse_sweetland

          Found the source of my connection leak, and it may or may not be related to the above post, so I'll put it here in case anyone is interested.

          My web service was creating a JbpmContext and calling getConnection() to get a connection. My assumption was that this was a shortcut for Jbpm.getSession().getConnection(), which is not exactly true. Lookin at DbPersistenceService, they end up being essentially the same thing unless that JNDI data source name property is somehow registered on the DbPersistenceService. I then created a JDBC PreparedStatement on the connection, executed some arbitrary SQL, and closed the JbpmContext, thinking that when the JbpmContext was closed, the Hibernate session would commit and close and the underlying connection would be taken care of.

          As it turns out, TxConnectionManager.end() was called (which tells me the connection.commit() method was called) but the TxConnectionManager.connectionClosed() method was never invoked. I suspect that Hibernate has some magic in the Transaction.commit() method that handles JTA transactions if there was work done during the transaction (in my case Hibernate didn't know about the work being done because I used an external JDBC PreparedStatement). I came to this conclusion for two reasons:

          1. Using a Hibernate SQLQuery instead of a PreparedStatement fixed the connection leak
          2. Using PreparedStatements does not cause a connection leak if JTA is not used

          Does using JTA imply exclusive use of the jBPM and/or Hibernate APIs? Is it incorrect to mix JDBC and Hibernate calls in a JTA transaction? Was there another step I needed to take (such as an exclusive JTA commit)?

          - Jesse

          • 2. Re: Question about DbPersistenceService
            koen.aers

            Jesse,

            Hibernate (and by consequence also jBPM) make the assumption that once you obtain a reference to the connection, you will handle the closing and disposal of it yourself. The rationale is that the lifecycle of the connection is from then on in your own hands. But it is perfectly ok to do what you want to do.

            Regards,
            Koen