java.lang.NoClassDefFoundError: io / реактив / объекты / субъект при создании jar в Intellij Idea (gradle + JavaFX 11) - PullRequest
0 голосов
/ 22 января 2019

Я запускаю какое-то приложение с JavaFX 11 (OpenFX). Приложение написано в IntellijIdea и построено с Gradle. При запуске в IDE все ок. При сборке jar он собирается успешно, но когда я пытаюсь его выполнить, я получаю сообщение об ошибке:

Exception in thread "main" java.lang.NoClassDefFoundError: io/reactivex/subjects/Subject

Для создания банки я использую плагин onslip.gradle-one-jar. Мой gradle следующий:

plugins {
   id 'application'
   id 'org.openjfx.javafxplugin' version '0.0.5'
   id 'com.github.onslip.gradle-one-jar' version '1.0.5'
}

repositories {
   mavenCentral()
}

dependencies {
   implementation "org.openjfx:javafx-base:11:win"
   implementation "org.openjfx:javafx-graphics:11:win"
   implementation "org.openjfx:javafx-controls:11:win"
   implementation "org.openjfx:javafx-fxml:11:win"
   implementation 'com.jfoenix:jfoenix:9.0.8' 
   implementation group: 'commons-validator', name: 'commons-validator', version: '1.6' 
   implementation group: 'commons-io', name: 'commons-io', version: '2.6' 
   implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.141.59' 
   implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1' 
   implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2' 
   implementation group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.2.5' 
   testImplementation group: 'junit', name: 'junit', version: '4.12'
}

javafx {
   modules = [ 'javafx.controls', 'javafx.fxml' ]
}

mainClassName = 'jetliner.Main'

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

task awesomeFunJar(type: OneJar) {
    mainClass = 'jetliner.Main'
}

Для создания банки я запускаю задание awesomeFunJar.

1 Ответ

0 голосов
/ 22 января 2019

Основная проблема в вашей сборке связана с тем, как вы определяете зависимости с помощью implementation (больше не compile), в то время как, с другой стороны, вы создаете свой jar на основе configurations.compile.

Поскольку implementation и compile не совпадают, configurations.compile содержит только классы вашего проекта, а не сторонние зависимости (включая JavaFX).

При запуске задачи сборки будет сгенерированочень маленькая толстая банка 3 кб.Очевидно, что этот jar пропускает все классы из зависимостей.

Решение

Замените в своем задании jar configurations.compile на configurations.compileClasspath:

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

Запустите ./gradlew build, чтобы сгенерировать толстый jar (около 23 МБ с заданными зависимостями), который можно запустить с помощью:

java -jar build/libs/myproject.jar

Или запустить ./gradlew awesomeFunJar, чтобы получить аналогичный толстый jar (21 МБ), который работает с:

java -jar build/libs/myproject-standalone.jar

В обоих случаях включены зависимости io.reactivex.rxjava2.

Примечание 1 : я не использовал этот gradle-плагин one-jar раньше, и я не вижу какого-либо существенного преимущества в наличии пользовательского загрузчика, все, что я вижу, это то, что для образца helloFX его загрузка занимает слишком много времени по сравнению с обычным толстым jar.

Если вы используете его, потому что толстая банка не работает, возможно, вам нужен класс Launcher, как объяснено здесь :

public class Launcher {
    public static void main(String[] args) {
        Main.main(args);
    }
}

, а затем заменитеmainClass с jetliner.Launcher.

Примечание 2 : Плагин JavaFX (последняя версия 0.0.7) использует implementation, и он заботится о добавлении зависимостей JavaFX, так что вы можетеупростить файл сборки:

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.7'
    id 'com.github.onslip.gradle-one-jar' version '1.0.5'
}

repositories {
    jcenter()
}

dependencies {
    implementation 'com.jfoenix:jfoenix:9.0.8'
    implementation group: 'commons-validator', name: 'commons-validator', version: '1.6'
    implementation group: 'commons-io', name: 'commons-io', version: '2.6'
    implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.141.59'
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'
    implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
    implementation group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.2.5'
    testImplementation group: 'junit', name: 'junit', version: '4.12'
}

javafx {
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

mainClassName = 'jetliner.Launcher'

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

task awesomeFunJar(type: OneJar) {
    mainClass = 'jetliner.Main'
}
...