views:

61

answers:

1

Hello,

I'm building an application which is collating data from multiple data sources. Of these data sources, we have multiple instances of Oracle running.

I find that the only way I can connect to my Oracle 8i instance is by using the ojdbc14.jar and the following:

String driver = "oracle.jdbc.OracleDriver";
String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=$HOST)(PORT=$PORT)))(CONNECT_DATA=(SID=$SID)))"
Class.forName(driver);
Connection c = DriverManager.getConnection(url, $USER, $PASSWORD);
c.close();

When I try to update to ojdbc5.jar or ojdbc6.jar, using the same code, I get an ArrayIndexOutofBoundsException. Ditto if I use just the URL "jdbc:oracle:thin:$user/$password@$host:$port:$sid", which does work against the more recent Oracle instances I'm connecting to.

I'd rather not get locked into having to use the older ojdbc14.jar (especially as I'm using Java 6) as I might have to support higher Oracle databases quite soon in the future.

So, I'm hoping one of two scenarios is possible:

1) There's a connection string I'm simply overlooking which can use to connect to Oracle 8i w/ more recent OJDBC jars.

2) I can have multiple OJDBC jars on my classpath so that I can use ojdbc14.jar on an exception basis and ojdbc6.jar everywhere else. The trick here, of course, is figuring out how to specify which jar the connection needs to use the "oracle.jdbc.OracleDriver" class from.

Any thoughts?

+1  A: 

Just out of curiosity I implemented your second approach via isolated classloader. It seems to be working:

public class DriverWrapper implements Driver {
    private Driver target;
    private String fakePrefix;
    private String realPrefix;

    protected DriverWrapper(Driver target, String  fakePrefix, String realPrefix) {
        this.target = target;
        this.fakePrefix = fakePrefix;
        this.realPrefix = realPrefix;
    }

    public static void loadDriver(URL[] classPath, String className, String fakePrefix, String actualPrefix) 
        throws Exception{

        URLClassLoader cl = new URLClassLoader(classPath, DriverWrapper.class.getClassLoader());
        Class<?> c = cl.loadClass(className);        

        // It's rather rude, but we haven't access to the existing instance anyway
        Driver d = (Driver) c.newInstance();
        Driver w = new DriverWrapper(d, fakePrefix, actualPrefix);

        // We don't care about already registerd instance, 
        // because driver loaded in isolated classloader 
        // is not visible to the rest of application, see DriverManager javadoc
        DriverManager.registerDriver(w);
    }

    private String resolveURL(String url) {
        if (url.startsWith(fakePrefix)) {
            return realPrefix + url.substring(fakePrefix.length());
        } else {
            return null;
        }
    }

    public boolean acceptsURL(String url) throws SQLException {
        url = resolveURL(url);
        if (url == null) {
            return false;
        } else {
            return target.acceptsURL(url);
        }
    }

    public Connection connect(String url, Properties info) throws SQLException  {
        url = resolveURL(url);
        if (url == null) {
            return null;
        } else {
            return target.connect(url, info);
        }
    }

    public int getMajorVersion() {
        return target.getMajorVersion();
    }

    public int getMinorVersion() {
        return target.getMinorVersion();
    }

    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException  {
        return target.getPropertyInfo(url, info);
    }

    public boolean jdbcCompliant() {
        return target.jdbcCompliant();
    }

}

Used as follows (driver jars shouldn't be located in the main classpath):

DriverWrapper.loadDriver(new URL[] { new File("ojdbc5.jar").toURL() }, 
    "oracle.jdbc.OracleDriver", "jdbc:oracle5", "jdbc:oracle");   
DriverWrapper.loadDriver(new URL[] { new File("ojdbc14.jar").toURL() }, 
    "oracle.jdbc.OracleDriver", "jdbc:oracle14", "jdbc:oracle");

... DriverManager.getConnection("jdbc:oracle14:...", ...);
... DriverManager.getConnection("jdbc:oracle5:...", ...);
axtavt