I'm trying to use the Polyglot API of GraalVM, and an example I see in the documentation does not work.
The documentation of Context.asValue states:
When Java host objects are passed to guest languages, their public methods and fields are provided as members.
And a code example is provided:
class JavaRecord {
public int x = 42;
public double y = 42.0;
public String name() {
return "foo";
}
}
Context context = Context.create();
Value record = context.asValue(new JavaRecord());
assert record.getMember("x").asInt() == 42;
...
However this code doesn't work for me. record.getMember("x")
returns null
. record.getMemberKeys
also returns just an empty list ([]
).
The same thing happens for another example, this time passing a method to Context.asValue
. The documentation states:
And single method interfaces annotated with FunctionalInterface are executable directly.
Illustrating with the example:
Context context = Context.create();
...
assert context.asValue((Supplier<Integer>) () -> 42).execute().asInt() == 42;
But when I run this example myself, I get UnsupportedOperationException: Unsupported operation Value.execute(Object...) ...
I'm using org.graalvm.polyglot:polyglot:24.0.1
, the latest version I found on the maven repository. Does anybody know how I can get this working? How can I pass functions and data to guest languages?
What the documentation omits is 1) you need to configure your Context
instance: allow the access to the host (==Java):
Context.newBuilder().allowHostAccess(HostAccess.ALL).build()
and 2) the stuff you're accessing must be public
, including the class that declares them. Full example:
import org.graalvm.polyglot.*;
public class Main {
public static class JavaRecord {
public int x = 42;
public double y = 42.0;
public String name() {
return "foo";
}
}
public static void main(String[] args) {
try (Context context = Context.newBuilder()
.allowHostAccess(HostAccess.ALL)
.build()) {
Value record = context.asValue(new JavaRecord());
System.out.println(record.getMember("x").asInt());
}
}
}