Подтвердить что ты не робот

Как экспортировать исполняемую банку в gradle, и эта банка может запускаться, так как она включает в себя справочные библиотеки

как экспортировать исполняемую банку в gradle, и эта банка может запускаться, поскольку она включает в себя справочные библиотеки.

build.gradle

apply plugin: 'java'

manifest.mainAttributes("Main-Class" : "com.botwave.analysis.LogAnalyzer")

repositories {
    mavenCentral()
}

dependencies {
    compile (
        'commons-codec:commons-codec:1.6',
        'commons-logging:commons-logging:1.1.1',
        'org.apache.httpcomponents:httpclient:4.2.1',
        'org.apache.httpcomponents:httpclient:4.2.1',
        'org.apache.httpcomponents:httpcore:4.2.1',
        'org.apache.httpcomponents:httpmime:4.2.1',
        'ch.qos.logback:logback-classic:1.0.6',
        'ch.qos.logback:logback-core:1.0.6',
        'org.slf4j:slf4j-api:1.6.0',
        'junit:junit:4.+'
    )
}

после запуска i: gradle build

он создает папку сборки, и я запускаю jar в файле build/libs/XXX.jar:

java -jar build/libs/XXX.jar

вот исполнение:

Exception in thread "main" java.lang.NoClassDefFoundError: ch/qos/logback/core/joran/spi/JoranException

как я могу запустить его с помощью библиотек ссылок?

4b9b3361

Ответ 2

Надеюсь, это поможет кому-то (поскольку, к сожалению, я потратил некоторое время на поиск решения). Вот решение, которое работало для меня для создания исполняемого JAR. Я внедряю Jetty в основной метод, Jetty 9, чтобы быть конкретным и использовать Gradle 2.1.

Включите следующий код в свой файл build.gradle(если подпроект является "основным" проектом, из которого необходимо построить банку, а затем добавьте его в подпроект, который должен начинаться как этот проект (':') { вставьте код где-то здесь, после зависимостей.}.

Кроме того, вам нужно добавить плагин java для этого: apply plugin: 'java'.

Моя задача jar выглядит следующим образом:

apply plugin: 'java'

jar {

    archiveName = "yourjar.jar"

    from {

        configurations.runtime.collect {
            it.isDirectory() ? it : zipTree(it)
        }

        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }

    manifest {
        attributes 'Main-Class': 'your.package.name.Mainclassname'
    }

    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}

И затем вы можете выполнить свой yourjar.jar через командную строку:

java -jar yourjar.jar

Для этого необходимо исключить DSA META-INF/.RSA, META-INF/.SF и META-INF/*. В противном случае возникает исключение SecurityException.

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

JAR, от которых зависит проект, определяются в зависимостях следующим образом:

dependencies {

    // add the subprojects / modules that this depends on
    compile project(':subproject-1')
    compile project(':subproject-2')

    compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.2.6.v20141205'
    compile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.2.6.v20141205'
    compile group: 'org.eclipse.jetty', name: 'jetty-http', version: '9.2.6.v20141205'

}

EDIT: прежде чем вместо

configurations.runtime.collect{...}

Я имел

configurations.runtime.asFileTree.files.collect{...}

Это вызвало странное поведение в более крупном проекте в чистой сборке. При запуске jar после выполнения Gradle чистой сборки в первый раз (после ручной очистки каталога сборки) он выкинет NoClassDefFoundException (в нашем проекте со многими подпроектами), но запустил jar после выполнения Gradle clean build a второй раз (без опустошения каталога сборки вручную), по какой-то причине он имел все зависимости. Этого не произошло, если asFileTree.files был исключен.

Также я должен отметить, что все компиляционные зависимости включены во время выполнения, однако не все время исполнения включено в компиляцию. Поэтому, если вы просто используете компиляцию

        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }

Затем обязательно помните, что если возникает NoClassDefFoundException, некоторый класс не найден во время выполнения, что означает, что вы также должны включить это:

        configurations.runtime.collect {
            it.isDirectory() ? it : zipTree(it)
        }

Ответ 3

Быстрый ответ

  • Добавьте в свой build.gradle следующее:

    apply plugin: 'application'
    
    mainClassName = 'org.example.app.MainClass'
    
    jar {
        manifest {
            attributes 'Main-Class': mainClassName,
                       'Class-Path': configurations.runtime.files.collect {"$it.name"}.join(' ')
        }
    }
    
  • В каталоге проекта запустите gradle installDist
  • Запустить java -jar build/install/<appname>/lib/<appname>.jar

Я рекомендую добавить версию приложения к вашему build.gradle, но это не требуется. Если вы это сделаете, имя встроенного баннера будет <appname>-<version>.jar.

Примечание. Я использую gradle 2.5


Подробнее

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

java -jar appname.jar

вам понадобится:

  • ваша банка должна включать файл MANIFEST, указывающий на основной класс приложения
  • все ваши зависимости (классы из банок за пределами вашего приложения) должны быть включены или доступны как-то
  • ваш файл MANIFEST для включения правильного пути к классам

Как показывают некоторые другие ответы, вы можете использовать сторонний плагин для достижения этого, например shadow или one-jar.

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

Другим вариантом было бы использовать gradle плагин приложения, как указано выше. Запуск gradle build будет создавать банку для вас и красиво связывать ее со всеми вашими зависимостями в файле zip/tar. Вы также можете запустить gradle installDist, чтобы пропустить zipping.

Однако, поскольку @jeremyjjbrown написал в комментарии там, плагин не создает сам исполняемый банку. Он создает банку и script, который создает путь к классам и выполняет команду для запуска основного класса вашего приложения. Вы не сможете запустить java -jar appname.jar.

Чтобы получить лучшее из обоих миров, выполните описанные выше шаги, которые создают вашу банку вместе со всеми вашими зависимостями в виде отдельных банок и добавьте правильные значения в ваш MANIEST.

Ответ 4

Я проверил довольно некоторые ссылки для решения, наконец, сделал следующие шаги, чтобы заставить его работать. Я использую Gradle 2.9.

Внесите следующие изменения в файл сборки: gradle:

1. Указать плагин:

apply plugin: 'eu.appsatori.fatjar'

2. Предоставьте Buildscript:

buildscript {
  repositories {
    jcenter()
   }

dependencies {
  classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
  }
}

3. Предоставить основной класс:

fatJar {
  classifier 'fat'
  manifest {
     attributes 'Main-Class': 'my.project.core.MyMainClass'
  }
  exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF'
}

4. Создайте жир:

./gradlew clean fatjar

5. Запустите fatjar из /build/libs/:

java -jar MyFatJar.jar

Ответ 5

Все эти ответы либо ошибочны, либо устарели.

ОП просит о том, что известно как "жирная банка". Это сложная банка, которая содержит все зависимости, чтобы она не требовала внешних зависимостей для запуска (за исключением JRE, конечно!).

Ответ на момент написания - это плагин Gradle Shadow Jar, хорошо понятный в Руководство пользователя и примеры теневого плагина.

Потому что я невежественный человек, но я все же немного боролся. Более конкретно, я использовал Gradle в течение нескольких месяцев, как это "окно волшебных трюков". Половина времени я действительно не знаю, что он делает слишком хорошо, или как он это делает (не в большой степени заинтересован в том, чтобы попасть в Groovy язык в настоящее время). Просто знайте, что он работает, чтобы выполнить тестирование и запуск файлов, которые я хочу сделать.

Сделайте так:

поместите все эти строки где-нибудь в файл build.gradle(я положил их вверху):

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.4' 
    }
}
apply plugin: 'com.github.johnrengelman.shadow'
shadowJar {
    baseName = 'shadow'
    classifier = null
    version = null
}
jar {
    manifest {
        attributes 'Class-Path': '/libs/a.jar'
        attributes 'Main-Class': 'core.MyClassContainingMainMethod'
    }
}

PS не беспокойтесь о каких-либо других строках "репозиториев", "зависимостей" или "плагинов" в другом месте вашего файла сборки, а do оставить строки таким образом внутри этого блока "buildscript" (I не знаю, зачем вам это нужно).

PPS Руководство пользователя и примеры плагинов плагинов хорошо написано, но не говорит вам для включения строки

attributes 'Main-Class': 'core.MyClassContainingMainMethod'

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

Когда вы переходите

> gradle shadowjar

Gradle, мы надеемся, создадим жирный исполняемый jar под /build/libs (имя по умолчанию "shadow.jar" ), которое вы можете запустить, выполнив это:

> java -jar shadow.jar