3

I am trying to build a JavaFX application using Spring Boot and deploy it with jpackage.

When using the javafx-maven-plugin javafx:run command, I can see project launching. But after building it to an *.msi installer, installing and launching the *.exe, nothing happens (whether by double-click or command line run).

How can I fix this, or at least know what is happening? I suspect the javafx:run goal to have some parameter that is missing from the manual jlink, however I can't use javafx:jlink as the application itself is not a module, because Spring Boot is not modularized yet.

Here are the sources;

EDIT: On @Slaw's suggestion, I modified the jpackage command to include `--win-console. Which successfully runs the app. Although a great step, that is not what I'm looking for, I would like to run it without having a prompt beside it.

pom.xml:

<?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>org.test</groupId>
    <artifactId>mytest</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.6.0</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.6.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>17.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-graphics</artifactId>
            <version>17.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>17.0.1</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.6.0</version>
            </plugin>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.8</version>
                <configuration>
                    <mainClass>org.test.Main</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>install</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Main:

package org.test;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class Main extends Application {
    private ConfigurableApplicationContext springContext;
    private Parent rootNode = new AnchorPane();
    public static void main(String[] args) {
        Application.launch(args);
    }
    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(rootNode, 700, 700));
        stage.setMinWidth(700);
        stage.setMinHeight(700);
        stage.show();
    }
    public void init() throws  Exception{
        springContext = SpringApplication.run(Main.class);
    }
    public void stop() throws Exception{
        springContext.close();
    }
}

And my build script is:

@ECHO OFF
SETLOCAL
call mvn clean install
set manual_modules=,javafx.controls,javafx.graphics,javafx.fxml
for /f %%i in ('jdeps --multi-release 17 --ignore-missing-deps --print-module-deps --class-path "target/lib/*" target/classes/org/test/Main.class') do set detected_modules=%%i
echo jlink
jlink --no-header-files --no-man-pages --compress=2 --strip-debug --module-path "target/lib" --add-modules %detected_modules%%manual_modules% --output target/java-runtime
echo jpackage
jpackage --type msi --dest target/installer --input target --name mytest --main-class org.test.Main --main-jar mytest-1.0.jar --runtime-image target/java-runtime
endlocal
@ECHO ON
3
  • 1
    I don't know if it will help, but you can try packaging --win-console and then running the *.exe from the console (may need to tell your console to wait and not create a new window, not sure), and hopefully a stack trace will be emitted showing you what's wrong. Commented Nov 27, 2021 at 19:58
  • @Slaw Sooo ..I tried your method and hoped for a stack trace. Unexpectedly, I did not get an error. The app ran & launched successfully. It looks like running it in a console makes it work. However that is not really a great UX. I will update the question Commented Nov 27, 2021 at 20:24
  • 1
    Interesting. I'm sorry, but I don't have a guess as to why that could happen, at least not at the moment. Commented Nov 27, 2021 at 20:42

1 Answer 1

6

I have no explanation as though why the first jpackage command works with --win-console and not without. Something I do not understand must be happening under the hood (I'm still interested in that answer if anyone knows!).

Anyways, I managed to produce an exe after some debugging and many attempts.

  1. Launching the application via the Spring Boot Loader, meaning the jpackage command is now: jpackage --type msi --dest output/installer --input target --name testing --main-class org.springframework.boot.loader.PropertiesLauncher --main-jar mytest-1.0.jar --runtime-image target/java-runtime
  2. Add spring boot loader dependency in pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-loader</artifactId>
    <version>2.6.0</version>
</dependency>
  1. Modify the spring-boot-maven-plugin configuration:
           <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.6.0</version>
                <configuration>
                    <mainClass>org.test.Main</mainClass>
                    <layout>ZIP</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

I admit what I'm doing here is quite experimental (at least to me), all answers that could provide a more in-depth look, references or a better way would be welcomed.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.