JavaFX 11: создайте файл JAR с Gradle - PullRequest
       48

JavaFX 11: создайте файл JAR с Gradle

0 голосов
/ 29 сентября 2018

Я пытаюсь обновить проект JavaFX с версии 8 Java до версии 11.Это работает, когда я использую задачу «Выполнить» Gradle ( Я следовал учебному руководству Openjfx ), но когда я собираю (с помощью задачи «jar» Gradle) и выполняю (с «java -jar») jarфайл, появляется сообщение «Ошибка: отсутствуют компоненты среды выполнения JavaFX, которые необходимы для запуска этого приложения».

Вот мой файл build.gradle:

group 'Project'
version '1.0'
apply plugin: 'java'
sourceCompatibility = 1.11

repositories {
    mavenCentral()
}

def currentOS = org.gradle.internal.os.OperatingSystem.current()
def platform
if (currentOS.isWindows()) {
    platform = 'win'
} else if (currentOS.isLinux()) {
    platform = 'linux'
} else if (currentOS.isMacOsX()) {
    platform = 'mac'
}
dependencies {
    compile "org.openjfx:javafx-base:11:${platform}"
    compile "org.openjfx:javafx-graphics:11:${platform}"
    compile "org.openjfx:javafx-controls:11:${platform}"
    compile "org.openjfx:javafx-fxml:11:${platform}"
}

task run(type: JavaExec) {
    classpath sourceSets.main.runtimeClasspath
    main = "project.Main"
}

jar {
    manifest {
        attributes 'Main-Class': 'project.Main'
    }
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

compileJava {
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.controls,javafx.fxml'
        ]
    }
}

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

Знаете ли вы, чтоЯ должен сделать?

Ответы [ 2 ]

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

Если кому-то интересно, я нашел способ создания jar-файлов для проекта JavaFX11 (с модулями Java 9).Я тестировал его только на Windows (если приложение также для Linux, я думаю, что мы должны сделать те же шаги, но на Linux, чтобы получить jar JavaFX для Linux).

У меня есть модуль "Project.main" (созданный IDEA при создании проекта Gradle):

 src
 +-- main
 |   +-- java
     |   +-- main
         |   +-- Main.java (from the "main" package, extends Application)
     |   +-- module-info.java
 build.gradle
 settings.gradle
 ...

Файл module-info.java:

module Project.main {
    requires javafx.controls;
    exports main;
}

Файл build.gradle:

plugins {
    id 'java'
}

group 'Project'
version '1.0'
ext.moduleName = 'Project.main'
sourceCompatibility = 1.11

repositories {
    mavenCentral()
}

def currentOS = org.gradle.internal.os.OperatingSystem.current()
def platform
if (currentOS.isWindows()) {
    platform = 'win'
} else if (currentOS.isLinux()) {
    platform = 'linux'
} else if (currentOS.isMacOsX()) {
    platform = 'mac'
}
dependencies {
    compile "org.openjfx:javafx-base:11:${platform}"
    compile "org.openjfx:javafx-graphics:11:${platform}"
    compile "org.openjfx:javafx-controls:11:${platform}"
}

task run(type: JavaExec) {
    classpath sourceSets.main.runtimeClasspath
    main = "main.Main"
}

jar {
    inputs.property("moduleName", moduleName)
    manifest {
        attributes('Automatic-Module-Name': moduleName)
    }
}

compileJava {
    inputs.property("moduleName", moduleName)
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.controls'
        ]
        classpath = files()
    }
}

task createJar(type: Copy) {
    dependsOn 'jar'
    into "$buildDir/libs"
    from configurations.runtime
}

Файл settings.gradle:

rootProject.name = 'Project'

И команды Gradle:

#Run the main class
gradle run

#Create the jars files (including the JavaFX jars) in the "build/libs" folder
gradle createJar

#Run the jar file
cd build/libs
java --module-path "." --module "Project.main/main.Main"
0 голосов
/ 29 сентября 2018

В Java / JavaFX 11 теневая / жирная банка не будет работать.

Как вы можете прочитать здесь :

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

Optional<Module> om = ModuleLayer.boot().findModule(JAVAFX_GRAPHICS_MODULE_NAME);

Если этот модуль отсутствует, запускпрерваноСледовательно, в этом случае использование библиотек JavaFX в качестве jar-файлов на пути к классам недопустимо.

Более того, каждый jar-файл JavaFX 11 имеет файл module-info.class на корневом уровне.

Когда вы объединяете все содержимое банок в одну толстую банку, что происходит с этими файлами с одинаковым именем и одинаковым расположением?Даже если толстый кувшин хранит их все, как он идентифицируется как один модуль?

Есть запрос на поддержку, но он еще не решен: http://openjdk.java.net/projects/jigsaw/spec/issues/#MultiModuleExecutableJARs

Предоставляет средство для создания исполняемого модульного «uber-JAR», который содержит более одного модуля, сохраняя идентификаторы и границы модулей, так что все приложение может быть доставлено как один артефакт.

Плагин тени все еще имеет смысл объединить все ваши другие зависимости в одну банку, но в конце концов вам придется запустить что-то вроде:

java --module-path <path-to>/javafx-sdk-11/lib \
   --add modules=javafx.controls -jar my-project-ALL-1.0-SNAPSHOT.jar

Это означает, что послевсе, вам придется установить JavaFX SDK (для каждой платформы), чтобы запустить тот jar-файл, который использовал зависимости JavaFX от maven central.

В качестве альтернативы вы можете попробовать использовать jlink для создания облегченной JRE,но ваше приложение должно быть модульным.

Также вы можете использовать Javapackager для генерации установщика для каждой платформы.См. http://openjdk.java.net/jeps/343, который создаст упаковщик для Java 12.

Наконец, есть экспериментальная версия Javapackager, которая работает с Java 11 / JavaFX 11: http://mail.openjdk.java.net/pipermail/openjfx-dev/2018-September/022500.html

EDIT

Поскольку средство запуска Java проверяет, расширяет ли основной класс javafx.application.Application, и в этом случае требуется, чтобы среда выполнения JavaFX была доступна в виде модулей (а не в виде jars), возможноЧтобы обойти это, нужно добавить новый Main класс, который будет основным классом вашего проекта, и этот класс будет вызывать ваш класс JavaFX Application.

Еслиу вас есть пакет javafx11 с классом приложения:

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(new StackPane(l), 400, 300);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

Затем вам нужно добавить этот класс в этот пакет:

public class Main {

    public static void main(String[] args) {
        HelloFX.main(args);
    }
}

И в вашем файле сборки:

mainClassName='javafx11.Main'
jar {
    manifest {
        attributes 'Main-Class': 'javafx11.Main'
    }
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

Теперь вы можете запустить:

./gradlew run

или

./gradlew jar
java -jar build/libs/javafx11-1.0-SNAPSHOT.jar

JavaFX from FAT jar

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

...