karel booshoofd
karel booshoofd

Reputation: 43

JavaFX 21 NoClassDefFoundError in Maven Multi-Module Project

I have a Non-Modular JavaFX 21 application using OpenJFX, organized into two Maven modules:

  1. UI

  2. Core

When running the application directly through IntelliJ's Application run configuration, everything works fine. However, when using the javafx-maven-plugin to build and run the application, I encounter a NoClassDefFoundError for javax.transaction.TransactionManager. This class is a nested dependency, provided by another dependency.

To temporarily resolve this, I added an explicit dependency on javax.transaction, which fixed the initial error. However, I now get a new NoClassDefFoundError for a class from a proprietary library (used by our company) that the Core module depends on. This class is not a nested dependency and is explicitly declared in the pom.xml of the Core module.

Note that i don't have any problems with loading any JavaFX classes

Project Structure:

The javafx-maven-plugin is configured in the pom.xml of the UI module, and the UI module has a dependency on the Core module.

<plugin>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-maven-plugin</artifactId>
    <version>0.0.8</version>
    <configuration>
        <mainClass>foo.bar.view.fx.Main</mainClass>
        <commandLineArgs>${programArgs}</commandLineArgs>
        <options>
            <option>jvm arg 1</option>
            <option>jvm arg 2</option>
        </options>
        <!--       THIS DIDN't WORK <runtimePathOption>CLASSPATH</runtimePathOption>-->
    </configuration>

What could be the issue here?

With the javafx-maven-plugin i would expect it to work the same if not better as with the intellij run configuration. I can't find any similar issues online. I only people having issues with JavaFX classes not being found.

Upvotes: 2

Views: 124

Answers (1)

jewelsea
jewelsea

Reputation: 159566

I was unable to replicate your issue.

Example Project

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>17</java.version>
    </properties>

    <modules>
        <module>core</module>
        <module>ui</module>
    </modules>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

core/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.example</groupId>
        <artifactId>parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>core</artifactId>

    <dependencies>
        <dependency>
            <groupId>jakarta.transaction</groupId>
            <artifactId>jakarta.transaction-api</artifactId>
            <version>2.0.1</version>
        </dependency>
    </dependencies>
</project>

ui/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>ui</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>core</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>17.0.12</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.8</version>
                <executions>
                    <execution>
                        <id>default-cli</id>
                        <configuration>
                            <mainClass>org.example.ui.FXApp</mainClass>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

ui/src/main/java/org/example/ui/FXApp.java

package org.example.ui;

import jakarta.transaction.TransactionManager;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;

public class FXApp extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        String transactionInfo = "Transaction Manager: " + TransactionManager.class;
        stage.setScene(
                new Scene(
                        new Label(
                                transactionInfo
                        )
                )
        );
        stage.show();
    }
}

Build

Command:

mvn install

Output:

[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for parent 1.0-SNAPSHOT:
[INFO] 
[INFO] parent ............................................. SUCCESS [  0.234 s]
[INFO] core ............................................... SUCCESS [  0.809 s]
[INFO] ui ................................................. SUCCESS [  0.815 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

Execution

Command:

mvn -f ui javafx:run

Output:

output

Notes

I added a dependency in the core project to the jakarta transaction manager rather than the javax transaction manager as the javax transaction manager is obsolete.

If you are going to the effort to upgrade from Oracle JDK 8, I would recommend as a minimum using the latest LTS JDK/JavaFX releases (21) rather than 17. Newer JavaFX releases will not support Java 17.

Upvotes: 0

Related Questions