style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Construcción de Proyectos con Gradle ( artículo. de ezamudio )

En la revista Software Guru de agosto saldrá este artículo escrito por Enrique Zamudio.

Se los comparto acá. Seguramente Enrique no lo posteo aquí porque es muy modesto o porque se le olvidó.

Fuente original:

@pedrogk

http://swgu.ru/p7FZiD


SG33 - Tutorial. Construcción de proyectos con Gradle


Sección: Tutorial

Estatus: Editado (PGK)

-------------------

Construcción de Proyectos con Gradle

Fácil y rápido

Por Enrique Zamudio

Una parte importante del desarrollo de software es la construcción de los proyectos y los sistemas completos. Desde la clásica herramienta make en los 70’s, ha habido varios mecanismos y sistemas distintos para construcción de proyectos, algunos enfocados a ciertos aspectos de la construcción, otros tratando de abarcar todo el espectro: compilación, manejo de dependencias, integración contínua, automatización del proceso de construcción, etc.

En el mundo Java, primero tuvimos Ant, una herramienta en cierta forma similar al make pero hecha 100% en Java, enfocada a construcción de proyectos Java. Al principio parecía muy buena, porque la sintaxis no era tan oscura como la de make, sino que usa XML, de modo que es más entendible lo que se quiere hacer. Pero cuando se comienzan a hacer scripts más complejos, la XML-itis se vuelve difícil de entender y modificar.

Luego hemos tenido otras cosas como Ivy y Maven. Ivy se enfoca al manejo de dependencias, que consiste en indicar qué bibliotecas externas de software se necesitan para poder compilar el proyecto, cuáles se necesitan para correrlo, cuáles para probarlo, etc. Maven, por su parte, abarca el ciclo completo: compilación, manejo de dependencias, pruebas unitarias, documentación técnica (javadoc) y hasta el sitio del proyecto puede hacer, todo esto gracias a que tiene una arquitectura de plugins bastante completa. Pero Maven, al ser tan completo, se vuelve a la vez complejo: para compilar un proyecto tipo “hola, mundo!” y generar su documentación se requieren unas 30 líneas de XML (probablemente más líneas que el mismo código fuente de un proyecto tan simple).

Gradle: Un sistema muy groovy

Nos saltamos a 2008, cuando surge el proyecto Gradle (pronunciado más o menos greirol). Este sistema para construcción de proyectos toma lo mejor de lo que ya existe: puede integrar tareas de Ant, usar el manejo de dependencias de Ivy, ciclos de compilación y pruebas tipo Maven y, lo mejor de todo, sigue el paradigma de convención sobre configuración; es decir, todas las opciones configurables tienen valores por defecto con lo más común o útil, de modo que sólo es necesario modificarlos para casos especiales, pero para la mayoría de los casos se puede usar el valor por omisión, lo cual nos permite tener scripts bastante breves.

Una de las características que hacen a Gradle tan sencillo de usar, es que los scripts usan un lenguaje específico de dominio (Domain-Specific Language, DSL) que extiende el lenguaje de programación Groovy. Esto le da a Gradle a la vez sencillez y poder, ya que en los scripts se pueden utilizar elementos tanto de programación orientada a objetos como de programación funcional. Gradle cuenta también con una arquitectura de plugins y de entrada ofrece varios muy útiles: para compilar proyectos Java, proyectos Groovy (y por supuesto híbridos Java+Groovy), crear artefactos para publicar en repositorios Maven, generar documentación técnica (Javadoc/Groovydoc), realizar pruebas unitarias y generar reportes con los resultados, etc. Y por supuesto, cuenta con una API para que terceros puedan crear sus propios plugins.

Veamos un ejemplo sencillo, para lo cual necesitamos crear un proyecto muy sencillo, algo un poquito arriba del típico “Hola, Mundo!” para poder integrar pruebas unitarias y documentación.

Hola, Gradle

Lo primero, por supuesto, es instalar Gradle. El único prerrequisito previo es tener instalado un JDK. Teniendo esto, descargamos la versión más reciente de Gradle en http://gradle.org (que al momento de escribir este artículo, es 1.0-milestone-3), desempaquetamos el .zip en el destino de nuestra preferencia, y apuntamos a ese directorio la variable de ambiente GRADLE_HOME. También es recomendable agregar a la ruta de ejecutables (PATH) el directorio $GRADLE_HOME/bin para que podamos llamar al ejecutable de gradle desde cualquier directorio. Para probar que la instalación es correcta, podemos ejecutar en una línea de comando gradle -v y nos debe regresar el número de versión de gradle que instalamos.

