title: HikariCP Connection Leak using unwrapped oracle.jdbc.driver.T4CConnection
body: <p>I am having an issue with a resource leak using HikariCP with an Unwrapped Connection. A little explanation then the code.</p>
  
  <p>I must use an unwrapped connection to access Oracle methods for oracle.sql.BFILE. This is streaming a binary out of an Oracle Directory.</p>
  
  <p>DataSource Example:</p>
  
  <pre><code>private static DataSource unwrapDatasource;
  public static synchronized DataSource getUnwrappedDataSource() {
      if (unwrapDatasource == null) {
          HikariConfig config = new HikariConfig();
          config.setMaximumPoolSize(50);
          config.setLeakDetectionThreshold(120000);
          config.setJdbcUrl(DATABASEURL);
          config.addDataSourceProperty("user", USERNAME);
          config.addDataSourceProperty("password", DBPASSWORD);
          config.addDataSourceProperty("driverType", "thin");
          config.setDriverClassName("oracle.jdbc.pool.OracleDataSource");
          config.setMaxLifetime(300000);
          config.setPoolName("UNWRAP");
          unwrapDatasource = new HikariDataSource(config);
      }
  
      return unwrapDatasource;
  }
  
    public static Connection getUnwrappedConnection() {
      Connection con = null;
      try {
          con = this.getUnwrappedDataSource().getConnection().unwrap(oracle.jdbc.driver.OracleConnection.class);
      } catch (SQLException ex) {
          //logger junk ommitted for brevity
      }
      return con;
  }
  </code></pre>
  
  <p>Using HikariCP-java7-2.4.12 as the app is very old and running on tomcat-6.
  Here is sample of the Connection that gets reported as Leaked with </p>
  
  <pre><code>    com.zaxxer.hikari.pool.ProxyLeakTask.run(poolProxyLeak.java:91) : &lt;Connection leak detection triggered for {}, stack trace follows&gt;
  java.lang.Exception: Apparent connection leak detected
      at myapp.package.obfuscated.getUnwrapConnection(DataSourceConstants.java:253)
      at myapp.package.obfuscated.BB.execute(DatabaseCallingClass2.java:106)
      at myapp.package.obfuscated.BB.execute(DatabaseCallingClass2.java:85)
      at myapp.package.obfuscated.AA.execute(DataBaseCallingClass.java:52)
      at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:425)
      at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:228)
      at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
      at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:123)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:563)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:610)
      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503)
      at java.lang.Thread.run(Thread.java:745)
  </code></pre>
  
  <p>Here is the Connection and how it is used:</p>
  
  <pre><code>     Connection con = null;
       PreparedStatement pstmt = null;
       OracleResultSet rs = null;
       InputStream inputStream = null;
       StringBuilder stringBuilder = new StringBuilder(128);
       try {
              con = DataSourceConstants.getUnwrappedConnection();
  
              pstmt = con.prepareStatement("SELECT BFILENAME('ORACLE_DIR', 'fileDownload.12345') AS BFILE from dual" );  //hardcoded for example
              rs = (OracleResultSet) pstmt.executeQuery();
  
              rs.next();  //Assumption if rs.next() blows up, catch would grab it and resources would all attempt to close in finally block
  
              bfile = rs.getBFILE(1);
              bfile.open();
              inputStream = bfile.getBinaryStream();
              char c;
              long size = bfile.length();
  
              int i = 0;
              do {
                  c= (char) inputStream.read();
                  stringBuilder.append(c);
              } while (++i &lt; size);
  
              } catch (Exception ex) {
                //logger ommitted but not throwing here
              } finally {
               //cleanup resources
               try { inputStream.close(); } catch (Exception ex) {}
               try { bfile.close(); } catch (Exception ex) {}
               try { rs.close(); } catch (Exception ex) {}
               try { pstmt.close(); } catch (Exception ex) {}
               try {con.close();  } catch (Exception ex){}
              }
         //use stringBuilder later in built output.
  </code></pre>
  
  <p>So The above retrieves an unwrapped T4CConnection so that I can use the OracleResultSet and BFILE / getBFILE(). This works and I get the result that I want, however two separate Classes using this structure to retrieve a BFILE are both Leaking, and another method that doesn't use BFILE but is using an Unwrapped Connection to use OracleCallableStatement is also leaking. I have instantiated 3 DataSources to split all of the connectors by type/function, the only pool that Leaks is the one using Datasource.getConnection().unwrap(oracle.jdbc.driver.OracleConnection.class) for its connectors.</p>
  
  <p>Am I doing something wrong with an unwrapped connection? Why is this the only one that leaks? Is this a known driver bug? (I haven't come up with any articles on it) BFILE doesn't seem to be very popular...</p>