2017-02-14 20 views
9

Я пишу библиотеку Java, и я хотел бы построить библиотеку с Gradle, а затем протестировать ее из локального тестового проекта.Включая библиотеку Java, построенную с помощью Gradle throws NoClassDefFoundError

Я бы предпочел использовать Gradle 3.3 для своей цели. Библиотека должна быть построена для Java5 и выше.

До сих пор мой build.gradle выглядит следующим образом:

plugins { 
    id 'jvm-component' 
    id 'java-lang' 
} 

repositories { 
    mavenCentral() 
} 

model { 
    components { 
    main(JvmLibrarySpec) { 
     sources { 
     java { 
      dependencies { 
      module 'commons-codec:commons-codec:1.10' 
      module 'org.apache.httpcomponents:httpcore:4.4.6' 
      module 'org.apache.httpcomponents:httpclient:4.5.3' 
      } 
     } 
     } 

     api { 
     exports 'io.simplepush' 
     } 

     targetPlatform 'java5' 
    } 
    } 
} 

Исходный код библиотеки находится в src/main/java/io/simplepush/Notification.java и зависит от зависимостей, указанных в файле build.gradle.

Здание библиотеки с ./gradlew build прекрасно работает и создает build/jars/main/jar/main.jar.

Однако, когда я запускаю тестовый проект с IntelliJ (после включения main.jar в тестовый проект), я получаю следующее сообщение об ошибке во время выполнения:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/HttpEntity.

Кажется, что тестовый проект не знает о зависимостях времени выполнения, необходимых моей библиотеке.

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

+0

Почему бы не добавить библиотечные тесты к самой библиотеке? –

+0

Потому что я хочу узнать о процессе включения библиотеки в проект с Gradle. – tymm

+0

Возможно, принятый ответ на этот вопрос поможет: http://stackoverflow.com/questions/24975745/gradle-dependencies-compile-project-by-relative-path – vinegarbin

ответ

2

Я решил это, изменив несколько вещей.
Благодаря @Babl для указания меня в правильном направлении.
Моя новая библиотека build.gradle выглядит следующим образом:

plugins { 
    id 'java' 
    id 'maven-publish' 
} 

sourceCompatibility = 1.5 

repositories { 
    mavenLocal() 
    mavenCentral() 
} 

dependencies { 
    compile 'commons-codec:commons-codec:1.10' 
    compile 'org.apache.httpcomponents:httpcore:4.4.6' 
    compile 'org.apache.httpcomponents:httpclient:4.5.3' 
} 

publishing { 
    publications { 
    maven(MavenPublication) { 
     groupId 'io.simplepush' 
     artifactId 'project1-sample' 
     version '1.1' 

     from components.java 
    } 
    } 
} 

Теперь я могу нажать на библиотеку в локальный репозиторий Maven с ./gradlew publishToMavenLocal.

В тестовом проекте build.gradle используется плагин application и определяется основной класс (в моем случае это Hello). Затем я могу запустить ./gradlew installDist для создания исполняемого файла (см. Application plugin docs), который ставит все зависимости в пути к классам и работает просто отлично.

group 'com.test' 
version '1.0-SNAPSHOT' 

apply plugin: 'java' 
apply plugin: 'application' 

repositories { 
    mavenLocal() 
    mavenCentral() 
} 

dependencies { 
    compile 'io.simplepush:project1-sample:1.1' 
} 

mainClassName = "Hello" 
+0

http://stackoverflow.com/help/someone-answers – LazerBanana

5

Созданный вами баннер библиотеки не содержит информации о зависимостях, которую IDE/Gradle может разрешить, чтобы иметь возможность компилировать/запускать тестовый проект. Я вижу, что вы используете центральный репозиторий maven, поэтому вам нужно опубликовать вашу библиотеку в вашем локальном репозитории maven, а в тестовом проекте просто добавьте информацию о зависимости (не просто файл jar jar).

Итак, в библиотеке и тестовом проекте build.gradle добавьте конфигурацию локального репозитория maven.

repositories { 
    mavenLocal() 
    mavenCentral() 
} 

И теперь вам нужно опубликовать библиотеку в местном репозитории. Когда вы используете град 3.3, вы можете использовать Maven Publishing.

Итак, в библиотеке build.gradle добавить информацию о публикации maven.

publishing { 
    publications { 
     maven(MavenPublication) { 
      groupId 'io.simplepush' 
      artifactId 'project1-sample' 
      version '1.1' 

      from components.java 
     } 
    } 
} 

Gradle «Maven публиковать» плагин делает это легко опубликовать в локальное хранилище автоматически создавая PublishToMavenLocal задачи. Таким образом, вы можете просто запустить

gradle publishToMavenLocal

Что опубликует вашу библиотеку со всей информацией зависимостей в локальный репозиторий Maven.

И тогда вам просто нужно добавить библиотеку информации для вас тестовых проектов build.gradle

dependencies { 
     // other dependencies ..... 
     module 'io.simplepush:project1-sample:1.1' 
} 
+0

Спасибо. Это направление, которое я хочу принять. После некоторой дополнительной модификации (удаление всей секции модели, определение зависимостей с 'compile' на первом уровне файла' build.gradle' и загрузка java-плагина), похоже, создает локальную библиотеку maven, которая правильно определяет ее зависимости в его файл pom. Однако я все равно получаю ту же ошибку. Не могли бы вы объяснить, как правильно генерировать исполняемую банку с градиентом для тестового проекта? – tymm

0

Это указание, что репозиториев для проверки, чтобы принести зависимости от

repositories { 
    mavenCentral() 
} 

Таким образом, все, что находится в dependecies{} будет извлечен из приведенных выше.

Если тестовый проект не связан с проектом библиотеки (пример @RaGe), новый тестовый проект должен знать, где взять зависимость, - вам нужно его опубликовать, используя предпочтительный метод.

После этого ваш новый тестовый проект необходимо указать библиотеку с предпочтительной конфигурацией (компилировать ... среда и т.д.) в build.gradle dependencies{}

После этого в зависимости от IDE вам необходимо обновить и классам скачать зависимость от указанного до того хранилища, транзитивная зависимость, указанная в зависимости библиотеки (в данном случае) будет получить скачивается из тестовых проектов repositories{}


библиотеки build.gradle

repositories { 
    mavenCentral() 
} 

dependencies { 
    module 'commons-codec:commons-codec:1.10' 
    module 'org.apache.httpcomponents:httpcore:4.4.6' 
    module 'org.apache.httpcomponents:httpclient:4.5.3' 
} 

тестовый проект build.gradle

repositories { 
    mavenCentral() repository to fetch transitives 
    mavenLocal() or any other repo that you published the library to 
} 

dependencies { 
    pref-conf librarygroup:name:version 
} 

Вы можете использовать идею или затмить плагин в Gradle для gradle idea или gradle eclipseClasspath задач, чтобы обновить его с недавно добавленных зависимостей.

С помощью этого решения, вам не нужно упаковать транзитивные зависимости в библиотеке,

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