Una vez que hemos completado la instalación, crearemos un proyecto Java. Por el momento, vamos a crear de forma manual la estructura de directorios del proyecto, pueden hacerlo ya sea desde línea de comando o con el administrador de archivos de su sistema operativo. Hay que crear un directorio raíz para el proyecto, HolaSG (Gradle usará el nombre de este directorio para el nombre del proyecto) y debemos tener la siguiente estructura de directorios debajo:

src/main/java/ejemplo

src/main/resources

src/test/java/ejemplo

src/test/resources

Si les parece conocida la estructura, es porque está basada en la que Maven ha hecho tan popular. En src/main/java va el código fuente, src/test/java contiene las pruebas unitarias. Los directorios src/main/resources y src/test/resources son para recursos auxiliares (XML, properties, imágenes, etc), tanto para el proyecto como para sus pruebas unitarias, pero este ejemplo es muy simple y no vamos a usar archivos auxiliares, de modo que podemos simplemente omitir estos directorios.

El código

Ahora sí, vamos a crear una clase en Java:

HolaJava.java (dentro de src/main/java/ejemplo)

package ejemplo;

public class HolaJava {

  public String saluda(String quien) {

    return String.format("Hola, %s! (en Java)");

  }

}

Por ahora vamos a saltarnos la prueba unitaria, para irnos directo a compilar. A fin de cuentas, este artículo es de Gradle, no de Test Driven Development.

El script

El script de Gradle debe ir directamente bajo el directorio HolaSG. Puede tener cualquier nombre, pero así como en ant la convención es un build.xml, en Gradle es un build.gradle. Y debe contener la fabulosa cantidad de una línea de código:

apply plugin:’java’

Como mencioné al principio, Gradle usa la convención sobre la configuración. De modo que lo único que estamos haciendo aquí es indicarle que cargue el plugin para proyectos Java, y ese plugin se encargará del resto. Este plugin es bastante completo, ya que va a descargar las dependencias necesarias (ninguna por el momento), compilar el código, ejecutar las pruebas unitarias y hasta puede generarnos un JAR con las clases compiladas. Vamos a ejecutarlo, en la línea de comando debemos ir al directorio HolaSG y teclear:

gradle build

Veremos cómo se ejecutan varias tareas: compileJava (compila el código), processResources (copia los archivos de src/main/resources a donde quedaron las clases compiladas), classes, jar, assemble (arma los artefactos o entregables definidos para el proyecto), compileTestJava (compila las pruebas unitarias), processTestResources (copia los archivos de src/test/resources a donde quedaron las pruebas unitarias compiladas), testClasses y test (que ejecutan las pruebas unitarias), check y finalmente, build. Debemos al final ver el mensaje de BUILD SUCCESSFUL y el tiempo que le tomó todo el proceso.

Ahora podemos ver que tenemos dos directorios nuevos bajo HolaSG: .gradle y build. El .gradle es un directorio interno de Gradle para almacenar el estado de todos los recursos involucrados en la construcción del proyecto, lo cual le permite saber entre otras cosas, qué clases hay que recompilar en ejecuciones subsecuentes. Y el directorio build contiene el resultado del proceso. Dentro podemos ver un directorio classes/main y ahí encontraremos nuestro HolaJava.class; y si vemos en libs encontraremos un HolaSG.jar.

Si ejecutamos nuevamente gradle build, veremos la lista de tareas nuevamente pero junto a cada una saldrá la leyenda UP-TO-DATE, esto gracias al cache que le permite a Gradle saber que todo está actualizado y por lo tanto ninguna tarea hizo realmente nada.

Pruebas unitarias

Bien, ahora que ya vimos a Gradle en acción por primera vez, agreguemos una prueba unitaria al proyecto. En este caso utilizaré jUnit para mis pruebas, para mostrar lo fácil que es configurarlo y utilizarlo:

TestAll.java (en src/test/java/ejemplo)

package ejemplo;

import org.junit.*;

public class TestAll {

  @Test public void testSaludo() {

    HolaJava o = new HolaJava();

    assert "Hola, Mundo! (en Java)".equals(o.saluda("Mundo"));

  }

}

Y ahora debemos agregar unas líneas al script de Gradle, para que nos quede así:

apply plugin:java

repositories {

  mavenCentral()

}

dependencies {

  testCompile ‘junit:junit:4.8.2’

}

Con esto modificamos la configuración de Gradle: primero, definimos repositorios de código para poder descargar las dependencias necesarias. Dado que el repositorio central de Maven es el lugar más utilizado, Gradle ya tiene un método para agregar su configuración a los repositorios, de modo que sólo tenemos que invocarlo.

