During an Upgrade from Wildfly 27.0.1 to Wildfly 29.0.1 I run into a compatibility problem with the GraalVM Script engine which we are using in our Open Source Workflow engine Imixs-Workflow.
One reason was that wildfly does no longer support Truffle version below 23.1.1. So our old maven dependencies used in our Web application did no longer work in Wildfly 29.0.1:
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>22.3.5</version>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>22.3.5</version>
</dependency>
You will see a server log error like this:
Polyglot version compatibility check failed.
The polyglot version '24.1.2' is not compatible to the used Truffle version '23.1.1'.
The Truffle or language version is older than the polyglot version in use.
The polygot and truffle version must always match.
Update the Truffle or language versions to '24.1.2' to resolve this.
You can fix this issue just by upgrading to the latest grallvm version 24.1.2.
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>24.1.2</version>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-language</artifactId>
<version>24.1.2</version>
</dependency>
Note: Also the artifact names have changed in GraalVM too!
So GraalVM ersion 22.3.5 runs fine with Wildfly 27.0.1 but is no longer compatible with Wildfly 29.0.1. I think one reason is that Wildfly and GraalVM have aligned there package names somehow. See release notes here.
Missing sun/misc Dependencies
But now Wildfly 29.0.1 will run into another problem with the missing class sun.misc.Unsave
. You will see a runtime error during initializing the script engine like this one:
Caused by: java.lang.NoClassDefFoundError: sun/misc/Unsafe
my-app.war//com.oracle.truffle.api.dsl.InlineSupport$UnsafeField.getUnsafe(InlineSupport.java:1346)
my-app.war//com.oracle.truffle.api.dsl.InlineSupport$UnsafeField.<clinit>(InlineSupport.java:1358)
my-app.war//com.oracle.truffle.api.strings.TruffleStringFactory$HashCodeNodeGen.<clinit>(TruffleStringFactory.java:2013)
my-app.war//com.oracle.truffle.api.strings.TruffleString$HashCodeNode.getUncached(TruffleString.java:3113)
my-app.war//com.oracle.truffle.api.strings.TruffleString$HashCodeNode.calculateHashCodeUncached(TruffleString.java:3121)
my-app.war//com.oracle.truffle.api.strings.AbstractTruffleString.hashCode(AbstractTruffleString.java:1321)
my-app.war//com.oracle.truffle.api.strings.TruffleString.createConstant(TruffleString.java:191)
my-app.war//com.oracle.truffle.api.strings.TruffleString.createConstant(TruffleString.java:185)
my-app.war//com.oracle.truffle.api.strings.TruffleString$Encoding.<clinit>(TruffleString.java:1062)
my-app.war//com.oracle.truffle.polyglot.PolyglotValueDispatch.createDefaultValues(PolyglotValueDispatch.java:1704)
my-app.war//com.oracle.truffle.polyglot.PolyglotImpl.initialize(PolyglotImpl.java:205)
my-app.war//org.graalvm.polyglot.Engine.loadAndValidateProviders(Engine.java:1691)
my-app.war//org.graalvm.polyglot.Engine$1.run(Engine.java:1717)
my-app.war//org.graalvm.polyglot.Engine$1.run(Engine.java:1712)
The reason for this error message is that some legacy JDK modules have been deprecated in Wildfly 29. This means some deprecated classes like the sun.misc.Unsave
will not be provided by Wildfly to a deployment. A detailed discussion can be found here.
1) The Easy Solution
The way to get access to sun.misc.Unsafe is by adding a dependency on the ‘jdk.unsupported’ module. The easiest way to do this is to use WildFly’s global modules feature. Just add the module ‘jdk.unsupported’ to your ee subsystem config in standalone.xml:
...
<subsystem xmlns="urn:jboss:domain:ee:6.0">
...
<global-modules>
<module name="jdk.unsupported"/>
</global-modules>
</subsystem>
....
This will solve the issue for all your deplyoments using the GraalVM Scripting or Polyglot feature. Find also more about his solution here.
2) The Deployment Specific Solution
In case you want to be more specific how this module can be used by a deployment you can also configure a custom module and add a jboss-deployment-structure.xml into your application. In this case you have do define a custom module and activate the module in your deployment. In the following I will explain to to setup your Wildfly and your deployment.
First create a file ‘module.xml
‘ with the following content
<module name="org.graalvm" xmlns="urn:jboss:module:1.6">
<properties>
<property name="jboss.api" value="public" />
</properties>
<dependencies>
<system export="true">
<paths>
<!-- GrallVM Scriptengine support -->
<path name="sun/misc" />
</paths>
</system>
</dependencies>
</module>
and copy this file into your Wildfly server under modules:
.
├── modules
│ ├── org
│ │ ├── graalvm
│ │ │ └── main
│ │ │ └── module.xml
If you using Docker, a Dockerfile may look like this:
FROM quay.io/wildfly/wildfly:29.0.1.Final-jdk17
# Copy custom modules
COPY ./docker/configuration/modules/ /opt/jboss/wildfly/modules/
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0"]
Finally create a file jboss-deployment-structure.xml with the following content:
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.graalvm" export="true" />
</dependencies>
</deployment>
</jboss-deployment-structure>
and place this custom deployment descriptor into your application /WEB-INF/
directory. This deployment descriptor will advice Wildfly to take care of your custom module ‘org.graalvm’.
That’s it! The first solution is more easy but activate the deprecated classes for all deployments. The second solution is more specific and will work with Wildfly 27.0.1 too. So you can upgrade you GraalVM Script engine and customize you project to be deployable on Wildfly 27, 29 and upcoming versions. Thanks to the help from the Wildfly team.
One Reply to “Using GraalVM Script Engine with Wildfly 29”