Search code examples
javamavengraalvm

Java dependencies not being loaded properly


I have a java project that I want to bundle up as a jar and run in several contexts. The library has a main function that I execute for testing.

When I run the code using mvn clean compile exec:java my main function runs and I get all the output I expect.

When I package the code as a jar the bundle seem to be correct. When I load the jar into my app I'm able to create my classes as I expect. However, when running the code that accesses dependencies, it throws the following error.

java.lang.IllegalStateException: No language and polyglot implementation was found on the class-path.
Make sure at last one language is added on the class-path. If you put a language on the class-path and
you encounter this error then there could be a problem with isolated class loading.
Use -Dpolyglotimpl.TraceClassPathIsolation=true to debug class loader islation problems.
For best performance it is recommended to use polyglot from the module-path instead of the class-path.

I've also tried running the jar on its own like so - I got the same error message.

java -cp target/cfwasm-1.0-SNAPSHOT-jar-with-dependencies.jar com.cfpoly
glot.Main

Why does it work when run from maven and not when run elsewhere? If my code can find and instantiate its dependencies (since they are bundled together) why does it claim they are not on the classpath?

This is my pom file

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.cfpolyglot</groupId>
  <artifactId>cfwasm</artifactId>
  <version>1.0-SNAPSHOT</version>
  <properties>
    <exec.mainClass>com.cfpolyglot.Main</exec.mainClass>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven-enforcer-plugin.version>3.0.0-M3</maven-enforcer-plugin.version>
    <maven-checkstyle-plugin.version>3.1.2</maven-checkstyle-plugin.version>
    <checkstyle.version>8.45.1</checkstyle.version>
    <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.graalvm.polyglot</groupId>
      <artifactId>polyglot</artifactId> 
      <version>23.1.1</version>
    </dependency>
    <dependency>
      <groupId>org.graalvm.polyglot</groupId>
      <artifactId>wasm</artifactId> 
      <version>23.1.1</version>
      <type>pom</type>
    </dependency>
    <dependency>
      <groupId>org.graalvm.polyglot</groupId>
      <artifactId>js</artifactId> 
      <version>23.1.1</version>
      <type>pom</type>
    </dependency>
    <dependency>
      <groupId>org.graalvm.polyglot</groupId>
      <artifactId>tools</artifactId>
      <version>23.1.1</version>
      <type>pom</type>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>${maven-enforcer-plugin.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>enforce</goal>
            </goals>
            <configuration>
              <rules>
                <requireMavenVersion>
                  <version>3.6.3</version>
                </requireMavenVersion>
              </rules>
              <fail>true</fail>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven-surefire-plugin.version}</version>
      </plugin>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
        <version>${maven-javadoc-plugin.version}</version>
      </plugin>
    </plugins>
  </reporting>
</project>


Solution

  • Due to the way the polyglot runtime works internally, bundling the polyglot runtime and languages into a fat jar is not supported at the moment. You always need to put those dependencies as separate jars on classpath or modulepath (preferably). That's why exec:java works, but running the packaged jar doesn't.

    Edit: this improved in the next version (23.1.2). See https://github.com/graalvm/polyglot-embedding-demo/blob/main/pom.xml#L360