Mostrando entradas con la etiqueta shadow plugin. Mostrar todas las entradas
Mostrando entradas con la etiqueta shadow plugin. Mostrar todas las entradas

miércoles, 25 de mayo de 2022

Gradle-7 (9) Gradle Multiproyecto (3). Creando wars. Shadow plugin. Reflexiones

1. Creando wars en multiproject

NOTA: Hay un conflicto entre el plugin war (cuando usamos la opcion api(project(":A000-Basic")) para cada uno de los proyectos de los que depende y la ejecución/depuración de la aplicación web en eclipse, ya que eclipse no copia los jars de los proyectos que depende a la carpeta de despliegue local de tomcat en eclipse:

WORKSPACES/WS_JSP01/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Mywebapp/WEB-INF/lib

Pero cuando genera el war desde la ventanda de "Gradle-tasks", si que lo genera bien.

Hay 2 opciones "sucias" para arreglarlo:

1. Copiar a mano los jars de los proyectos-dependencia a en dicha carpeta o
2. Indicar en el build.gradle 

implementation files(
      'path_to_firstjar/firstjar.jar',
        'path_to_secondjar/secondjar.jar',
        ........
)

Después de reflexionar, me parece que lo más lógico es crear 2 ficheros build.gradle (build.gradle.eclipse y build.gradle.gradle

Cada vez que queramos ejecutar el proyecto en eclipse o generar el war se copiará  build.gradle.eclipse a build.gradle. Esto equivale a como casi si sacáramos nuestro proyecto del multiproyecto

Solamente, para tener todo actualizado y sincronizado se copiará build.gradle.gradle a build.gradle por tanto esta última opción hay que utilizarla poco. Además esta última opción pierde mas dependencias que la otra por lo que los build.gradle pueden cambiar significativamente.

Veamos para un proyecto complejo primeramente el build.gradle que se ejecuta bien desde eclipse y también su jar es menos problemático (build.gradle.eclipse) y la parte de amarillo es donde se indican las dependencias, y varía significativamente con respecto a la otra versión.

plugins {
    // Apply the java-library plugin for API and implementation separation.
    id 'java-library'
    id 'war'
    id "org.gretty" version "4.0.1"
}

repositories {
    jcenter()
    mavenCentral()
}


//Configuration
project.war.destinationDirectory = file("$rootDir/../mynewtargets")  
project.archivesBaseName = 'CSV01' 
project.version = '3.0'


dependencies {
       
    //=============LOMBOK BEGIN ============================
    compileOnly 'org.projectlombok:lombok:1.18.20'
    annotationProcessor 'org.projectlombok:lombok:1.18.20'
	
    testCompileOnly 'org.projectlombok:lombok:1.18.20'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
    //=============LOMBOK END ==============================
    
    // JSP & SERVLETS
    compileOnly 'jakarta.servlet:jakarta.servlet-api:5.0.0'
    implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:2.0.0'
    
    compileOnly 'jakarta.platform:jakarta.jakartaee-api:9.1.0' 
    compileOnly 'jakarta.el:jakarta.el-api:4.0.0'
        
    compileOnly 'jakarta.platform:jakarta.jakartaee-web-api:9.1.0' //Multipart
    implementation 'jakarta.activation:jakarta.activation-api:2.1.0'
    
    
    //Apache
    implementation 'commons-io:commons-io:2.11.0' 
    implementation 'org.apache.commons:commons-lang3:3.12.0' 
    implementation 'commons-codec:commons-codec:1.15'
    implementation "org.apache.commons:commons-vfs2:2.9.0"
    
    /* SELENIUM */
    api "org.seleniumhq.selenium:selenium-server:3.141.59"
    implementation 'org.seleniumhq.selenium:selenium-java:4.1.2'
    implementation "org.seleniumhq.selenium:selenium-firefox-driver:4.1.2"
    implementation "org.seleniumhq.selenium:selenium-chrome-driver:4.1.2"
    
    /* PDFBox */
    implementation 'org.apache.pdfbox:pdfbox:2.0.24'
    
    /* Samba */
    implementation "com.hierynomus:smbj:0.11.3"
    
    /* sftp */
    implementation 'com.jcraft:jsch:0.1.55'
    
    /* HIbernate */    
    implementation "org.hibernate:hibernate-core-jakarta:5.6.9.Final"
    implementation "org.hibernate:hibernate-envers-jakarta:5.6.9.Final"
    implementation "org.hibernate:hibernate-validator:7.0.4.Final" 
        
    
    /*DB Drivers */
    //runtimeOnly "com.h2database:h2:1.4.200"
    implementation "org.postgresql:postgresql:42.2.20"
    implementation "net.sourceforge.jtds:jtds:1.3.1"      
    
     /*CMIS*/    
    implementation "org.apache.chemistry.opencmis:chemistry-opencmis-client-impl:1.1.0"
    
     /* Jackson */
    implementation "com.fasterxml.jackson.core:jackson-core:2.13.2"
    implementation "com.fasterxml.jackson.core:jackson-annotations:2.13.2"
    implementation "com.fasterxml.jackson.core:jackson-databind:2.13.2.2"
    implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.2"
    implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.13.2"
    implementation "com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.13.2"
    implementation "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.2"
    implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2"   
    
    /* BAR CODES */
    implementation 'com.google.zxing:core:3.4.1'
    implementation 'com.google.zxing:javase:3.4.1'
    
    //Own libraries
    
    implementation files(
     	"$rootDir/../mynewtargets/a000-basic-3.0.jar",
     	"$rootDir/../mynewtargets/a002-jackson-3.0.jar",
     	"$rootDir/../mynewtargets/a004-pdf-3.0.jar",
     	"$rootDir/../mynewtargets/a006-cmis-3.0.jar",
        "$rootDir/../mynewtargets/a009-samba-3.0.jar",
        "$rootDir/../mynewtargets/a010-sftp-3.0.jar",
        "$rootDir/../mynewtargets/a011-barcode-3.0.jar",
        "$rootDir/../mynewtargets/a012-selenium-3.0.jar",
        "$rootDir/../mynewtargets/b001-model-base-3.0.jar",
        "$rootDir/../mynewtargets/b003-dao-3.0.jar",
        "$rootDir/../mynewtargets/c002-model-control-3.0.jar",
        "$rootDir/../mynewtargets/c005-model-csv-3.0.jar",
        "$rootDir/../mynewtargets/c007-model-gexflow-3.0.jar",
        "$rootDir/../mynewtargets/d001-dao-imp-3.0.jar",
      )
}


Para la versión que sirve únicamente para tener el proyecto actualizado (build.gradle.gradle), en amarillo se ven los cambios respecto a la anterior versión.

plugins {
    // Apply the java-library plugin for API and implementation separation.
    id 'java-library'
    id 'war'
    id "org.gretty" version "4.0.1"
}

repositories {
    jcenter()
    mavenCentral()
    maven { url "https://jitpack.io" } //@see: https://stackoverflow.com/questions/38905939/how-to-import-library-from-jitpack-io-using-gradle
    maven { url "https://repository.mulesoft.org/nexus/content/repositories/public/"}
}


//Configuration
project.war.destinationDirectory = file("$rootDir/../mynewtargets")  
project.archivesBaseName = 'CSV01' 
project.version = '3.0'


dependencies {
       
    //=============LOMBOK BEGIN ============================
    compileOnly 'org.projectlombok:lombok:1.18.20'
    annotationProcessor 'org.projectlombok:lombok:1.18.20'
	
    testCompileOnly 'org.projectlombok:lombok:1.18.20'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
    //=============LOMBOK END ==============================
    
    // JSP & SERVLETS
    compileOnly 'jakarta.servlet:jakarta.servlet-api:5.0.0'
    implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:2.0.0'
    
    compileOnly 'jakarta.platform:jakarta.jakartaee-api:9.1.0' 
    compileOnly 'jakarta.el:jakarta.el-api:4.0.0'
        
    compileOnly 'jakarta.platform:jakarta.jakartaee-web-api:9.1.0' //Multipart
    implementation 'jakarta.activation:jakarta.activation-api:2.1.0'
    
    
    //Apache
    implementation 'commons-io:commons-io:2.11.0' 
    implementation 'org.apache.commons:commons-lang3:3.12.0' 
    implementation 'commons-codec:commons-codec:1.15'
    implementation "org.apache.commons:commons-vfs2:2.9.0"
    
    /* SELENIUM */
    api "org.seleniumhq.selenium:selenium-server:3.141.59"
    implementation 'org.seleniumhq.selenium:selenium-java:4.1.2'
    implementation "org.seleniumhq.selenium:selenium-firefox-driver:4.1.2"
    implementation "org.seleniumhq.selenium:selenium-chrome-driver:4.1.2"
    
    /* PDFBox */
    implementation 'org.apache.pdfbox:pdfbox:2.0.24'
    
    /* Samba */
    implementation "com.hierynomus:smbj:0.11.3"
    
    /* sftp */
    implementation 'com.jcraft:jsch:0.1.55'
    
    /* HIbernate */    
    implementation "org.hibernate:hibernate-core-jakarta:5.6.9.Final"
    implementation "org.hibernate:hibernate-envers-jakarta:5.6.9.Final"
    implementation "org.hibernate:hibernate-validator:7.0.4.Final" 
        
    
    /*DB Drivers */
    //runtimeOnly "com.h2database:h2:1.4.200"
    implementation "org.postgresql:postgresql:42.2.20"
    implementation "net.sourceforge.jtds:jtds:1.3.1"      
    
     /*CMIS*/    
    implementation "org.apache.chemistry.opencmis:chemistry-opencmis-client-impl:1.1.0"
    
     /* Jackson */
    implementation "com.fasterxml.jackson.core:jackson-core:2.13.2"
    implementation "com.fasterxml.jackson.core:jackson-annotations:2.13.2"
    implementation "com.fasterxml.jackson.core:jackson-databind:2.13.2.2"
    implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.2"
    implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.13.2"
    implementation "com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.13.2"
    implementation "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.2"
    implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2"   
    
    /* BAR CODES */
    implementation 'net.sourceforge.barbecue:barbecue:1.5-beta1'
    implementation 'net.sf.barcode4j:barcode4j:2.1'  
    implementation 'com.github.kenglxn.qrgen:core:v2.2.0'
        
    implementation 'com.google.zxing:core:3.4.1'
    implementation 'com.google.zxing:javase:3.4.1'
        
    //1. Reference to other maven project in muiltiproject scenario
    api(project(":A000-Basic"))
    api(project(":A002-Jackson"))
    api(project(":A004-PDF"))
    api(project(":A006-CMIS"))
    api(project(":A009-Samba"))
    api(project(":A010-SFTP"))
    api(project(":A011-BarCode"))
    api(project(":A012-Selenium"))
    api(project(":B001-Model-Base"))
    api(project(":B003-DAO"))
    api(project(":C002-Model-Control"))
    api(project(":C005-Model-CSV"))
    api(project(":C007-Model-Gexflow"))
    api(project(":D001-DAO-Imp"))
}

Como se puede ver, se pierden referencias a algunos repositorios y a también a ciertos "jars", y además en este caso concreto, da errores de dependencias transitivas con las versiones de org.codehaus.woodstox:stax2-api

Esto en cambio no ha pasado en el build.gradle anterior

2. Gradle build-build vs shadow-shadowJar

En el proyecto principal (en este caso Multiproject), hay 2 operaciones importantes que no hay que confundir:

1. build-build: Genera todos los jars y wars del proyecto

2. shadow-shadowJar: Genera todos los jars o wars pero solo de aquellos proyectos que han utilizado el shadow plugin, junto con los proyectos que son necesitados(dependencias) por los proyectos con shadow.


Por tanto para construir todos los jars y wars convierne utilizar la primera opción


3. Errores y resultados inesperados en la ejecución

Cuando incluimos un subproyecto con shadow jar, Eclipse tarda muchísimo en actualizar las referencias, de manera que si ejecutamos el projecto que hace referencia a otro con shadow plugin aparecen resultados incoherentes.

Esto es debido a que Eclipse utiliza "caches" para que la cosa vaya más rápida, pero lo que está haciendo es provocar resultados extraños pues no tarda mucho en actualizarse los caches. Mucho cuidado y paciencia.

Para evitar estos problemas, es conveniente sacar los proyectos que dependan de aquellos que se utiliza el shadow jar, fuera de este gradle multiproyecto

martes, 24 de mayo de 2022

Gradle-7 (8) Gradle Multiproyecto (2) Shadow plugin con Apache CXF . Soluciónes al problema de ejecución- Manda Güevos!

0. Introducción

El famoso "jar hell" o infierno de los jars, se manifiesta aquí en todo su esplendor. En concreto la integración de Apache CXF ha corrido mas ríos de sangre y frustación que de tinta.

1. Shadow plugin con Apache CXF

Recordar crear el subproyecto dentro del módulo principal y añadirle la referencia al subproyecto en "settings.properties" del proyecto principal 


El settings.gradle seria:


rootProject.name = 'Multiproject'

include('lib', 

        'A000-Basic', 'A003-Excel', 'A004-PDF', 

        'B001-Model-Base', 'B003-DAO', 

        'C002-Model-Control', 'C005-Model-CSV', 

        'D001-DAO-Imp', 'D002-Sedipualba-WS-Shdw',   

        'PH01', 'PH01-Simple')


Veamos el fichero build.gradle

Hay que prestar especial atención a las líneas que hacen referencia al transformer y a las reubicaciones que son muy truculentas ("tricky")

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
plugins {
    // Apply the java-library plugin for API and implementation separation.
    id 'java-library'
    //id 'application'
    id 'com.github.johnrengelman.shadow' version '7.1.2'
}

import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer


repositories {
    jcenter()
    mavenCentral()
    maven { url "https://jitpack.io" } //@see: https://stackoverflow.com/questions/38905939/how-to-import-library-from-jitpack-io-using-gradle
}


dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'

    /***********************************************************************
    *********************** LOMBOK DEFINITION ******************************/
    compileOnly             'org.projectlombok:lombok:1.18.20'
    annotationProcessor     'org.projectlombok:lombok:1.18.20'
    testCompileOnly         'org.projectlombok:lombok:1.18.20'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
    /************************************************************************
    *********************** END LOMBOK DEFINITION ***************************/
    
    api(project(":A000-Basic"))
        
    // Apache general //
    implementation "commons-beanutils:commons-beanutils:1.9.4"
    implementation "commons-io:commons-io:2.11.0"
    implementation "org.apache.commons:commons-lang3:3.12.0"
        
    
    /*Apache CXF*/
    implementation 'org.apache.cxf:cxf-core:3.5.2'
    implementation 'org.apache.cxf:cxf-rt-features-logging:3.5.2'
    implementation 'org.apache.cxf:cxf-rt-ws-security:3.5.2' // WSS4JInterceptors, WSPasswordCallback
    implementation 'org.apache.cxf:cxf-rt-frontend-jaxws:3.5.2' //Dynamic client
    implementation 'org.apache.cxf:cxf-rt-transports-http:3.5.2'//Si no es fica,  es queda penjat !!!
    
    implementation 'com.sun.xml.ws:jaxws-ri:2.3.5' //FUNCIONA!  Quita:com.sun.tools.internal.xjc.api.XJC   
    
    /* Jackson */
    implementation "com.fasterxml.jackson.core:jackson-databind:2.13.3"
    
 } //dependencies

shadowJar {
    transform(AppendingTransformer) {
    	resource = 'META-INF/cxf/bus-extensions.txt'
    }	
    //1. Name and location of jars
    destinationDirectory = file("$rootDir/../mynewtargets") 
    archiveBaseName.set('d002-sedipualba-ws-shdw')
    archiveClassifier.set('')
    archiveVersion.set('2.1')
	//mainClassName = 'openadmin.utils.sedipualba.SedipuAlbaUtilsWSSeres'
	
    //2. Relocate (shadow) old problematic transitive dependency
    relocate 'com.sun.xml.bind.v2', 'com.sun.xmlv2.internal.bind.v2'
    relocate 'com.sun.xml'        , 'com.sun.xmlv2'    
    relocate 'javax.xml.bind'     , 'javax.xml.bindv2' 
	
	
    //4. Include sources
    from sourceSets.main.allSource
	
}//shadowJar


tasks.named('test') {
    // Use JUnit Platform for unit tests.
    useJUnitPlatform()
}//tasks

Veamos las líneas importantes:

5: Se importa el gradle shadow plugin.

8: Se importa el transformer, pieza clave para que se pueda empaquetar apache cxf. Ver la contestación de petternordholm 

40-44: Dependencias de Apache CXF

46-49: Dependencias que se requieren en apache CXF

54-56: Aplicación del transformer. Sin esto, da un montón de referencias nulas (Bindings...)

58-61: Se define nombre y ubicación del jar generado

66: Reubicación importante: Hay conflictos a partir de la versión 3, pues se cambia la referencia desde javax a jakarta. Por tanto hay que utilizar el shadow para que reubique estas dependencias antiguas que las llama apache cxf. (que internamente llaman a javax)

65: Volvemos atras una línea, para indicar que si se reubiva la línea 65, entonces el sistema se "inventa" una reubicación intermedia llamada "internal". Por tanto hay que tener cuidado

67: Reubicación del javax para que nlo lo machaque el jakarta

71. Incluimos las fuentes ".java" para que la depuración sea más fácil

2. Subproyecto que usa este como referencia.

Aquí la cosa tiene truco.

Para ello seguimos la entrada anterior del blog y creamos un subproyecto "PH01-Simple" que solo va a tener de dependencia al subproyecto anterior, y otro. Recordar de crear la referencia a settings.gradle del proyecto padre.


Veamos el build.gradle

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
plugins {
    // Apply the java-library plugin for API and implementation separation.
    id 'java-library'
    id 'application'
}

repositories {
    jcenter()
    mavenCentral()
}

gradle.startParameter.showStacktrace = org.gradle.api.logging.configuration.ShowStacktrace.ALWAYS

project.jar.destinationDirectory = file("$rootDir/../mynewtargets")
project.archivesBaseName = 'PH01-Simple' 
project.version = '2.0'


dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
        
    //=============LOMBOK BEGIN ============================
    // Not generated by the Vaadin starting-project
    compileOnly 'org.projectlombok:lombok:1.18.20'
    annotationProcessor 'org.projectlombok:lombok:1.18.20'
	
    testCompileOnly 'org.projectlombok:lombok:1.18.20'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
    //=============LOMBOK END ==============================
    api(project(":A000-Basic"))
implementation project(path: ':D002-Sedipualba-WS-Shdw', configuration: 'shadow') } application { mainClass = 'alba.utils.AlbaEdu' } jar { duplicatesStrategy = 'exclude' from sourceSets.main.allSource //Include java sources }

Observar que:

  • No utilizamos el shadow plugin
  • Para referenciar a un proyecto hecho shadow plugin, ver la línea 32. En cambio un proyecto normal se referencia con la línea 31

Si le damos a la task de gradle application -run, parece ser que funciona 


Pero si le damos a ejecutar una clase que hace referencia al proyecto anterior (AlbaEdu) que usamos el shadow plugin. da error de ejecución y no encuentra la referencia a apache cxf.


Exception in thread "main" java.lang.NoClassDefFoundError: org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory

at openadmin.utils.sedipualba.SedipualbaUtilsOther.getClientsAndClassLoadersIRunBO(SedipualbaUtilsOther.java:270)

at alba.utils.AlbaEdu.<init>(AlbaEdu.java:32)

at alba.utils.AlbaEdu.main(AlbaEdu.java:106)

Caused by: java.lang.ClassNotFoundException: org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory

at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:827)

