24

Trying to compile my app against java 1.7 I found what there was a new method added in javax.sql.CommonDataSource (and so in j.s.DataSource) -- .getParentLogger(). You can compare CommonDataSource:1.7 with CommonDataSource:1.6

For me this change definitely breaks backward compatibility. For example, my app (which contains implementations of DataSource) even doesn't compile against 1.7 without changes in code.

By my opinion, it should be very strong reasons for doing this -- but I can't google even one. Can somebody explain the reasoning behind this change? How it's supposed to deal with it correctly -- for me it's a first time I've met with backward uncompatibility with java, so I do not have any "best practices" here...

Buhake Sindi
  • 82,658
  • 26
  • 157
  • 220
BegemoT
  • 3,608
  • 1
  • 21
  • 29
  • 1
    It's not the first time. This always happens when they update JDBC. I agree that this is Not A Nice Thing (tm). Many drivers for example need to maintain separate versions just because of this. It is a pain, but it should only result in compile errors, not in runtime errors (i.e. you can build for JDK6 and still run it against JDK7). – Thilo Dec 14 '11 at 11:08
  • 2
    JDBC interfaces have become backward-incompatible several times (by adding methods) in the past. You should be able to add the additional methods to your classes, and they should work without problem in pre-1.7 environments. – JB Nizet Dec 14 '11 at 11:16
  • Hm... Doesn't it breaks binary compatibility? I mean -- my implementation of DS was compiled against old DS, without new method added -- it seems to be binary incompatible change, isn't it? – BegemoT Dec 14 '11 at 11:16
  • 1
    compiling against the old API and running on the new JDK will work (unless of course someone calls those new methods). The other way around (compiling for the new, running on the old) will probably cause ClassNotFoundExceptions. – Thilo Dec 15 '11 at 01:02

3 Answers3

7

If you're not ready to support compiling your application for Java 7, you can still compile for Java 1.6 using the Java 7 compiler. You will need a Java 1.6 runtime environment (or SDK) installed. If you try compiling a MyDataSource.java class that implements a stubbed DataSource using a Java 7 compiler, you might see the following:

$ java -version 
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) Server VM (build 21.0-b17, mixed mode)
$ javac -version
javac 1.7.0
$ javac MyDataSource.java 
MyDataSource.java:7: error: MyDataSource is not abstract and does not override abstract method getParentLogger() in CommonDataSource
public class MyDataSource implements DataSource {
       ^
1 error

You need to tell the compiler that you want to use source files written for Java 1.6, produce Java 1.6 bytecode and where to find the Java 1.6 runtime JAR:

$ javac -source 1.6 -target 1.6 -bootclasspath <path to Java 1.6 JRE>/lib/rt.jar MyDataSource.java 
$ file MyDataSource.class 
MyDataSource.class: compiled Java class data, version 50.0 (Java 1.6)
$ javap MyDataSource
Compiled from "MyDataSource.java"
public class MyDataSource implements javax.sql.DataSource {
  public MyDataSource();
  public java.io.PrintWriter getLogWriter() throws java.sql.SQLException;
  public void setLogWriter(java.io.PrintWriter) throws java.sql.SQLException;
  public void setLoginTimeout(int) throws java.sql.SQLException;
  public int getLoginTimeout() throws java.sql.SQLException;
  public <T extends java/lang/Object> T unwrap(java.lang.Class<T>) throws java.sql.SQLException;
  public boolean isWrapperFor(java.lang.Class<?>) throws java.sql.SQLException;
  public java.sql.Connection getConnection() throws java.sql.SQLException;
  public java.sql.Connection getConnection(java.lang.String, java.lang.String) throws java.sql.SQLException;
}
Dan Cruz
  • 14,336
  • 6
  • 39
  • 64
6

First add the requested new method(s) without the @Override annotation.

If you don't mind supporting the new methods simply throw SQLFeatureNotSupportedException.

If you are wrapping another DataSource and want to support 6 and 7, use reflection to call the methods if they exists.

eskatos
  • 3,495
  • 2
  • 33
  • 37
0

Another way to handle this is to change the environment variables of PATH and JAVA_HOME

Here is way to deal with it on Mac:

export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home

export PATH=/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/bin/:$PATH

stones333
  • 7,618
  • 1
  • 22
  • 24