2

My Goal:

I'm building a "plugin" for Apache Unomi, which seems to be a pretty standard set of Karaf / OSGi services. As part of this, I'd like to be able to execute Javascript (and eventually Nodejs) from inside my Java code, and the best option moving forward seems to be GraalVM (I'm not interested in using anything legacy like Nashorn/Rhino). My current work in progress is in this PR on my fork of Unomi.

My Issue:

I'm unable to get GraalVM Polyglot code working inside a Karaf module. Adding Maven dependencies fails at runtime, and manually adding the class (that the GraalVM runtime should provide) into my framework config file throws an error about no additional languages available.

What I've Done So Far:

I've successfully installed GraalVM for JDK 11 (OS X Catalina)

% java -version
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment GraalVM CE 20.0.0 (build 11.0.6+9-jvmci-20.0-b02)
OpenJDK 64-Bit Server VM GraalVM CE 20.0.0 (build 11.0.6+9-jvmci-20.0-b02, mixed mode, sharing)

I've referenced the GraalVM tutorial for Maven on JDK 11 and added the following to my plugin's pom based on the example:

        <dependency>
            <groupId>org.graalvm.sdk</groupId>
            <artifactId>graal-sdk</artifactId>
            <version>20.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.graalvm.js</groupId>
            <artifactId>js</artifactId>
            <version>20.0.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.graalvm.js</groupId>
            <artifactId>js-scriptengine</artifactId>
            <version>20.0.0</version>
        </dependency>

I've also added some sample code per the GraalVM documentation to my plugin:

Context polyglot = Context.create();
Value array = polyglot.eval("js", "[1,2,42,4]");
int result = array.getArrayElement(2).asInt();

What Happens (Fails):

At this point, my Maven build completes without errors. When I start Karaf, however, I immediately get an error (full output):

Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=unomi-router-karaf-feature; type=karaf.feature; version="[1.5.0.SNAPSHOT,1.5.0.SNAPSHOT]"; filter:="(&(osgi.identity=unomi-router-karaf-feature)(type=karaf.feature)(version>=1.5.0.SNAPSHOT)(version<=1.5.0.SNAPSHOT))" [caused by: Unable to resolve unomi-router-karaf-feature/1.5.0.SNAPSHOT: missing requirement [unomi-router-karaf-feature/1.5.0.SNAPSHOT] osgi.identity; osgi.identity=org.apache.unomi.router-rest; type=osgi.bundle; version="[1.5.0.SNAPSHOT,1.5.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve org.apache.unomi.router-rest/1.5.0.SNAPSHOT: missing requirement [org.apache.unomi.router-rest/1.5.0.SNAPSHOT] osgi.service; effective:=active; filter:="(&(objectClass=org.apache.unomi.router.api.services.ImportExportConfigurationService)(configDiscriminator=IMPORT))" [caused by: Unable to resolve org.apache.unomi.router-service/1.5.0.SNAPSHOT: missing requirement [org.apache.unomi.router-service/1.5.0.SNAPSHOT] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.apache.unomi.persistence.spi)(version>=1.5.0)(!(version>=2.0.0)))" [caused by: Unable to resolve org.apache.unomi.persistence-spi/1.5.0.SNAPSHOT: missing requirement [org.apache.unomi.persistence-spi/1.5.0.SNAPSHOT] osgi.identity; osgi.identity="root#unomi-kar-1.5.0.SNAPSHOT"; type=karaf.subsystem; version="[0,0.0.0]"; resolution:=mandatory [caused by: Unable to resolve root#unomi-kar-1.5.0.SNAPSHOT: missing requirement [root#unomi-kar-1.5.0.SNAPSHOT] osgi.identity; osgi.identity=unomi-kar; type=karaf.feature; version="[1.5.0.SNAPSHOT,1.5.0.SNAPSHOT]" [caused by: Unable to resolve unomi-kar/1.5.0.SNAPSHOT: missing requirement [unomi-kar/1.5.0.SNAPSHOT] osgi.identity; osgi.identity=org.apache.unomi.plugins-firstparty; type=osgi.bundle; version="[1.5.0.SNAPSHOT,1.5.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve org.apache.unomi.plugins-firstparty/1.5.0.SNAPSHOT: missing requirement [org.apache.unomi.plugins-firstparty/1.5.0.SNAPSHOT] osgi.wiring.package; filter:="(osgi.wiring.package=com.ibm.icu.impl)"]]]]]]]

If I remove the three dependencies from my plugin's pom and rebuild, I can start Karaf without issue. However, when I try and run my action in my Unomi plugin, it immediately says there's no graalvm polyglot class available (expected).

After some googling, I stumbled upon an existing GitHub issue, and followed the suggestion to add org.graalvm.polyglot to org.osgi.framework.system.packages.extra. This almost worked, but now when I try and run my action in my Unomi plugin, I get a PolyglotIllegalArgumentException: A language with id 'js' is not installed. Installed languages are: []. I then tried adding all of the classes I attempted including in the pom above in this manner, but it continued to return the same error.

I'm unsure of where to go from here. I'm guessing my inexperience with Maven is going to point out that this is a stupid problem, though after a lot of searching it appears that the small amount of content available around running GraalVM on OSGi all points to it possibly not working - though I have to imagine this is possible. My thoughts on a potential solution are

  1. I've configured my Maven pom poorly, and there's a way to solve this through a properly configured pom
  2. I need to specify additional system packages in org.osgi.framework.system.packages.extra beyond the single org.graalvm.polyglot, but am unsure of how to move forward here.

Any assistance is beyond appreciated!

Community
  • 1
  • 1
Kressaty
  • 41
  • 5
  • NOTE: The "GraalVM tutorial for Maven on JDK 11" is meant for stock JDK11. If you are using GraalVM you don't need to follow that maven config. I'm not very familiar with OSGi so I'm unsure how many things can go wrong. Could you provide a small reproducer project or something? – BoriS Mar 26 '20 at 16:58

1 Answers1

0

A language with id 'js' is not installed.

As I can see that is very outdated question but I hope my answer will help somebody. I also stumbled with that error in project written by another developer with GraalVM and js polyglot support. So I figured out why that problem happens and how to fix that. Error means you don't have JS lang component installed at your (linux) system. Use commands for 'GraalVM Component Updater' CLI.

Run command to see what is installed locally.

$ gu list

Probably you'll see a list like that.

ComponentId Version Component name Stability Origin
graalvm 22.3.0 GraalVM Core Supported
$ gu available

'Available' command gives the list of available components for downloading.

If you are missing JS component (most probably) you have to install it by next command.

$ gu install js

When check the installed list again.

$ gu list
ComponentId Version Component name Stability Origin
graalvm 22.3.0 GraalVM Core Supported
js 22.3.0 Graal.js Supported github.com

Error 'A language with id 'js' is not installed.' should gone away.

blandger
  • 718
  • 7
  • 17