at java.base/jdk.internal.loader.ClassLoaders$Aimplementation project(path: ':D002-Sedipualba-WS-Shdw', configuration: 'shadow')implementation project(path: ':D002-Sedipualba-WS-Shdw', configuration: 'shadow')ppClassLoader.loadClass(ClassLoaders.java:188)

at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:1112)

... 3 more

3. 1ª Solución al problema

Para poder depurar esta clase en Eclipse, es importante que se pueda ejecutar. Para ello, como Eclipse no  puede encontrar las referencias al proyecto anterior (del shadow plugin), hay que indicárselo en la configuración de ejecución.

Apretar el botón derecho del ratón sobre la clase en cuestión (en mi caso AlbaEdu) y Run As ->Run Configurations o también Debug As > Debug Configurations

Le indicamos Add External Jars, y buscamos donde está el jar generado en el subproyecto anterior y lo añadimos. Y a funcionar!!!



4. 2ª Solución al problema

Es evidente que la solución anterior no es precisamente muy elegante. Parece ser que el shadow plugin y la implementación multiproyecto de eclipse no se comunican muy bien.

Otra solución poco elegante pero no tanto consiste en realizar estos pasos:

1. Generar el jar del proyecto que contiene el shadow plugin (maven lo contempla)

2. En vez de hacer referencia a este proyecto, se haría referencia al jar generado. En concreto bastaría con cambiar esta línea en el build-gradle:

