La inclusión de la biblioteca Java construida con Gradle arroja NoClassDefFoundError
jvm dependencies (3)
El contenedor de la biblioteca que ha creado no contiene ninguna información de dependencia que el IDE / Gradle pueda resolver para poder compilar / ejecutar el proyecto de prueba. Veo que estás usando el repositorio central de maven, así que lo que tienes que hacer es publicar tu biblioteca en tu repositorio local de maven y en el proyecto de prueba simplemente agregar una información de dependencia (no solo el archivo jar simple).
Entonces, tanto en la biblioteca como en el proyecto de prueba build.gradle
agregue una configuración de repositorio local maven.
repositories {
mavenLocal()
mavenCentral()
}
Y ahora necesita publicar la biblioteca en el repositorio local. Como está utilizando el gradle 3.3, puede usar Maven Publishing .
Por lo tanto, en la biblioteca build.gradle
agregue una información de publicación maven.
publishing {
publications {
maven(MavenPublication) {
groupId ''io.simplepush''
artifactId ''project1-sample''
version ''1.1''
from components.java
}
}
}
El plugin "maven-publish" de Gradle hace que esto sea fácil de publicar en el repositorio local creando automáticamente una tarea PublishToMavenLocal. Entonces puedes correr
gradle publishToMavenLocal
Que publicará su biblioteca con toda la información de dependencia en el repositorio maven local.
Y luego solo necesita agregar una información de la biblioteca a los proyectos de prueba build.gradle
dependencies {
// other dependencies .....
module ''io.simplepush:project1-sample:1.1''
}
Estoy escribiendo una biblioteca Java y me gustaría construir la biblioteca con Gradle y luego probarla desde un proyecto de prueba local.
Preferiría usar Gradle 3.3 para mi objetivo. La biblioteca debe estar construida para Java5 y superior.
Hasta ahora mi build.gradle
ve así:
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''
}
}
}
El código fuente de la biblioteca se encuentra en src/main/java/io/simplepush/Notification.java
y depende de las dependencias indicadas en el archivo build.gradle
.
La construcción de la biblioteca con ./gradlew build
funciona bien y genera build/jars/main/jar/main.jar
.
Sin embargo, cuando ejecuto un proyecto de prueba de IntelliJ (después de incluir main.jar
en el proyecto de prueba), main.jar
el siguiente error de tiempo de ejecución:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/HttpEntity
.
Parece que el proyecto de prueba no conoce las dependencias de tiempo de ejecución que necesita mi biblioteca.
No estoy seguro de cuál es la forma correcta de contar el proyecto de prueba sobre las dependencias de mi biblioteca. No quiero un frasco gordo que incluya todas las dependencias.
Listar todas las dependencias en el proyecto de prueba tampoco es una opción.
Preferiblemente, quiero que la biblioteca le cuente al proyecto de prueba qué dependencias necesita.
Esto especifica qué repositorios verificar para recuperar las dependencias de
repositories {
mavenCentral()
}
Por lo tanto, todo lo que está en las dependecies{}
obtendrá de los anteriores.
Si el proyecto de prueba no está acoplado con el proyecto de la biblioteca, (ejemplo de @RaGe) el nuevo proyecto de prueba necesita saber de dónde tomar la dependencia, necesita publicarla, utilizando el método preferido.
Después de eso, su nuevo proyecto de prueba necesita especificar la biblioteca con la configuración preferida (compilación ... tiempo de ejecución, etc.) en las dependencies{}
build.gradle dependencies{}
Después de eso, dependiendo de IDE, debe actualizar la ruta de clase y descargar la dependencia del repositorio antes especificado, las dependencias transitivas especificadas en la dependencia de la biblioteca (en este caso) se obtendrán de los repositories{}
proyectos de prueba repositories{}
Biblioteca 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''
}
proyecto de prueba 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
}
Puede usar el plugin idea o eclipse en gradle para gradle idea
o gradle eclipseClasspath
tasks para actualizarlo con sus dependencias recién agregadas.
Con esta solución, no debería necesitar empacar las dependencias transitivas dentro de la biblioteca,
PD. Estoy confundido después de que dijiste que querías un archivo ejecutable.
Lo solucioné cambiando varias cosas.
Gracias a @Babl por señalarme en la dirección correcta.
Mi nueva biblioteca build.gradle
ve así:
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
}
}
}
Ahora puedo enviar la biblioteca al repositorio local de maven con ./gradlew publishToMavenLocal
.
El build.gradle
del proyecto de prueba usa el plugin de la application
y define una clase principal (que es Hello
en mi caso). Luego puedo ejecutar ./gradlew installDist
para generar un archivo ejecutable (consulte los documentos del complemento de la aplicación ) que coloca todas las dependencias en el classpath y se ejecuta perfectamente.
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"