Y para las dependencias, estamos indicando que para la compilación de las pruebas unitarias queremos usar jUnit 4.8.2. Las dependencias se pueden indicar simplemente con una cadena en formato groupID:artifactID:version para buscarlas en el repositorio de Maven. En este caso definimos dependencias para la tarea de compilación de pruebas con testCompile, pero también lo podemos hacer para otras tareas como compile (compilación de clases del proyecto), runtime (ejecución de la aplicación) o testRuntime (se usan para correr las pruebas, no para compilarlas). Es posible definir dependencias para tareas adicionales en caso que fuera necesario, pero estas que menciono son las más comunes.

Para ejecutar las pruebas tecleamos gradle test. Veremos pasar las tareas de compileJava y demás con la señal UP-TO-DATE y posteriormente compileTestJava donde se compila nuestra nueva clase de prueba. Luego, al llegar a la tarea test que es donde se ejecutan las pruebas, nos encontraremos con un mensaje de error. La prueba unitaria falló (la clase HolaJava tiene un error intencional). Podemos abrir el reporte en build/reports/tests/index.html para ver la razón (Gradle nos entrega un reporte muy bonito en HTML con el resultado de las pruebas unitarias, ver figura 1).

Figura 1. Reporte de resultado de pruebas.

Al revisar la prueba podemos ver que tenemos un defecto en nuestra clase HolaJava. Corregimos el código, cambiando la línea que genera el saludo para agregar el parámetro faltante:

return String.format("Hola, %s! (en Java)", quien);

Ahora ejecutamos nuevamente las pruebas con gradle test para verificar que salen bien.

Aprovechemos este momento para agregarle una etiqueta con la versión y descripción a nuestro proyecto. Para agregar estos datos, simplemente hay que agregar unas líneas en nuestro script de gradle, debajo de nuestra línea donde invocamos el plugin de java.

version = '0.1'

description = 'Ejemplo de uso de Gradle para Revista SG'

Documentación Técnica

La documentación técnica es una parte fundamental de todo proyecto. En Java tenemos la facilidad del javadoc que nos permite generar documentación de cada clase y cada método a partir de los comentarios que se le pongan al código, siguiendo ciertos lineamientos. El problema generalmente es generar la documentación, ya que el comando es muy engorroso de invocar. Herramientas como Ant lo hacen un poco menos complicado y Maven incluye lo necesario para poder generar la documentación; por supuesto Gradle no se queda atrás.

Primero que nada, hay que agregar los comentarios a nuestro código, para que haya algo que generar:

/** Clase de ejemplo para demo Gradle en SG

 *

 * @author Enrique Zamudio

 */

public class HolaJava {

  /** Devuelve un saludo a la persona que se indique.

   * @param quien La persona a quien hay que saludar

   * @return Una cadena saludando a la persona indicada.

   */

  public String saluda(String quien) {

    return String.format("Hola, %s! (en Java)", quien);

  }

}

Y ahora simplemente debemos ejecutar gradle javadoc y después podemos abrir en un navegador el archivo build/docs/javadoc/index.html para ver la documentación generada.

Adicionalmente, en proyectos de tipo biblioteca de clases, es común generar por separado un JAR con el javadoc y otro JAR con los archivos de código fuente (en proyectos de software libre y en proyectos subcontratados), para tener una distribución completa.

Para crear los JARs, necesitamos definir dos tareas nuevas. En Gradle, las tareas llevan un nombre, un tipo, y algunas otras propiedades, como dependencias con otras tareas, etc. Cada tarea puede tener propiedades distintas. Una tarea se declara con la palabra task y el nombre de la misma. Cada tarea lleva una serie de acciones y se le pueden agregar acciones a las tareas existentes, así como modificar sus propiedades. Gradle mantiene una lista de todas las tareas en la propiedad tasks y se pueden obtener por nombre.

Primero agreguemos a las opciones de javadoc la lista de ligas externas con la referencia a la documentación de Java, para que el parámetro y valor de retorno del método saluda tengan referencia a la clase String. Agreguemos esta linea al final de build.gradle:

tasks.javadoc.options.links=[

  'http://download.oracle.com/javase/6/docs/api/'

]

En esa lista se pueden agregar referencias a la documentación de otras dependencias del proyecto, pero por el momento no tenemos ninguna. Las tareas que necesitamos definir para crear los JARs son estas (las podemos agregar al final del script):

task javadocJar(type:Jar, dependsOn:'javadoc') {

        from javadoc.destinationDir

        classifier='javadoc'

}

