'Calling JDBC from Node.js: java.lang.UnsupportedClassVersionError

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?



Solution 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 trashgod