The Graal Polyglot API lets you embed and run code from guest languages in JVM-based host applications.
In this article, we will cover how we create a Java API on top of a JavaScript library.
With more than 700 000 packages
npmjs
is the world’s largest repository of code!
You can find literally everything you need (or not).
For our example we will use the excellent
chroma.js
library.
chroma.js
is a tiny JavaScript library (but really useful) for dealing with colors!
Here’s an example for a simple read / manipulate / output chain:
chroma('pink').darken().saturate(2).hex() // "#ff6d93"
Use the GraalVM Polyglot API to evaluate the
chroma
library.
Now that we can use the
org.graalvm.polyglot
API in our code,
we are going to create a singleton class named
GraalVMChroma
in the
org.chroma
package:
package org.chroma;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
public class GraalVMChroma {
private final Value chroma;
private static GraalVMChroma instance = null;
private GraalVMChroma() {
Context context = Context.create();
URL chromaResource = Thread.currentThread().getContextClassLoader().getResource("chroma.min.js");
String content = new String(Files.readAllBytes(Paths.get(chromaResource.toURI())));
context.eval("js", content);
chroma = context.eval("js", "chroma");
public static GraalVMChroma create() {
if (instance == null) {
instance = new GraalVMChroma();
return instance;
public Value getChroma() {
return chroma;
In the code above, the file chroma.min.js will be read from the classpath and turned into a String
.
Then we evaluate the chroma library code, using the eval
method on the context
.
And finally, we use eval("js", "chroma")
to get the chroma
object.
The GraalVM Value
represents a polyglot value that can be accessed using a set of language agnostic operations.
Polyglot values have one of the following types:
static Chroma create(String color) {
try {
Value chroma = GraalVMChroma.create().getChroma();
Value instance = chroma.newInstance(color);
return new ChromaInstance(instance);
} catch (IOException | URISyntaxException e) {
throw new RuntimeException("Unable to instantiate Chroma GraalVM");
@Override
public Chroma darken() {
return new ChromaInstance(chromaInstance.getMember("darken").execute());
@Override
public Chroma saturate(int value) {
return new ChromaInstance(chromaInstance.getMember("saturate").execute(value));
@Override
public String hex() {
return chromaInstance.getMember("hex").execute().asString();
@Override
public List<Integer> rgba() {
List<Integer> result = new ArrayList<>();
Value value = chromaInstance.getMember("rgba").execute();
if (value.hasArrayElements()) {
for (int i = 0; i < value.getArraySize(); i++) {
result.add(value.getArrayElement(i).asInt());
return result;
Get the member called saturate
on the chroma instance and execute the function with a value
Get the member called hex
on the chroma instance, execute the function and return a String
Get the member called rgba
on the chroma instance, execute the function and build a Java List
from the Array Elements Value