task sourcesJar(type:Jar) {

        from sourceSets.main.allSource

        classifier='sources'

}

Lo que estamos haciendo es definir la tarea javadocJar, de tipo Jar y que depende de la tarea javadoc; es importante definir esta dependencia para obligar a que primero se genere la documentación, sino vamos a generar un jar vacío o con documentación desactualizada. Para el segundo Jar no tenemos dependencias porque sólo vamos a incluir los fuentes, pero hay que indicar que queremos únicamente los fuentes del proyecto y no los de las pruebas.

Cabe mencionar que el plugin de Java agrega el concepto de sourceSets a Gradle, que son precisamente los conjuntos de archivos de código fuente. Por omisión se definen dos conjuntos: main, con las clases del proyecto, y test, con las pruebas unitarias. Por omisión, los fuentes del conjunto main están en src/main/java. Dado que estamos siguiendo convenciones, no es necesario que especifiquemos todo esto de forma explícita en nuestro script. En la tarea de sourcesJar, estamos incluyendo TODOS los fuentes (incluyendo recursos) del conjunto main. Y a cada Jar le pusimos un clasificador, el cual irá en el nombre del archivo resultante, ya que por omisión Gradle va a crear los Jars usando el nombre del proyecto, la versión y el clasificador.

Y ahora podemos ejecutar estas tareas de manera secuencial, simplemente hay que indicar cada una en la línea de comando. De modo que tecleamos gradle javadocJar sourcesJar y al final en el directorio build/libs tendremos HolaSG-0.1-javadoc.jar y HolaSG-0.1-sources.jar.

Pero estas son tareas definidas específicamente en este proyecto, no parecen ser algo estándar; la idea de estos scripts y herramientas es facilitarle la vida a cualquier persona que quiera construir el proyecto, permitiéndoles ejecutar el script sin tener siquiera que verlo; honestamente, ¿cuántos de nosotros hemos visto un Makefile de un proyecto que bajamos y construimos desde fuentes? Simplemente le damos ./configure && make && sudo make install y listo. Afortunadamente, el plugin de Java para Gradle detecta cualquier tarea de tipo Jar y la agrega automáticamente a la tarea de assemble. Y esa tarea a su vez depende de las de compilación (pero no de las de pruebas). De modo que podemos definir que algunas tareas se ejecuten por omisión en nuestro script. Agreguemos esta línea después de donde definimos la versión:

defaultTasks ‘build’, ‘assemble’

Ahora, podremos simplemente ejecutar gradle sin ningún argumento adicional y se ejecutarán las tareas de compilación, pruebas, javadoc, etc. Puedes borrar todo tu directorio build antes de correr la tarea, para asegurar que sí se recree todo. Al final, en build/libs tendremos tres JARs: el binario, el de fuentes y el de documentación.

Capacidades avanzadas

La simplicidad de uso de Gradle puede ser engañosa, pues es realmente una herramienta muy, muy poderosa. En esta ocasión quise resaltar lo sencillo que puede ser su uso, para compilar un proyecto muy sencillo.

Algunas capacidades avanzadas que no se cubrieron en este tutorial de introducción pero que seguramente requerirán en proyectos complejos son: incluir dependencias en la configuración de compile y tal vez la de testRuntime; agregar dependencias locales, para esos casos tan comunes en que se tiene un directorio con muchos JARs existentes; convertir el proyecto en uno políglota, cambiando el plugin de Java por el de Groovy para compilar y probar clases en ambos lenguajes; crear scripts multi-proyecto, para poder compilar, armar y juntar varios proyectos con un solo comando, manejando dependencias y otras configuraciones tanto de manera individual como global. Esta última capacidad hace a Gradle mucho muy superior a otras herramientas de construcción populares.

También es posible crear tareas de manera dinámica, es decir, que no están definidas de manera formal en el script pero éste contiene código que al momento de ejecutarlo, genera tareas que pueden depender de otras tareas y agregarse a las existentes. Esto parece muy esotérico al principio, pero realmente puede facilitarnos la vida, especialmente cuando se usa Gradle para organizar, integrar y automatizar la construcción de proyectos existentes.

El código fuente utilizado para este tutorial está disponible en https://github.com/chochos/HolaSG 

------------

[Semblanza]

Enrique Zamudio es Licenciado en Sistemas Computacionales egresado de la Universidad Iberoamericana y tiene 17 años desarrollando software profesionalmente, principalmente utilizando tecnologías relacionadas con Java del lado del servidor. Es autor de los proyectos de software libre jAlarms y j8583, y forma parte del staff de la comunidad de desarrolladores JavaMéxico. @chochosmx github.com/chochos.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Genial ezamudio

