Disclaimer
This article is an expansion from a previous, separate Oracle forums thread. The question posed was (paraphrasing):
Can I use ORDS with Oracle GraalVM for JDK 21 (despite the ORDS team only officially claiming support for Oracle JDK 17, Oracle JDK 21, Oracle GraalVM Enterprise Edition for Java version 17, and Oracle GraalVM Enterprise Edition for Java version 21)?
And, if I can, how do I install the Oracle GraalVM for JDK 21 graaljs and polyglot dependencies required for ORDS’ GraphQL UI and querying capabilities?
I’m also reiterating, that what follows is experimental only. We still need to investigate the possibility of supporting Oracle GraalVM for JDK 17 or 21 (the non-Enterprise Editions) in future ORDS releases. So, stay tuned. With all the disclaimers and release of liability out of the way, read on if you’d like learn how to build these dependencies for Oracle GraalVM for JDK 21.
You’ll need Maven first though.
Install Maven
Install the Java project build tool Maven. Installation instructions for your OS can be found here.
Create a new Maven project
Next, create a new Maven project1 (you can use the maven-archetype-quickstart
archetype for your project) by executing this command in your terminal:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5 -DinteractiveMode=false
Next cd
into the project folder (e.g., the artifactId, in this case “my-app”):
cd my-app
Your project folder will resemble the following:
.
├── pom.xml
└── src
├── main
│ └── java
│ └── com
│ └── mycompany
│ └── app
│ └── App.java
└── test
└── java
└── com
└── mycompany
└── app
└── AppTest.java

You can disregard /src/test
subfolder and its descendants.
Modify the pom.xml file
You will need to modify the quickstart project’s pom.xml file. Add the following dependencies2 in the <dependencies></dependencies>
parameter section:
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>polyglot</artifactId>
<version>[TBD]</version>
</dependency>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>js</artifactId>
<version>[TBD]</version>
<type>pom</type>
</dependency>
How do I know which version to choose?
Check the Release Notes for the JDK you intend to use. In this case, I’m configuring Oracle GraalVM for JDK 21.0.7, which is based on Oracle JDK 21. The Release Notes state:
Truffle languages and other components version 23.1.7 are designed for use with GraalVM for JDK 21.0.7.” So, I’m using the following polyglot and js versions.
Updated pom.xml file
Your updated POM.xml file should end up looking like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.11.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<!-- Optionally: parameterized tests support -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>polyglot</artifactId>
<version>23.1.7</version>
</dependency>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>js</artifactId>
<version>23.1.7</version>
<type>pom</type>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.4.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.12.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.6.1</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Copy the Maven dependencies
Save your changes, and then from your terminal execute the following command:
mvn dependency:copy-dependencies
You’ll notice a new /target/dependency
subfolder in your project, along with new .jar and .pom files:
.
├── pom.xml
├── src
│ ├── main
│ │ └── java
│ │ └── com
│ │ └── mycompany
│ │ └── app
│ │ └── App.java
│ └── test
│ └── java
│ └── com
│ └── mycompany
│ └── app
│ └── AppTest.java
└── target
├── classes
│ └── com
│ └── mycompany
│ └── app
│ └── App.class
├── dependency
│ ├── apiguardian-api-1.1.2.jar
│ ├── collections-23.1.7.jar
│ ├── icu4j-23.1.7.jar
│ ├── jniutils-23.1.7.jar
│ ├── js-23.1.7.pom
│ ├── js-community-23.1.7.pom
│ ├── js-language-23.1.7.jar
│ ├── junit-jupiter-api-5.11.0.jar
│ ├── junit-jupiter-params-5.11.0.jar
│ ├── junit-platform-commons-1.11.0.jar
│ ├── nativebridge-23.1.7.jar
│ ├── nativeimage-23.1.7.jar
│ ├── opentest4j-1.3.0.jar
│ ├── polyglot-23.1.7.jar
│ ├── regex-23.1.7.jar
│ ├── truffle-api-23.1.7.jar
│ ├── truffle-compiler-23.1.7.jar
│ ├── truffle-enterprise-23.1.7.jar
│ ├── truffle-runtime-23.1.7.jar
│ └── word-23.1.7.jar
└── test-classes
└── com
└── mycompany
└── app
└── AppTest.class

