Hi Tim,
Welcome back from "holiday" (I know moving house is no vacation).
The questions boil down to:
1. Why is it that if I create a jar with an org.example.foo.Nifty in it, and put that jar in the lib directory of my module alongside the MySQL Connector/J jar, this JavaScript code in the module main:
try {
stdout.println("typeof org.example.foo.Nifty: " + typeof org.example.foo.Nifty);
stdout.println("Loading org.example.foo.Nifty");
java.lang.Class.forName("org.example.foo.Nifty");
stdout.println("typeof com.mysql.jdbc.Driver: " + typeof com.mysql.jdbc.Driver);
stdout.println("Loading com.mysql.jdbc.Driver");
java.lang.Class.forName("com.mysql.jdbc.Driver");
}
catch (e) {
stdout.println("Exception: " + (e.message || e.toString()));
}
...produces this output:
typeof org.example.foo.Nifty: function
Loading org.example.foo.Nifty
typeof com.mysql.jdbc.Driver: function
Loading com.mysql.jdbc.Driver
Exception: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
? Why would it find the class in one jar but not the other? Why can it find it when making the Java packages available to JavaScript, but not when doing Class.forName?
2. If I explicitly create a driver instance in the JavaScript main:
var driver = new com.mysql.jdbc.Driver();
...then in theory, the static init of the Driver class should have occurred. That static init from the MySQL Connector/J source in com.mysql.jdbc.Driver.java looks like this:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
...and so I'd expect that this following line of JavaScript code in my main:
conn = java.sql.DriverManager.getConnection(
"jdbc:mysql://localhost/jdbcexample",
"username",
"password"
);
...would be referring to the same DriverManager that the static init in the Driver class registered with. But it would seem not, because it fails saying it can't find a registered driver for the URL. Why is that?
3. Why is it that if I create another jar with this compiled class in it:
package com.farsightsoftware;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.DriverManager;
public class DriverBridge {
public static final void loadDriver(String cls)
throws ClassNotFoundException {
Class.forName(cls);
}
public static final Connection getConnection(String url, String user, String pass)
throws SQLException {
return DriverManager.getConnection(url, user, pass);
}
}
...then this JavaScript code in main *works*
stdout.println("Loading driver");
com.farsightsoftware.DriverBridge.loadDriver("com.mysql.jdbc.Driver");
stdout.println("Getting connection");
conn = com.farsightsoftware.DriverBridge.getConnection(
"jdbc:mysql://localhost/jdbcexample",
"username",
"password"
);
? The driver gets found by the Java call to Class.forName, and the static init registers with the DriverManager that the Java code sees, and all is well.
Just to be clear, none of this is meant as disguised criticism (questions like this can seem that way, particularly from someone you don't know). I'm just trying to understand the environment. It could be that one or more of these issues points up something worth changing in the platform, but equally it could be that once you understand it, it makes sense.
I suspect all of the above stem from something fundamental, possibly even something simple, that I'm just not getting. Probably two distinct things, actually: One for why one class is found and the other isn't (question #1), and another related to the other questions. I suspect part of it relates to different classloaders being used for making the Java classes available to JavaScript and loading classes from jars in the lib directory, but that's speculation, and even two different classloaders doesn't quite seem (to me) to explain all of the above.
Thanks in advance,
-- T.J.