BTM
  1. BTM
  2. BTM-81

detectJdbcVersion may lead to "java.lang.AbstractMethodError"

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.3.3
    • Fix Version/s: 2.0.0
    • Labels:
      None
    • Environment:
      Java 1.6.0_01 + Oracle JDBC 3 Driver (10.2.0.3)
    • Number of attachments :
      0

      Description

      Using an old JVM with JDBC3 may lead to java.lang.AbstractMethodError: oracle.jdbc.driver.LogicalConnection.isValid(I)Z.

      It prevents pooled to be initialized.

      Using JDBC4 (latest Oracle 11g driver) or JVM 1.6.0_20 can workaround this issue.

        Activity

        Hide
        Johann Dupuis added a comment - - edited

        Replacing in JdbcPooledConnection.java, line 93:

        } catch (Exception ex) {

        with

        } catch (Throwable th) {

        is fixing this issue.

        Show
        Johann Dupuis added a comment - - edited Replacing in JdbcPooledConnection.java, line 93: } catch (Exception ex) { with } catch (Throwable th) { is fixing this issue.
        Hide
        Ludovic Orban added a comment - - edited

        I don't like the idea of catching Throwable. How about patching the detectJdbcVersion() method this way instead?

            private synchronized void detectJdbcVersion(Connection connection) {
                if (jdbcVersionDetected > 0)
                    return;
        
                try {
                    isValidMethod = connection.getClass().getMethod("isValid", new Class[]{Integer.TYPE});
                    if (Modifier.isAbstract(isValidMethod.getModifiers())) {
                        jdbcVersionDetected = 3;
                    } else {
                        isValidMethod.invoke(connection, new Object[]{new Integer(DETECTION_TIMEOUT)}); // test invoke
                        jdbcVersionDetected = 4;
                        if (!poolingDataSource.isEnableJdbc4ConnectionTest()) {
                            if (log.isDebugEnabled()) log.debug("dataSource is JDBC4 or newer and supports isValid(), but enableJdbc4ConnectionTest is not set or is false");
                        }
                    }
                } catch (Exception ex) {
                    jdbcVersionDetected = 3;
                }
                if (log.isDebugEnabled()) log.debug("detected JDBC connection class '" + connection.getClass() + "' is version " + jdbcVersionDetected + " type");
            }
        
        Show
        Ludovic Orban added a comment - - edited I don't like the idea of catching Throwable. How about patching the detectJdbcVersion() method this way instead? private synchronized void detectJdbcVersion(Connection connection) { if (jdbcVersionDetected > 0) return; try { isValidMethod = connection.getClass().getMethod("isValid", new Class[]{Integer.TYPE}); if (Modifier.isAbstract(isValidMethod.getModifiers())) { jdbcVersionDetected = 3; } else { isValidMethod.invoke(connection, new Object[]{new Integer(DETECTION_TIMEOUT)}); // test invoke jdbcVersionDetected = 4; if (!poolingDataSource.isEnableJdbc4ConnectionTest()) { if (log.isDebugEnabled()) log.debug("dataSource is JDBC4 or newer and supports isValid(), but enableJdbc4ConnectionTest is not set or is false"); } } } catch (Exception ex) { jdbcVersionDetected = 3; } if (log.isDebugEnabled()) log.debug("detected JDBC connection class '" + connection.getClass() + "' is version " + jdbcVersionDetected + " type"); }
        Hide
        Brett Wooldridge added a comment -

        Ludovic, I like your proposed change.

        Show
        Brett Wooldridge added a comment - Ludovic, I like your proposed change.
        Hide
        Brett Wooldridge added a comment -

        On second thought, I don't think it does what you think it does. I believe the Modifier.isAbstract() will perform a class-level modifier check, rather than an instance check. In other words, it can detect if a class declares a method abstract, but I don't think it can detect whether a class method is implicitly abstract because it does not implement an interface method. I think we should be able to catch java.lang.AbstractMethodError explicitly (rather than Throwable) to handle this case.

        Show
        Brett Wooldridge added a comment - On second thought, I don't think it does what you think it does. I believe the Modifier.isAbstract() will perform a class-level modifier check, rather than an instance check. In other words, it can detect if a class declares a method abstract, but I don't think it can detect whether a class method is implicitly abstract because it does not implement an interface method. I think we should be able to catch java.lang.AbstractMethodError explicitly (rather than Throwable) to handle this case.
        Hide
        Ludovic Orban added a comment -

        fixed in trunk

        Show
        Ludovic Orban added a comment - fixed in trunk
        Hide
        Johann Dupuis added a comment -

        Works fine with "btm-2.0.0-beta2".

        Thank you.

        Show
        Johann Dupuis added a comment - Works fine with "btm-2.0.0-beta2". Thank you.

          People

          • Assignee:
            Ludovic Orban
            Reporter:
            Johann Dupuis
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: