Running Javascript and Python code in a Java 15 application

255 Views Asked by At

I'm running Javascript code in my Java 15 application with GraalVM. It is a web application that runs on Tomee. It works fine, and now I also need to run Python code with GraalVM.

What are the libraries I need to include in pom.xml? I see several here:

https://mvnrepository.com/artifact/org.graalvm.python

This is what I have today in pom.xml:

    <dependency>
        <groupId>org.graalvm.js</groupId>
        <artifactId>js</artifactId>
        <version>22.1.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.graalvm.js</groupId>
        <artifactId>js-scriptengine</artifactId>
        <version>22.1.0.1</version>
    </dependency>

should I change from graal.js to graal.sdk? I want to be able to run either Javascript or Python with the same engine.

2

There are 2 best solutions below

5
Steves On BEST ANSWER

Edit:

For JDK < 21 there aren't any Maven artifacts for GraalPy (Python on GraalVM). Moreover, previous releases of GraalPy for JDKs < 21 are not maintained. On top of that JDK15 is out of life, so "I hope this is not an important system." ;-)

However, you can use an older GraalVM release, ideally LST that is still supported, for example as of now 21.3. You can choose GraalVM 21.3 based on JDK17 or JDK11. There may be some other unsupported GraalVM releases based on JDK15 lying around too. Then download GraalPy for given GraalVM (https://github.com/oracle/graalpython/releases) and install it using $GRAALVM_HOME/bin/gu install -F the-graalpython-release.jar. Then you use that GraalVM installation as you JDK (i.e., $JAVA_HOME). GraalPy will be "just" available out of the box there. No need to any dependencies. You can do the same for JavaScript.


If you can upgrade Java to 21 or later:

What you want for Python embedding in Java is:

These are mata-poms that include all the necessary dependencies from the org.graalvm.python group and elsewhere. So your pom.xml should look like:

    <dependencies>
        <dependency>
            <groupId>org.graalvm.polyglot</groupId>
            <artifactId>polyglot</artifactId>
            <version>23.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.graalvm.polyglot</groupId>
            <artifactId>python-community</artifactId>
            <version>23.1.1</version>
            <type>pom</type>
        </dependency>
    </dependencies>

and then you can do things like:

try (var ctx = org.graalvm.polyglot.Context.create("python")) {
    ctx.eval("python", "print('Hello world')"); 
}

It seems that you are using JavaScript via the Script engine API. This is not supported for Python. One can find some example Script engine implementations, but the recommended approach is to use the Context API. It is language agnostic, so you can use it for both Python and JavaScript.

1
VonC On

Check if oracle/graal issue 6852 can help:

We’re looking for feedback from Java developers who utilize the org.graalvm.polyglot API to embed languages such as JavaScript, Python, Ruby, Espresso, WebAssembly, LLVM, etc. within Java. Version 23.1 (September release) is set to introduce some significant changes to how embedding in Java applications works. In previous versions, you had to install a language with gu, our Graal Updater tool (e.g., gu install python). Post 23.1, this will no longer be possible. You’ll need to download the artifacts from a Maven Repository and run them using the module-path instead.

To clarify how this will work, here’s a brief example for a new Maven configuration that includes Python.

<?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.yourcorp.yourapp</groupId>
    <artifactId>yourartefact</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency> <!-- We also move from graal-sdk => polyglot --> 
            <groupId>org.graalvm.polyglot</groupId>
            <artifactId>polyglot</artifactId>
            <version>23.1.0</version>
        </dependency>
        <dependency> <!-- you can also depend on org.graalvm.polyglot:languages for all languages --> 
            <groupId>org.graalvm.python</groupId>
            <artifactId>python</artifactId>
            <version>23.1.0</version>
            <type>pom</type>
        </dependency>
        <dependency> <!-- all tools we include in Oracle GraalVM --> 
            <groupId>org.graalvm.polyglot</groupId>
            <artifactId>tools</artifactId>
            <version>23.1.0</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

Note: If you want Open Source versions of all these components you need to change the artefact names to python-community and tools-community.

Note: We also broke the org.graalvm.sdk module (graal-sdk.jar) into several parts: nativeimage, polyglot, word and collections. We will still deploy a deprecated version of this module in the next release to not break your code.

That would illustrate the kind of dependency you can test in your pom.xml.

And that would also point out the GraalVM updater gu, a command-line tool for installing and managing optional GraalVM language runtimes and utilities, which could help in case maven dependencies are not available in your case.


Yes, I had tried this, but it didn't work, it seems that it's only supported for Java 21?
Also, I'm not sure how to apply the GraalVM updater to the EAR jar file that I have in Tomee.

Maybe check if the process described in "tomitribe/graalvm-microprofile" could give some ideas, as it does mention (4 years ago, so before Java 21) using gu install python to install the python language in GraalVM.

But: I am not sure how you would apply the GraalVM updater to an EAR file in a Tomee server environment. Normally, the GraalVM updater is used to install or update languages and tools in a GraalVM installation. However, integrating this into an EAR deployment would require that the correct versions of libraries and scripts are packaged within the EAR file.

As alternative approaches, you might consider:

  • if updating Java is not an option, exploring using the GraalVM Polyglot API explicitly in your code to manage the execution of Python scripts. That might offer more control and compatibility with your existing Java version.
  • running the Python code in a separate service, possibly in a container, and communicating with it from your Java application. That approach could bypass the limitations of integrating directly into GraalVM and provide more flexibility.