1

Not quite a duplicate of this Q&A when I try to use a JDBC driver from Node.js.

For reference, Node.js runs initialize.js which is the following script:

var JDBC = require('jdbc');
var jinst = require('jdbc/lib/jinst');

if (!jinst.isJvmCreated()) {
    jinst.addOption("-Xrs");
    jinst.setupClasspath(['./drivers/hsqldb.jar',
        './drivers/derby.jar',
        './drivers/derbyclient.jar',
        './drivers/derbytools.jar']);
}

var config = {
    // Required
    url: 'jdbc:hsqldb:hsql://localhost/xdb',

    // Optional
    drivername: 'org.hsqldb.jdbc.JDBCDriver', //'my.jdbc.DriverName',
    minpoolsize: 10,
    maxpoolsize: 100,

    // Note that if you sepecify the user and password as below, they get
    // converted to properties and submitted to getConnection that way.  That
    // means that if your driver doesn't support the 'user' and 'password'
    // properties this will not work.  You will have to supply the appropriate
    // values in the properties object instead.
    user: 'SA',
    password: '',
    properties: {}
};

// or user/password in url
// var config = {
//   // Required
//   url: 'jdbc:hsqldb:hsql://localhost/xdb;user=SA;password=',
//
//   // Optional
//   drivername: 'my.jdbc.DriverName',
//   minpoolsize: 10
//   maxpoolsize: 100,
//   properties: {}
// };

// or user/password in properties
// var config = {
//   // Required
//   url: 'jdbc:hsqldb:hsql://localhost/xdb',
//
//   // Optional
//   drivername: 'my.jdbc.DriverName',
//   minpoolsize: 10,
//   maxpoolsize: 100,
//   properties: {
//     user: 'SA',
//     password: ''
//     // Other driver supported properties can be added here as well.
//   }
// };

var hsqldb = new JDBC(config);

hsqldb.initialize(function(err) {
    if (err) {
        console.log(err);
    }
});

I am getting the following error:

$ node initialize.js 
Error: Could not find class org.hsqldb.jdbc.JDBCDriver
java.lang.UnsupportedClassVersionError: org/hsqldb/jdbc/JDBCDriver has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

    at JDBC.Pool.initialize (/home/me/PROJECTS/angular/node-jdbc-master/node_modules/jdbc/lib/pool.js:156:10)
    at Object.<anonymous> (/home/me/PROJECTS/angular/node-jdbc-master/initialize.js:61:8)
    at Module._compile (node:internal/modules/cjs/loader:1103:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47 {
  cause: nodeJava_java_lang_UnsupportedClassVersionError {}
}

The error happens in this function:

Pool.prototype.initialize = function(callback) {
  var self = this;

  winston.level = this._logging.level;

  // If a drivername is supplied, initialize the via the old method,
  // Class.forName()
  if (this._drivername) {
    java.newInstance(this._drivername, function(err, driver) { //ERROR!!!
      if (err) {
        return callback(err);
      } else {
        dm.registerDriver(driver, function(err) {
          if (err) {
            return callback(err);
          }
          self._addConnectionsOnInitialize(callback);
        });
      }
    });
  }
  else {
    self._addConnectionsOnInitialize(callback);
  }

  jinst.events.emit('initialized');
};

However I do have the latest JRE on the path:

$ java -version
java version "18.0.1" 2022-04-19
Java(TM) SE Runtime Environment (build 18.0.1+10-24)
Java HotSpot(TM) 64-Bit Server VM (build 18.0.1+10-24, mixed mode, sharing)

Why then do I get this error?

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
rapt
  • 11,810
  • 35
  • 103
  • 145
  • 1
    Classfile version 52.0 is Java 8. Clearly, node.js is invoking a Java 8 JVM, not the one you think it is using. – Jim Garrison Apr 21 '22 at 22:56
  • Yes but from where could Node.js get the idea to choose Java 8 rather than the one which is on PATH? – rapt Apr 21 '22 at 23:01
  • The fact is node is using Java 8. That is indisputable based on the message. Does node bundle its own JVM? Do you have a leftover JVM installed? How does node choose the JVM? Is there a configuration setting? – Jim Garrison Apr 21 '22 at 23:03
  • @JimGarrison I have several versions of Java installed. I am using node v16.14.2, I don't know if it comes with its own JVM. I don't know how node.js chooses the JVM version in general or specifically in the project I linked to (I guess this is the question I am asking here). – rapt Apr 21 '22 at 23:25
  • @trashgod I had to upgrade the older driver provided in the project because I had some other error. It's possible that upgrading it to a lesser amount would not invoke this new error. But I prefer not to resort to voodoo solutions. I think it's better for me to find out where Node (or some other entity) bypasses the PATH info. – rapt Apr 22 '22 at 14:41
  • @trashgod, Yes, that was the reason I had to upgrade the provided driver: my local db was too new for the provided driver, so I replaced the driver with the newest (current) one. Now, I did understand before posting OP that Node (or some entity) uses an older JRE than the compiler of the driver jar. It's not clear to me why. And that's what my OP is about. I.e. my question is not a duplicate as far as I can tell. – rapt Apr 22 '22 at 18:49

1 Answers1

0

It looks like your JDBCDriver throws UnsupportedClassVersionError.

java.lang.UnsupportedClassVersionError: org/hsqldb/jdbc/JDBCDriver has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0

As show here, newer versions of Java can use classes compiled with older versions, but not vice-versa. In this case, the problem is somewhat obscured by the implementation of the Java Standard Edition Service Provider mechanism. The problem arises when the JDBCDriver "creates an instance of itself and register it with the DriverManager." At a minimum, the HSQLDB and corresponding JDBCDriver class versions must match.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045