Skip to main content
Broadpin

Migrating to Oracle SQLcl 25.3 (with JavaScript)

This blog post was written by Johannes Michler (Chief Technology Officer (CTO) @ Broadpin & Oracle Ace Director).

In a bunch of Broadpin customer projects we're leveraging Oracle SQLcl in combination with JavaScript to implement DevOps pipelines.

With the recent SQLcl 25.3 release this caused us a bunch of issues – here are our workarounds should you run into similar trouble.

Java / JavaScript support with SQLcl

As you can see in the release notes of SQLcl 25.3 starting with the latest release, only the following java versions are supported:

Java Releases support with SQLcl 25.3

When comparing this with 25.2 and 25.1 you'll realize, that starting even with 25.2 the support for Java 11 (which includes a Java-Script engine also in the Oracle Java 11) went away.

Strangely under Linux everything is still working with oracle/openjdk-11, but on Windows you'll get:

C:\Entwicklung\Projekte\ebs>sqlcl\bin\sql.exe
Oracle SQLcl Console: This application requires a Java Runtime Environment 17.0.5

C:\Entwicklung\Projekte\ebs>

(and Oracle is nice enough to open the browser to point you to the JDK download).

Since also on Linux openjdk-11 is no longer supported for sqlcl-25.2+ I looked into a migration to GraalVM 17 with the JavaScript Plugin.

Installation of GraalVM 17

The installation of GraalVM17 including the JavaScript plugin is simple enough: Navigate to https://www.oracle.com/downloads/graalvm-downloads.html, select the "GraalVM 17" tab and download "Oracle GraalVM Core". I just extracted the files to c:\Entwicklung\jdks\graalvm-jdk-17.0.17 and then set my PATH appropriately:

C:\Entwicklung\Projekte\ebs>set PATH=c:\Entwicklung\jdks\graalvm-jdk-17.0.17\bin;%PATH%;

C:\Entwicklung\Projekte\ebs>java -version
java version "17.0.17" 2025-10-21 LTS
Java(TM) SE Runtime Environment Oracle GraalVM 17.0.17+8.1 (build 17.0.17+8-LTS-jvmci-23.0-b76)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 17.0.17+8.1 (build 17.0.17+8-LTS-jvmci-23.0-b76, mixed mode, sharing)

Next us is the JavaScript plugin. The installation is described here: https://docs.oracle.com/en/graalvm/jdk/17/docs/reference-manual/graalvm-updater/#install-components

The easiest way to install the plugin is:

gu install js

You'll have to accept the OTN License (that you get e-mailed) and then all the required plugins are installed:

GraalVM including Java-Script

After that you can do a trivial test as follows:

C:\Entwicklung\Projekte\ebs>sqlcl\bin\sql.exe /nolog

SQLcl: Release 25.3 Production auf Di. Nov. 11 20:52:17 2025

Copyright (c) 1982, 2025, Oracle. All rights reserved. Alle Rechte vorbehalten.

SQL> script
2 ctx.write('test\n');
3* /
test
SQL>

Issue number one: directly running a script

Of course typically you'll have your script in a myscript.js file that you want to run. This worked without issues with openjdk-11 (still does on Linux), but on Windows I'm seeing:

C:\Entwicklung\Projekte\ebs>sqlcl\bin\sql.exe /nolog

SQLcl: Release 25.3 Production auf Di. Nov. 11 20:53:36 2025

Copyright (c) 1982, 2025, Oracle. All rights reserved. Alle Rechte vorbehalten.

SQL> !type test.js
ctx.write('Start extraction ...\n');

SQL> script test.js
TypeError: invokeMember (write) on oracle.dbtools.raptor.newscriptrunner.ScriptRunnerContext failed due to: Unknown identifier: write at line number 1 at column number 1
SQL>

Crazy thing. Running an empty script block before solves (or better: workarounds) this behavior that differs from the openjdk behavior with previous SQLcl versions:

C:\Entwicklung\Projekte\ebs>sqlcl\bin\sql.exe /nolog