Relocate the new .pom and .jar files
You’ll need to move all of the files from this temporary app project, and place them into your [ORDS product folder]/lib/ext
folder. If you recall, when you first configure and install ORDS, the best practice is to set the ORDS/bin
3 and ORDS_CONFIG
environment variables.
If I issue the ENV
command in a terminal, I’ll see something similar to the following:
TMPDIR=/var/folders/wm/t9qmbgnn3f577b51xzb5yrkc0000gp/T/
__CFBundleIdentifier=com.apple.Terminal
XPC_FLAGS=0x0
TERM=xterm-256color
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.sFYLlexTu3/Listeners
XPC_SERVICE_NAME=0
TERM_PROGRAM=Apple_Terminal
TERM_PROGRAM_VERSION=455.1
TERM_SESSION_ID=*********-****-****-****-**********
SHELL=/bin/zsh
HOME=/Users/choina
LOGNAME=choina
USER=choina
PATH=/opt/homebrew/Caskroom/sqlcl/25.1.1.113.2054/sqlcl/bin:/Library/Frameworks/Python.framework/Versions/3.13/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/podman/bin:/Users/choina/ords/25.2.0.r1651520/bin
SHLVL=1
PWD=/Users/choina/my-app
OLDPWD=/Users/choina
HOMEBREW_PREFIX=/opt/homebrew
HOMEBREW_CELLAR=/opt/homebrew/Cellar
HOMEBREW_REPOSITORY=/opt/homebrew
INFOPATH=/opt/homebrew/share/info:
ORDS_CONFIG=/Users/choina/ords/ords_config
LANG=en_US.UTF-8
_=/usr/bin/env
```

Notice in the PATH
variable the location of my “ORDS Product Folder”: /Users/choina/ords/25.2.0.r1651520/bin
. You can use that “root” /Users/choina/ords/25.2.0.r1651520/
and cd
directly to the /lib/ext
folder. Like this:
cd /Users/choina/ords/25.2.0.r1651520/lib/ext
Drag and drop (or use the mv
command) all of these new .jar and .pom files from the /target/dependency
folder into the ORDS /lib/ext
folder. Your ORDS product folder will now look something like this:
.
├── bin
│ ├── ords
│ ├── ords-metrics
│ └── ords.exe
├── docs
│ └── javadoc
│ └── plugin-api
├── examples
│ ├── application-container
│ │ └── README.md
│ ├── db_auth
│ │ ├── index.html
│ │ └── sql
│ ├── ords-metrics
│ │ ├── create_alarms.sh
│ │ └── ords-metrics.service
│ ├── plugins
│ │ ├── lib
│ │ ├── plugin-demo
│ │ └── plugin-javascript
│ ├── pre_hook
│ │ ├── index.html
│ │ ├── README.md
│ │ └── sql
│ └── soda
│ └── getting-started
├── icons
│ └── ords_logo2.ico
├── lib
│ └── ext
│ ├── apiguardian-api-1.1.2.jar
│ ├── collections-23.1.7.jar
│ ├── icu4j-23.1.7.jar
│ ├── jniutils-23.1.7.jar
│ ├── js-language-23.1.7.jar
│ ├── junit-jupiter-api-5.11.0.jar
│ ├── junit-jupiter-params-5.11.0.jar
│ ├── junit-platform-commons-1.11.0.jar
│ ├── nativebridge-23.1.7.jar
│ ├── nativeimage-23.1.7.jar
│ ├── opentest4j-1.3.0.jar
│ ├── polyglot-23.1.7.jar
│ ├── README
│ ├── regex-23.1.7.jar
│ ├── truffle-api-23.1.7.jar
│ ├── truffle-compiler-23.1.7.jar
│ ├── truffle-enterprise-23.1.7.jar
│ ├── truffle-runtime-23.1.7.jar
│ └── word-23.1.7.jar
├── LICENSE.txt
├── linux-support
│ ├── man
│ │ ├── ords.1
│ │ ├── ords.conf.5
│ │ └── ords.service.8
│ ├── ords.conf
│ ├── ords.service
│ ├── ords.sh
│ └── README.md
├── NOTICE.txt
├── ords.war
├── scripts
│ ├── installer
│ │ ├── apex_ords_app_con_grants.sql
│ │ ├── ords_installer_privileges.sql
│ │ └── ords_set_editioning.sql
│ └── migrate
│ ├── ords_manual_migrate_workspace.sql
│ ├── ords_manual_migrate.sql
│ ├── ords_migrate_apex_rest.sql
│ ├── ords_migrate_report.sql
│ └── ords_migrate_workspace_rest.sql
└── THIRD-PARTY-LICENSES.txt

Close out all of your terminal sessions. And make sure you are using the correct version of Java; you can check with the java --version
command.
Restart ORDS and test
Restart ORDS, the ords/_/graphiql
endpoint should be available. You can access it one of three ways:
- Directly by navigating to http://host:port/ords/[your schema]/_/graphiql
- From:
- the SQL Developer Web LaunchPad
- the SQL Developer (Hamburger) menu



The end
That’s it. You should now have a test/experimental version of GraalVM for JDK 21 with the required Graal js and polyglot dependencies installed (much like you would with the now-deprecated gu installer).