Различное поведение между Maven и Eclipse при запуске приложения JavaFX 11 - PullRequest
0 голосов
/ 10 октября 2018

Я начинаю углубляться в миграцию Java 11 для большого приложения (включая части Java FX), и мне нужна ваша помощь, чтобы понять разницу между Maven (3.5.4) в командной строке и Eclipse (2018-09с обновлением Java11).

У меня есть простой класс Java 11

import java.util.stream.Stream;

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

public class HelloFX extends Application {

    @Override
    public void start(Stage stage) {
        String javaVersion = System.getProperty("java.version");
        String javafxVersion = System.getProperty("javafx.version");
        Label l = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");
        Scene scene = new Scene(l, 640, 480);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        Stream.of("jdk.module.path",
                "jdk.module.upgrade.path",
                "jdk.module.main",
                "jdk.module.main.class").forEach(key -> System.out.println(key + " : " + System.getProperty(key)));

        Application.launch();
    }

}

и простой pom

<project 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.gluonhq</groupId>
    <artifactId>hellofx</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>11</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <release>11</release>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>HelloFX</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Когда я запускаю 'mvn compile exec: java'Я думаю, что ничего не использует новый путь к модулю, и программа отображает панель JavaFX, как и ожидалось.Выход системы:

jdk.module.path: null

jdk.module.upgrade.path: null

jdk.module.main: null

jdk.module.main.class: null

При запуске из средства запуска Eclipse я должен добавить в средство запуска следующие аргументы vm:

- module-path = $ {env_var: JAVAFX_PATH} --add-modules = javafx.controls

и панель также отображается, но вывод:

jdk.module.path: C: \ dev \ tools \ javafx-sdk-11 \ lib

jdk.module.upgrade.path: null

jdk.module.main: null

jdk.module.main.class: null

jdk.module.main.class: null

Я не могу заставить его работать в Eclipse, так как он работает изкомандная строка: я вынужден связываться с модулями и путь к модулю.Если я не добавляю параметры vm, я получаю либо «Ошибка: отсутствуют компоненты среды выполнения JavaFX, которые необходимы для запуска этого приложения», либо «Ошибка произошла во время инициализации загрузочного слоя java.lang.module.FindException: Модуль javafx.controlsnot found ".

Как это работает из командной строки без какой-либо дополнительной настройки?Насколько мне известно, Maven не добавляет ничего автоматически в путь модуля ...

Есть идеи?Чего мне не хватает?

Обновление 1: я понял, что при импорте проекта в Eclipse «как проект Maven» (что я всегда делаю) это приводит к добавлению JRE в путь к модулю (который не являетсядело для моих классных проектов).Смотрите скриншот enter image description here

1 Ответ

0 голосов
/ 10 октября 2018

При запуске из командной строки, если вы выбираете систему сборки Maven (то же самое работает для Gradle), вы позволяете плагинам делать всю работу за вас.

Когда вы запускаете из своей IDE основной класс,но не из встроенных окон Maven / Gradle, напротив, вы запускаете простые параметры командной строки java.

И это приводит к двум разным вещам (но, конечно, с одинаковым конечным результатом), как вы уже выяснили через распечатку свойств.

Как уже указано в этом ответе для IntelliJ, но применимо к любой другой IDE или этой другой one для Eclipse существует два способа запуска проекта JavaFX 11, основанные на использовании или не использовании системы сборки Maven / Gradle.

проект JavaFX, без инструментов сборки

Чтобы запустить проект JavaFX из среды IDE, необходимо загрузить JavaFX SDK и добавить библиотекус различными javafx jar для вашей IDE, с путем, подобным /Users/<user>/Downloads/javafx-sdk-11/lib/.

Теперь, чтобы запустить этот проект, даже если он не является модульным, вы должны добавить путь к этим модулям и включитьмодули, которые вы используете для параметров / аргументов виртуальной машины проекта.

Запускаете ли вы проект из IDE или из командной строки, вы будете запускать что-то вроде:

java --module-path /Users/<user>/Downloads/javafx-sdk-11/lib/ \
    --add-modules=javafx.controls org.openjfx.hellofx.HelloFX

Обратите внимание, что даже если ваш проект не является модульным, вы все равно используетеМодули JavaFX, и поскольку вы не используете какой-либо инструмент для сборки, вам необходимо позаботиться о загрузке SDK.

Проект JavaFX, инструменты сборки

Если вы используете инструменты сборки Maven или Gradle, первое основное отличие заключается в том, что вам не нужно загружать JavaFX SDK.Вы включите в свой pom (или файл build.gradle), какие модули вам нужны, и Maven / Gradle сможет загрузить только эти модули (и зависимости) в ваш локальный репозиторий .m2 / .gradle.

КогдаВы запускаете свой основной класс из Maven exec:java goal Вы используете плагин, и то же самое относится к задаче run в Gradle.

На данный момент, выглядит как , когдавы запускаете:

mvn compile exec:java

или

gradle run

вы не добавляете вышеупомянутые аргументы VM, но факт в том, что Maven / Gradle позаботится об этом за вас.

Gradle

В случае Gradle это более очевидно, поскольку вы должны установить их в задаче run:

run {
    doFirst {
        jvmArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'javafx.controls'
        ]
    }
}

Пока выSDK не нужен, classpath содержит путь к вашему .m2 или .gradle репозиторию, куда были загружены артефакты javafx.

Maven

Для Maven, в то время как pom управляет зависимостями различных модулей javafx и устанавливает классификатор для загрузки специфичных для платформы модулей (см., Например, /Users/<User>/.m2/repository/org/openjfx/javafx-controls/11/javafx.controls-11.pom), плагину удается настроить путь к классам и создать необходимые параметры для запуска проекта.

Короче говоря, новый класс, который не расширяется Application, используется для вызова класса вашего приложения: HelloFX.main(args).

EDIT

См. Этот ответ для более подробного объяснения того, почему не удается запустить приложение JavaFX без пути к модулю .Но вкратце:

Эта ошибка происходит от sun.launcher.LauncherHelper в модуле java.base.Причина этого заключается в том, что главное приложение расширяет приложение и имеет основной метод.Если это так, LauncherHelper проверит наличие модуля javafx.graphics в качестве именованного модуля.Если этот модуль отсутствует, запуск прерывается.

Более подробное объяснение того, как работает плагин maven без установки module-path :

Если вы добавите уровень отладки (по умолчанию это информация) при выполнении целей Maven, вы получите более подробную информацию о том, что происходит за кулисами.

Запуск mvn compile exec:java показывает:

 ...
[DEBUG]   (f) mainClass = org.openjfx.hellofx.HelloFX
 ...
[DEBUG] Invoking : org.openjfx.hellofx.HelloFX.main()
 ...

И если вы проверите исходный код exec-maven-plugin, вы можете найти в ExecJavaMojo::execute, как метод main класса Application вызывается из потока.

Thisэто именно то, что позволяет запускать класс Application из внешнего класса, который не расширяет класс Application, чтобы пропустить проверки.

Заключение

Выбор за вами - сборкаинструменты или нет, хотя в настоящее время их использование является предпочтительным вариантом, конечно.В любом случае, конечный результат будет одинаковым.

Но важно понять, в чем различия этих подходов и как ваша IDE справляется с ними.

...