implementation project(path: ':D002-Sedipualba-WS-Shdw', configuration: 'shadow')

por esta otra

implementation files(

        '../mynewtargets/d002-sedipualba-ws-shdw-2.1.jar',

)




Ahora me toca probar con un war!



jueves, 27 de enero de 2022

Gradle-7 (7) BUENA: Recapitulación, Dependencias transitivas incompatibles, Shadow Plugin, Strictly, Incluir Sources fuentes

 0. Introducción

1. Quitar la carpeta lib (como antes en Gradle <6.7)

2. El maravilloso Shodow plugin de John Engelman

3. Versionado "sctrictly", para fijar la veersión de la dependencia que funcione bien (FALLA)


 

1. Quitar la carpeta lib (como antes en Gradle <6.7)

Para ello, seguir estos pasos:

1. Crear el propyecto gradle en Eclipse

2. Una vez creado, se aprieta el boton derecho del ratón sobre el proyecto y indicamos "Delete", pero sin borrar el contenido.

3. Borramos todos los ficheros del proyecto creado, excepto la carpeta "lib",

4. Trasladamos el fichero build.gradle y la carpeta src a la carpeta del proyecto.

5. Borramos la carpeta lib, con lo que nos queda: la carpeta del proyecto, y dentro de ella, la carpeta src y el build.gradle

