title: HIbernate - How to close multi-tenant connection pool?
body: <p>I'm having troubles with hibernate not closing the (hikari) connection pool in a multi-tenant setup. Here is the hibernate session-factory config:</p>
  
  <pre><code>&lt;session-factory&gt;
      &lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.PostgreSQL82Dialect&lt;/property&gt;
      &lt;property name="hibernate.multiTenancy"&gt;SCHEMA&lt;/property&gt;
      &lt;property name="hibernate.multi_tenant_connection_provider"&gt;foundation.hibernate.TaxonomyMultiTenantConnectionProvider&lt;/property&gt;
      &lt;property name="hibernate.jdbc.batch_size"&gt;100&lt;/property&gt;
      &lt;property name="hibernate.order_inserts"&gt;true&lt;/property&gt;
  
      &lt;property name="hibernate.hikari.dataSourceClassName"&gt;org.postgresql.ds.PGSimpleDataSource&lt;/property&gt;
      &lt;property name="hibernate.hikari.minimumIdle"&gt;50&lt;/property&gt;
      &lt;property name="hibernate.hikari.connectionTestQuery"&gt;SELECT 1&lt;/property&gt;
      &lt;property name="hibernate.hikari.maximumPoolSize"&gt;200&lt;/property&gt;
      &lt;property name="hibernate.hikari.idleTimeout"&gt;28000000&lt;/property&gt;
      &lt;property name="hibernate.hikari.maxLifetime"&gt;28000000&lt;/property&gt;
      &lt;property name="hibernate.hikari.connectionTimeout"&gt;10000&lt;/property&gt;
      &lt;property name="hibernate.hikari.dataSource.applicationName"&gt;Taxonomy Workbench&lt;/property&gt;
  
      &lt;property name="show_sql"&gt;true&lt;/property&gt;
      &lt;property name="format_sql"&gt;true&lt;/property&gt;
  
      &lt;mapping class="dal.models.DbProduct"/&gt;
  &lt;/session-factory&gt;
  </code></pre>
  
  <p>The implementation of TaxonomyMultiTenantConnectionProvider is as follows:</p>
  
  <pre><code>package foundation.hibernate;
  
  import com.zaxxer.hikari.HikariConfig;
  import com.zaxxer.hikari.HikariDataSource;
  import foundation.hibernate.TenantDoesNotExistException.TenantDoesNotExistException;
  import org.hibernate.engine.config.spi.ConfigurationService;
  import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
  import org.hibernate.service.spi.ServiceRegistryAwareService;
  import org.hibernate.service.spi.ServiceRegistryImplementor;
  
  import java.sql.Connection;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.util.Properties;
  
  public class TaxonomyMultiTenantConnectionProvider implements MultiTenantConnectionProvider, ServiceRegistryAwareService, AutoCloseable {
  
      private HikariDataSource dataSource;
  
      @Override
      public void injectServices(ServiceRegistryImplementor serviceRegistry) {
          Properties hikariSettings = new Properties();
          String hikariPrefix = "hibernate.hikari.";
          serviceRegistry.getService(ConfigurationService.class).getSettings().forEach((key, value) -&gt; {
              if (key instanceof String) {
                  String skey = (String) key;
                  if (skey.toLowerCase().startsWith(hikariPrefix)) {
                      hikariSettings.put(skey.substring(hikariPrefix.length()), value);
                  }
              }
          });
          dataSource = new HikariDataSource(new HikariConfig(hikariSettings));
      }
  
      @Override
      public Connection getAnyConnection() throws SQLException {
          System.out.println("getAnyConnection");
          return dataSource.getConnection();
      }
  
      @Override
      public void releaseAnyConnection(Connection connection) throws SQLException {
          System.out.println("releaseAnyConnection");
          dataSource.evictConnection(connection);
      }
  
      @Override
      public Connection getConnection(String tenantIdentifier) throws SQLException {
          //Acquire connection
          Connection connection = getAnyConnection();
  
          //Check if schema exists
          ResultSet rs = connection.createStatement().executeQuery(ConnectionSQL.schemaExists(tenantIdentifier));
          boolean found = false;
          while (rs.next()) {
              if (rs.getInt(1) == 1) {
                  found = true;
              }
          }
          rs.close();
          if (!found) {
              throw new TenantDoesNotExistException(tenantIdentifier);
          }
  
          //Change schema
          try {
              connection.createStatement().executeUpdate(ConnectionSQL.selectSchema(tenantIdentifier));
          } catch (Exception e) {
              throw new RuntimeException("Could not alter JDBC connection to specified schema [" + tenantIdentifier + "]", e);
          }
  
          return connection;
      }
  
      @Override
      public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
          System.out.println("releaseConnection");
          dataSource.evictConnection(connection);
      }
  
      @Override
      public boolean supportsAggressiveRelease() {
          System.out.println("supportsAggressiveRelease");
          return false;
      }
  
      @Override
      public boolean isUnwrappableAs(Class unwrapType) {
          System.out.println("isUnwrappableAs");
          return false;
      }
  
      @Override
      public &lt;T&gt; T unwrap(Class&lt;T&gt; unwrapType) {
          System.out.println("unwrap");
          return null;
      }
  
      @Override
      public void close(){
          System.out.println("close");
          dataSource.close();
      }
  
  }
  </code></pre>
  
  <p>The pooling and working with connections is fine. However, calling sessionFactory.close() will not close the connection pool.</p>
  
  <p>I found <a href="https://stackoverflow.com/a/20930906" title="this answer">this answer</a>. But in my case, getConnectionProvider() returns null.
  The code: </p>
  
  <pre><code>if (sessionFactory != null) {
      Logger.debug("Closing SessionFactory.");
      sessionFactory.close();
      if(sessionFactory instanceof SessionFactoryImpl){
          SessionFactoryImpl impl = (SessionFactoryImpl) sessionFactory;
          Logger.debug("Closing database connections.");
          ConnectionProvider conn = impl.getConnectionProvider();
          if(conn instanceof TaxonomyMultiTenantConnectionProvider){
              ((TaxonomyMultiTenantConnectionProvider) conn).close();
          } else {
              throw new RuntimeException("Unexpected ConnectionProvider");
          }
      }
  }
  </code></pre>
  
  <p>Any ideas on what I'm doing wrong?</p>
  
  <p>Thanks in advance!</p>
  
  <h3>edit</h3>
  
  <p>BTW: My hibernate version is <code>4.3.6-Final</code></p>