Derby
  1. Derby
  2. DERBY-2488 When loaded by jvm1.6 - EmbeddedConnectionPoolDataSource is not returning a JDBC 4 compliant PooledConnection object
  3. DERBY-2582

EmbeddedConnectionPoolDataSource does not implement java.sql.Wrapper but reports JDBC 4 compliance when run with JDK 6

    Details

    • Type: Sub-task Sub-task
    • Status: Closed
    • Priority: Major Major
    • Resolution: Duplicate
    • Affects Version/s: 10.2.2.1
    • Fix Version/s: None
    • Component/s: JDBC
    • Environment:
      JDK 6
    • Urgency:
      Normal
    • Issue & fix info:
      High Value Fix

      Description

      Software that checks the value returned by the dataseMetadata method getJDBCMajorVersion for JDBC compliance level and, based on the value, takes different paths in the code will fail unexpectedly accessing java.sql.Wrapper when loading EmbeddedConnectionPoolDataSource in a JDK 6 environment. EmbeddedConnectionPoolDataSource reports a compliance level of 4 when loaded in a JDK 6 environment. It returns JDBC 4 objects but the Datasource itself does NOT satify the JDBC 4.0 interface Wrapper and so, not being fully compliant, should not report JDBC 4 compliance.

      JSR 221 does not detail the behavior of the dataseMetadata method getJDBCMajorVersion but the description in Section 6.3, JDBC 4.0 API Compliance, states: "A driver that is compliant with the JDBC 4.0 specification must .. Fully implement .. java.sql.Wrapper". As Dan stated in his comment on DERBY-2488, (http://issues.apache.org/jira/browse/DERBY-2488#action_12485033) EmbeddedConnectionPoolDataSource does not implement Wrapper.

        Issue Links

          Activity

          Hide
          Daniel John Debrunner added a comment -

          Dumb question but what from the DataSource api indicates "JDBC 4 compliance"?

          The javadoc for DatabaseMetaData.getJDBCMajorVersion() does not say anything about compliance.

          Show
          Daniel John Debrunner added a comment - Dumb question but what from the DataSource api indicates "JDBC 4 compliance"? The javadoc for DatabaseMetaData.getJDBCMajorVersion() does not say anything about compliance.
          Hide
          Stan Bradbury added a comment -

          Being new to issues of API specs and all I don't know. The words used are those of the development lead I spoke to about the topic. They are using the metadata call as described. I do not recall if the word compliance was used, however, I don't want that to detract from the problem presented here. The situation for this developer is as described. The metadata call is used to determine what is supported in code using the datasource. His comment upon finding that the datasource did not implement this JDBC 4 interfaces was:

          "For non JDBC4.0 providers we expect JDBC3.0 to be returned (or JDBC2.0 depending on the spec version), otherwise, we would break."

          Upon looking at the JSR221 sections cited above this seemed like a reasonable use of the call so I raised this issue so others in the community familiar with implementing datasources in complex environments could give there assessment of whether this might be a problem in other development efforts as well.

          Show
          Stan Bradbury added a comment - Being new to issues of API specs and all I don't know. The words used are those of the development lead I spoke to about the topic. They are using the metadata call as described. I do not recall if the word compliance was used, however, I don't want that to detract from the problem presented here. The situation for this developer is as described. The metadata call is used to determine what is supported in code using the datasource. His comment upon finding that the datasource did not implement this JDBC 4 interfaces was: "For non JDBC4.0 providers we expect JDBC3.0 to be returned (or JDBC2.0 depending on the spec version), otherwise, we would break." Upon looking at the JSR221 sections cited above this seemed like a reasonable use of the call so I raised this issue so others in the community familiar with implementing datasources in complex environments could give there assessment of whether this might be a problem in other development efforts as well.
          Hide
          Daniel John Debrunner added a comment -

          I see the issue but I'm not sure of a solution. I think compliance is the key point here though, as EmbeddedConnectionPoolDataSource does not claim to be JDBC 4.0 compliant in a JDK 6 environment. So once compliance is not there, any requirement to implement java.sql.Wrapper goes away.

          Of course I think the only compliance indicator in JDBC is on Driver and Derby's driver is JDBC 4.0 compliant, but it doesn't really have a direct relationship to DataSource objects.

          Maybe the meta-data call could return 3 for getJDBCMajorVersion() but then connection objects within the same JVM would be returning different values.
          I.e. Connection objects created by old data source implementations would return 3 while those created by DriverManager or the 40 data source implementations would return 4. Even though it's the same implementation of Connection in all cases, i.e. all Connection objects in a JDK 6 environment are JDBC 4.0 compliant. This would be additional code for the only reason of satisfying this condition, which is assuming compliance for something that isn't.

          Another question is what is the Wrapper interface being used for? The Wrapper interface is explicitly for non-standard features provided by the JDBC driver and since Derby does not provide any non-standard features there should be no need to treat any of its JDBC objects as Wrappers.

          Show
          Daniel John Debrunner added a comment - I see the issue but I'm not sure of a solution. I think compliance is the key point here though, as EmbeddedConnectionPoolDataSource does not claim to be JDBC 4.0 compliant in a JDK 6 environment. So once compliance is not there, any requirement to implement java.sql.Wrapper goes away. Of course I think the only compliance indicator in JDBC is on Driver and Derby's driver is JDBC 4.0 compliant, but it doesn't really have a direct relationship to DataSource objects. Maybe the meta-data call could return 3 for getJDBCMajorVersion() but then connection objects within the same JVM would be returning different values. I.e. Connection objects created by old data source implementations would return 3 while those created by DriverManager or the 40 data source implementations would return 4. Even though it's the same implementation of Connection in all cases, i.e. all Connection objects in a JDK 6 environment are JDBC 4.0 compliant. This would be additional code for the only reason of satisfying this condition, which is assuming compliance for something that isn't. Another question is what is the Wrapper interface being used for? The Wrapper interface is explicitly for non-standard features provided by the JDBC driver and since Derby does not provide any non-standard features there should be no need to treat any of its JDBC objects as Wrappers.
          Hide
          A B added a comment -

          I can't say that I fully understand the issue, but from what I gather the application in question is receiving some DataSource from somewhere and it (the application) needs to figure out whether or not that DataSource object is JDBC 4. I assume the app itself is not the one creating the datasource (if it was then it should theoretically know whether or not it instantiated the JDBC 4 Derby datasource class, shouldn't it?).

          My inclination is to agree with Dan's comment above: "I think the only compliance indicator in JDBC is on Driver and Derby's driver is JDBC 4.0 compliant, but it doesn't really have a direct relationship to DataSource objects."

          To me it seems odd to change Derby's connection objects to return a driver version of 3 for DataSources even though the connection and the driver are both JDBC 4.

          One possible application-side workaround to this problem (if it's actually a problem with Derby, of which I am not sure) is to use reflection on the data source and then check the declared methods. Since EmbeddedConnectionPoolDataSource40 is a public class that we expect users/apps to be referencing directly, it seems like we should be able to suggest that applications code according to the public javadoc for that class:

          http://db.apache.org/derby/javadoc/engine/org/apache/derby/jdbc/EmbeddedConnectionPoolDataSource40.html

          Notice that all of the Derby *40 data source classes declare two public methods, both of which are required for JDBC 4:

          public boolean isWrapperFor(Class<?> interfaces)
          public <T> T unwrap(java.lang.Class<T> interfaces)

          So if an application has some generic DataSource object and it wants to determine whether or not that data source is JDBC 4, one possible approach is to iterate through the declared methods and search for either of the above two. If "ds" is some DataSource object, we could do something like:

          boolean isJDBC4DataSource = false;
          java.lang.reflect.Method [] mA = ds.getClass().getDeclaredMethods();
          for (int i = 0; i < mA.length; i++)
          {
          String methodName = mA[i].getName();
          if (methodName.equals("isWrapperFor") || methodName.equals("unwrap"))

          { isJDBC4DataSource = true; break; }

          }

          Maybe this is too naive of an approach, but when I tried it on a simple repro it seems to have done the trick (i.e. isJDBC4DataSource remained false for the JDBC 3 datasource but was set to true for the JDBC 4 datasources). For what that's worth...

          Show
          A B added a comment - I can't say that I fully understand the issue, but from what I gather the application in question is receiving some DataSource from somewhere and it (the application) needs to figure out whether or not that DataSource object is JDBC 4. I assume the app itself is not the one creating the datasource (if it was then it should theoretically know whether or not it instantiated the JDBC 4 Derby datasource class, shouldn't it?). My inclination is to agree with Dan's comment above: "I think the only compliance indicator in JDBC is on Driver and Derby's driver is JDBC 4.0 compliant, but it doesn't really have a direct relationship to DataSource objects." To me it seems odd to change Derby's connection objects to return a driver version of 3 for DataSources even though the connection and the driver are both JDBC 4. One possible application-side workaround to this problem (if it's actually a problem with Derby, of which I am not sure) is to use reflection on the data source and then check the declared methods. Since EmbeddedConnectionPoolDataSource40 is a public class that we expect users/apps to be referencing directly, it seems like we should be able to suggest that applications code according to the public javadoc for that class: http://db.apache.org/derby/javadoc/engine/org/apache/derby/jdbc/EmbeddedConnectionPoolDataSource40.html Notice that all of the Derby *40 data source classes declare two public methods, both of which are required for JDBC 4: public boolean isWrapperFor(Class<?> interfaces) public <T> T unwrap(java.lang.Class<T> interfaces) So if an application has some generic DataSource object and it wants to determine whether or not that data source is JDBC 4, one possible approach is to iterate through the declared methods and search for either of the above two. If "ds" is some DataSource object, we could do something like: boolean isJDBC4DataSource = false; java.lang.reflect.Method [] mA = ds.getClass().getDeclaredMethods(); for (int i = 0; i < mA.length; i++) { String methodName = mA [i] .getName(); if (methodName.equals("isWrapperFor") || methodName.equals("unwrap")) { isJDBC4DataSource = true; break; } } Maybe this is too naive of an approach, but when I tried it on a simple repro it seems to have done the trick (i.e. isJDBC4DataSource remained false for the JDBC 3 datasource but was set to true for the JDBC 4 datasources). For what that's worth...
          Hide
          Daniel John Debrunner added a comment -

          Simpler check would be

          ds instanceof java.sql.Wrapper

          Show
          Daniel John Debrunner added a comment - Simpler check would be ds instanceof java.sql.Wrapper
          Hide
          Daniel John Debrunner added a comment -

          or derby specific

          ds instanceof EmbeddedConnectionPoolDataSource40

          Show
          Daniel John Debrunner added a comment - or derby specific ds instanceof EmbeddedConnectionPoolDataSource40
          Hide
          A B added a comment -

          >Simpler check would be
          > ds instanceof java.sql.Wrapper

          I don't think this works, as all DataSources are instances of java.sql.Wrapper in a Java 1.6 JVM. At least that's what I noticed when I tried this.

          > ds instanceof EmbeddedConnectionPoolDataSource40

          I guess that's simple enough Assumes application is running with Java 1.6 and is Derby-specific, but you're right, that'd be the easies route.

          Show
          A B added a comment - >Simpler check would be > ds instanceof java.sql.Wrapper I don't think this works, as all DataSources are instances of java.sql.Wrapper in a Java 1.6 JVM. At least that's what I noticed when I tried this. > ds instanceof EmbeddedConnectionPoolDataSource40 I guess that's simple enough Assumes application is running with Java 1.6 and is Derby-specific, but you're right, that'd be the easies route.
          Hide
          A B added a comment -

          > Assumes application is running with Java 1.6

          Err, meant "built", not "running". Or is it possible to build an application that references a *40 class without JDBC 4?

          Show
          A B added a comment - > Assumes application is running with Java 1.6 Err, meant "built", not "running". Or is it possible to build an application that references a *40 class without JDBC 4?
          Hide
          Knut Anders Hatlen added a comment -

          It is also possible to add wrapper methods with these signatures to the old data sources:

          public boolean isWrapperFor(Class iface)
          public Object unwrap(Class iface)

          This will work as long as you access them through the ConnectionPoolDataSource interface (or the Wrapper interface) on Java 1.6, like this:

          ConnectionPoolDataSource ds = myEmbeddedConnectionPoolDataSource;
          if (ds.isWrapperFor(EmbeddedConnectionPoolDataSource.class)

          { EmbeddedConnectionPoolDataSource ds2 = ds.unwrap(EmbeddedConnectionPoolDataSource.class); }

          I'm not saying it's a good solution, but perhaps it could reduce the problem?

          Show
          Knut Anders Hatlen added a comment - It is also possible to add wrapper methods with these signatures to the old data sources: public boolean isWrapperFor(Class iface) public Object unwrap(Class iface) This will work as long as you access them through the ConnectionPoolDataSource interface (or the Wrapper interface) on Java 1.6, like this: ConnectionPoolDataSource ds = myEmbeddedConnectionPoolDataSource; if (ds.isWrapperFor(EmbeddedConnectionPoolDataSource.class) { EmbeddedConnectionPoolDataSource ds2 = ds.unwrap(EmbeddedConnectionPoolDataSource.class); } I'm not saying it's a good solution, but perhaps it could reduce the problem?
          Hide
          Kathey Marsden added a comment -

          Marking normal urgency and HVF so hopefully it will get picked up for the next release. This won't make it for 10.5.2.

          Show
          Kathey Marsden added a comment - Marking normal urgency and HVF so hopefully it will get picked up for the next release. This won't make it for 10.5.2.
          Hide
          Knut Anders Hatlen added a comment -

          EmbeddedConnectionPoolDataSource and friends have implemented the java.sql.Wrapper methods since DERBY-5880/Derby 10.10.1.1, so I believe this is not an issue anymore. Closing the issue.

          Show
          Knut Anders Hatlen added a comment - EmbeddedConnectionPoolDataSource and friends have implemented the java.sql.Wrapper methods since DERBY-5880 /Derby 10.10.1.1, so I believe this is not an issue anymore. Closing the issue.

            People

            • Assignee:
              Unassigned
              Reporter:
              Stan Bradbury
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development