Home > Software engineering >  Maven javafx:jlink. How to specifiy the module-path used?
Maven javafx:jlink. How to specifiy the module-path used?

Time:12-07

I'm currently working on a modular JavaFX application and I'm using maven to compile/deploy it.

One of the dependencies of my application is JBibTex which doesn't have a module-info file so it's used as an automodule. In order for my javafx:jlink to work (because javafx:jlink cannot work on automodules), I had to convert JBibTex to an explicit module. I used the maven's ModiTect plugin for that.

I used ModiTect to generate the module-info file for the JBibTex library and I added it to the JBibTex's jar file (I used moditect:add-module-infos for that).

Now the problem is that javafx:jlink uses the JBibTex.jar file that is located in my ".m2" folder (where maven automatically downloads all your projects' dependencies). The JBibTex.jar file located in my .m2 folder is not the file to which I added the module-info file.

So I still get the error:

Error: automatic module cannot be used with jlink: jbibtex

The explicit JBibtex module that I have generated through the use of ModiTect is automatically put in target/modules by my ModiTect plugin configuration.

How can I get javafx:jlink to use the target/modules/JBibTex.jar file that contains the module-info.class file and not the JBibTex.jar of my .m2 folder?

Here is my pom.xml just in case:

<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>xxx</groupId>
    <artifactId>BRM</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>BRM</name>
    <url>http://maven.apache.org</url>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>15</maven.compiler.source>
        <maven.compiler.target>15</maven.compiler.target>
        
        <mainClass>xxx.App</mainClass>
        <moduleName>xxx.brm</moduleName>
        
        <javafx.version>17.0.1</javafx.version>
        <javafx.maven.plugin.version>0.0.8</javafx.maven.plugin.version>
    </properties>
    

    <dependencies>
        <!-- javafx dependencies -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
          <version>${javafx.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
          <version>${javafx.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.jbibtex/jbibtex -->
        <dependency>
            <groupId>org.jbibtex</groupId>
            <artifactId>jbibtex</artifactId>
            <version>1.0.17</version>
        </dependency>
    </dependencies>

    <build>
         <resources>
            <resource>
                <directory>configs</directory>
            </resource>
        </resources>
        
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
            </plugin>
            
            <plugin>
                <groupId>org.moditect</groupId>
                <artifactId>moditect-maven-plugin</artifactId>
            </plugin>
        </plugins>
        
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>15</source>
                        <target>15</target>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.openjfx</groupId>
                    <artifactId>javafx-maven-plugin</artifactId>
                    <version>${javafx.maven.plugin.version}</version>
                    <configuration>
                            <mainClass>${mainClass}</mainClass>
                            <launcher>launcher</launcher>
                            <jlinkImageName>BRM</jlinkImageName>
                    </configuration>
                </plugin>
                
                <plugin>
                    <groupId>org.moditect</groupId>
                    <artifactId>moditect-maven-plugin</artifactId>
                    <version>1.0.0.RC2</version>
                    <executions>
                        <execution>
                            <id>add-module-infos</id>
                            <phase>generate-resources</phase>
                            <goals>
                                <goal>add-module-info</goal>
                            </goals>
                            <configuration>
                                <overwriteExistingFiles>true</overwriteExistingFiles>
                                <outputDirectory>${project.build.directory}/modules</outputDirectory>
                                <modules>
                                    <module>
                                        <artifact>
                                            <groupId>org.jbibtex</groupId>
                                            <artifactId>jbibtex</artifactId>
                                            <version>1.0.17</version>
                                        </artifact>
                                        <moduleInfoSource>
                                            module jbibtex 
                                            {
                                                exports org.jbibtex;
                                            }
                                        </moduleInfoSource>
                                    </module>
                                </modules>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

CodePudding user response:

Specifically to answer your question:

How to specify the module-path used?

You could run jlink from the command-line instead of via Maven.

That way you can specify any module path you wish.

From the man page for jlink:

jlink [options] --module-path modulepath --add-modules module [, module...]

modulepath

The path where the jlink tool discovers observable modules. These modules can be modular JAR files, JMOD files, or exploded modules.

module

The names of the modules to add to the runtime image. The jlink tool adds these modules and their transitive dependencies.

If you wish to continue using the openjfx maven plugin jlink command, you can do that.

The code which configures the module path passed to jlink by the maven plugin is in git.

if (modulepathElements != null && !modulepathElements.isEmpty()) {
    commandArguments.add(" --module-path");
    String modulePath = StringUtils.join(modulepathElements.iterator(), File.pathSeparator);
    if (jmodsPath != null && ! jmodsPath.isEmpty()) {
        getLog().debug("Including jmods from local path: "   jmodsPath);
        modulePath = jmodsPath   File.pathSeparator   modulePath;
    }
    commandArguments.add(modulePath);

    commandArguments.add(" --add-modules");
    if (moduleDescriptor != null) {
        commandArguments.add(" "   moduleDescriptor.name());
    } else {
        throw new MojoExecutionException("jlink requires a module descriptor");
    }
}

This is based on the javafx:jlink options:

jmodsPath: When using a local JavaFX SDK, sets the path to the local JavaFX jmods

So if you put your module on the path specified by that option, it should be found.


Here are some other options.

Package your app as a non-modular app using jpackage

I think mipa's suggestion of using JPackageScriptFX is probably the best approach:

  • github.com/dlemmermann/JPackageScriptFX

Create a new jar from binaries

  1. Unjar the JBibTex.jar.
  2. Add in the compiled module-info to unjared directory.
  3. Create a new jar, e.g. JBibTexModule.jar.
  4. Install that to your maven repository via a mvn install command.
  5. Add a maven dependency on JBibTexModule instead of JBibTex.
  6. Add any needed statements to your main app module-info file to use the library.

Then, I believe you are done, and it would build, link, and run ok.

Create a new jar from source

The jbibtex library is also in github, so you could create an issue or pull-request on the project to ask it to be modularized.

Also, you could:

  1. Clone the repository.
  2. Add the module-info.java.
  3. Build the jar file.
  4. Install it locally in your local maven repository.
  5. Then depend on the local version you have created.
  • Related