6. Ahora importamos el proyecto gradle desde Eclipse y ya está.


2. El maravilloso Shadow plugin de John Engelman

Este plugin permite:

1.Usar el plugin (línea 4 -> id 'com.github.johnrengelman.shadow' version '7.1.2')

2. Muy importante la línea 12  para ver donde falla la compilación!

3 Crear un "uber jar" o jar total. Para ello se añade la tarea shadowJar (línea 29) 

NO! 4 Reducir el tamaño del "uber jar" (linea 40 -> minimize() ) eliminameos dependencias no usadas

5. Solucionar el problema de las depencias transitivas con diferentes versiones e incompatibles. Para ello utiliza internamente la libreria ASM para cambier el "bytecode" de las clases. (Pueden haver algunos problemillas si se hace referencia a

las clases por reflexión). (Línea   ->relocate 'com.sun.xml.ws', 'com.sun.xml.ws234') En este caso cambiamos la ubicación de la carpeta com.sun.xml.ws a com.sun.xml.ws234

Veamos como hacerlo, para muestra un fichero "build.gradle"

6. Lo mas importante, aparece en las tareas de gradle, una carpeta "shadow" con la tarea shadowJar, que es la que genera el jar.

7. Las líneas 33-34 indicamos el nombre del fichero jar, versión y la carpeta donde se genera (en este caso se crea una carpeta llamada "mytargets" dentro del Workspace (a la misma altura que la carpeta del proyeco, así guardamos todos los jars que hacemos en la misma carpeta.

7. Se puede incluir el código fuente para poder depurarlo en Eclipse (línea 43)


 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
plugins {
    // Apply the java-library plugin for API and implementation separation.
    id 'java-library'
    id 'com.github.johnrengelman.shadow' version '7.1.2'
}

repositories {
    jcenter()
    mavenCentral()
    maven { url "https://jitpack.io" } //@see: https://stackoverflow.com/questions/38905939/how-to-import-library-from-jitpack-io-using-gradle
}
gradle.startParameter.showStacktrace = org.gradle.api.logging.configuration.ShowStacktrace.ALWAYS
dependencies {
    // Use JUnit test framework.
    testImplementation 'junit:junit:4.13.1'
    
    /***********************************************************************
    *********************** LOMBOK DEFINITION ******************************/
    compileOnly             'org.projectlombok:lombok:1.18.20'
    annotationProcessor     'org.projectlombok:lombok:1.18.20'
    testCompileOnly         'org.projectlombok:lombok:1.18.20'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
    /************************************************************************/
   
    /* Apache */
    implementation "commons-io:commons-io:2.11.0"
}    
// Output to build/libs/shadow.jar ?
shadowJar {
    //1. Name and location of jars
	archiveBaseName.set('a004-pdf')
	archiveClassifier.set('')
	archiveVersion.set('1.1')
	destinationDirectory = file("$rootDir/../mytargets") 
	
	//2. Relocate (shadow) old problematic transitive dependency com.sun.xml.ws:jaxws-rt:2.3.4
	relocate 'com.sun.xml.ws', 'com.sun.xml.ws234'
	
	//3. Discard not used libraries
	//minimize() //NO USAR

	//4. Include Sources
	from sourceSets.main.allSource
}
tasks.named('test') { // Use JUnit Platform for unit tests. useJUnitPlatform() }


3. Versionado "strictly" para fijar la version correcta (FALLA)

Con el tema de la migracion de javax a jakarta, hay liobrerias que tienen dependencias a versioes antiguas y otras a las nuevas.

En concreto tengo el error:

java.lang.ClassNotFoundException: javax.xml.bind.JAXBException

Y según se dice en stackoverflow las dependencias "org.glassfish.jaxb:jaxb-runtimealudidas" indirectamente són:

jakarta.xml.bind:jakarta.xml.bind-api
org.glassfish.jaxb:jaxb-runtime

Si intentamos ver las dependencias tal y como se indica en la imagen, cuando elprograma funciona bien para localizar las versiones correctas:



Cuando le añadimos la version de hibernate-core-jakarta, hace referencia a las versiones 3.x.x de ambas dependencias, con lo que deja de funcionar aquellas partes del programa que referencia a versiones 2.x.x.

Para ello le indicamos en la parte de depencencias del gradle, estas dependencias con la clausula "strictly"

 /**********************************************************************/
/* STRICTLY VERSIONS !!!!!!!!!*/
//Avoid version 4.0.0'
implementation ('jakarta.xml.bind:jakarta.xml.bind-api') { version { strictly '2.3.3'} }
    
//Avoid version 3.0.0
implementation ('org.glassfish.jaxb:jaxb-runtime') { version { strictly '2.3.6'} } 	
/**********************************************************************/