Gracias por compartir tu concocimiento ezamudio, eres grande :)
sigue ilustrandonos en javamexico .

+1

Vientos \m/

Imagen de ezamudio

Utilidad

Espero les sea de utilidad la info, a mi la verdad me gustó mucho Gradle, ya pude usarlo en vez de Maven en mis 2 principales proyectos de software libre, y lo estoy usando ya también en la chamba para automatizar la construcción de unos 50 proyectos (módulos de un sistema) que antes solamente manejábamos con Eclipse.

El artículo es para la revista Software Guru, saldrá en la edición de Agosto. La audiencia es un poco distinta (según yo está más orientada a gerencias, IT empresarial, etc), espero que tenga buena recepción ahí también.

Imagen de Sr. Negativo

Buena info

Esta muy bien explicado. Compartir no empobrece je je. Gracias.

Así es Sr(-) de hecho cuesta

Así es Sr(-) de hecho cuesta bastante trabajo comunicarse efectivamente y Enrique lo hace muy bien en este artículo.

Imagen de CesarAlducin

Muy buen Articulo

Esta muy interesante tu articulo, si no fuera mucha molesta nos platicaras un poco mas como lo estas
aplicando para la automatización de tus proyectos.

En lo particular no había escuchado mucho sobre este tema, es lo interesante de poder compartir opiniones.
en JavaMexico.

Imagen de ezamudio

dos previos

Previo a este, escribí dos artículos en mi blog: un ejemplo sencillo donde no uso ningún plugin, es simplemente un relato de mi primer contacto con Gradle, para sustituir unos scripts de Ant, y otro de aplicarlo a proyectos existentes, ya usando el plugin de Java y viene un poquito de multiproyecto (aunque ya encontré mejores maneras de construcción de multiproyecto desde entonces).

Posteriormente quiero hacer otro artículo más enfocado a multiproyecto, pero pues 1)necesito tiempo y 2)quiero ver qué aceptación tiene este artículo en la revista, para ver si se puede convertir en una serie de 2 ó 3 artículos más, o si ya lo sigo publicando aquí.

Imagen de ingscjoshua

Dudas NetBeans

Hola stimados Tengo un proyecto que por Azares del destino usa glasfish y ya todos sabmos lo horrible q es tratar de usar eclipse con glasfish!!! y por eso me veo obligado a usar netbeans tengo mi proyecto dividido en 4 proyectos el web y 3 java standar el problema es q tengo estar agragando los jars en todos mis proyectos!! pff es horrible mis jars pesan muchisimo hay alguan formade ahcerlo con gradel o q puedo utilizar?. desde Ya Muchas gracias

Imagen de ezamudio

con Gradle

Simplemente necesitas crear tu script, declarar las dependencias que requieres, usar el plugin de war y con eso empaquetas al final tu aplicacion.war si quieres versionada y todo.

El plugin de war es similar al de Java, con algunas configuraciones adicionales de dependencias (provided, para las que se usan en compilación pero no se deben meter al WAR) y pues al final en lugar de jar te genera un war.

Imagen de ingscjoshua

Gracias

Muchas gracias por la info de donde lo puedo descargar?

Imagen de ezamudio

jaj

Muchas gracias por la info de donde lo puedo descargar

De verdad?

Si te refieres a de dónde descargas Gradle, en el artículo dice claramente...

Imagen de ingscjoshua

jeje

Sip ya revise sorry estaba en mis 5 min de mi while(true) jeje Sorry

Imagen de Sr. Negativo

Odio Maven

En serio lo odio. Leo y vuelvo a leer documentación sobre Maven y de plano no le agarro la onda.

Estoy sufriendo tratando de integrar JSF/Maven/Spring/Hibernate/Eclipse (apenas comprendo lo básico de Spring y más problemas tengo), instale el plugin para Eclipse, parece funcionar correctamente pero sigo teniendo problemas.

Gradle como que me esta convenciendo...

no puedo correr en servidor la aplicación web

Hola estoy tratando de correr un proyecto en el servidor y estoy implementando gradle, he estado buscando información sobre como correr el proyecto desde el IDE para poder debbuggear, pero no he encontrado nada :(

Alguien podría orientarme un poco?

Agradecería su apoyo infinitamente.

Gracias :)

Imagen de Sr. Negativo

Gradle para NetBeans

Yo tenía un problema similar, existe un plugin para NetBeans Gradle para NetBeans

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">