SQLcl: Release 25.3 Production auf Di. Nov. 11 20:54:47 2025

Copyright (c) 1982, 2025, Oracle. All rights reserved. Alle Rechte vorbehalten.

SQL> script
2 ;
3* /
SQL> script test.js
Start extraction ...
SQL>

While I don't understand this, maybe I'll get an answer here: https://forums.oracle.com/ords/apexds/post/sqlcl-25-3-migrating-to-graalvm-with-js-plugin-0345

Lucky for me I run all my scripts through a small run.sql-helper that I just extended by 3 dummy-lines to make this workaround global across my project:

whenever oserror exit failure
whenever sqlerror exit failure
script
;
/
script &1 &2;
exit;

Issue number two: sql vs sql.exe and mingw

Usually I run my sqlcl scripts through a wrapper-bash-script that (on Windows) is executed through git-bash. Unfortunately, with SQLcl 25.3 there is another issue here:

jmichler@PROM-231 MINGW64 /c/Entwicklung/Projekte/ebs (feature/1123)
$ sqlcl/bin/sql -v
Exception in thread "main" java.lang.NoClassDefFoundError: oracle/dbtools/win32/WindowsSupport
at oracle.dbtools.raptor.utils.WindowsUtility.readStringSubKeys(WindowsUtility.java:81)
at oracle.dbtools.raptor.scriptrunner.cmdline.JDBCHelper.getOH(JDBCHelper.java:83)
at oracle.dbtools.raptor.scriptrunner.cmdline.JDBCHelper.isOHReal(JDBCHelper.java:58)
at oracle.dbtools.raptor.scriptrunner.cmdline.JDBCHelper.doesOHJDBCExist(JDBCHelper.java:120)
at oracle.dbtools.raptor.scriptrunner.cmdline.SQLCliOptions.populateContextWithOptions(SQLCliOptions.java:1040)
at oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli.processArgsAndPopulateInContext(SqlCli.java:329)
at oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli.processArgsAndPopulateInContext(SqlCli.java:321)
at oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli.main(SqlCli.java:276)
Caused by: java.lang.ClassNotFoundException: oracle.dbtools.win32.WindowsSupport
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
... 8 more

But the good thing is – as pointed out in xxx – this can be solved by just running sql.exe instead:

jmichler@PROM-231 MINGW64 /c/Entwicklung/Projekte/ebs (feature/1123)
$ sqlcl/bin/sql.exe -v

SQLcl: Release 25.3.0.0 Production Build: 25.3.0.274.1210

jmichler@PROM-231 MINGW64 /c/Entwicklung/Projekte/ebs (feature/1123)

And with this in place you'll run into a third (easy to solve) issue.

Issue number 3: Parameter passing with mingw

jmichler@PROM-231 MINGW64 /c/Entwicklung/Projekte/ebs (feature/1123)
$ sqlcl/bin/sql.exe /nolog

Invalid Option: C:/Program Files/Git/nolog

Oracle SQL Developer Command-Line (SQLcl) help

Luckily this can be solved by either passing double / or by setting the following environment variable:

jmichler@PROM-231 MINGW64 /c/Entwicklung/Projekte/ebs (feature/1123)
$ export MSYS2_ARG_CONV_EXCL="*"

jmichler@PROM-231 MINGW64 /c/Entwicklung/Projekte/ebs (feature/1123)
$ sqlcl/bin/sql.exe /nolog

SQLcl: Release 25.3 Production auf Di. Nov. 11 21:00:56 2025

Copyright (c) 1982, 2025, Oracle. All rights reserved. Alle Rechte vorbehalten.

SQL>

Thanks to https://forums.oracle.com/ords/apexds/post/sqlcl-25-3-noclassdeffounderror-when-running-from-git-bash-2576 for pointing out those solutions.

Complex Scripts and Summary

The good thing is: After having overcome those little hurdles the actual scripts and processes we had implemented work without any further modifications.

Hopefully Oracle will continue to support the JavaScript engine within sqlcl since it can be really helpful; even though it gets more and more complex to leverage the engine due to special JDK/JRE requirements.