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

No hay comentarios :

Publicar un comentario