Desarrollando un plugin Maven Report (I)

Hace varios meses me enfrenté al primer desarrollo de un plugin Maven para generar un report en el site, y comprobé en mis carnes que había muy muy poca documentación, y en castellano era totalmente inexistente. Por ello considero interesante describir paso a paso el proceso para desarrollar un plugin sencillo del tipo Hola Mundo!, dejando para un post futuro otros detalles interesantes, como la utilización de ficheros properties, introducción de parámetros de configuración, generación de ficheros externos al report, etc.

Este post supone que el lector ya está suficientemente familiarizado con la utilización de Maven, por lo que no entraré en detalles excesivamente básicos, como explicar lo que es un pom.xml, cómo se utiliza Maven, etc. Lo único básico que explicaré es que un plugin Maven Report sirve para generar un informe que se anexa al site del proyecto (se invoca, por ejemplo, ejecutando ‘mvn site’) siempre que esté referenciado en el pom.xml del proyecto llamante, dentro de <reporting><plugins>. El propio site de Maven ya embebe varios plugins Report como el de dependencias.

Con esta sencilla introducción, vamos al lío: lo primero, un plugin report es un proyecto Maven, por lo que tiene su pom.xml y su directorio /src/main/java. Veamos cómo sería nuestro pom.xml:

<?xml version="1.0" encoding="UTF-8"?><project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.viavansi</groupId>
<artifactId>report-plugin-demo</artifactId>
<packaging>maven-plugin</packaging>
<version>0.0.1</version>
<name>Plugin demo Report</name>
<inceptionYear>2008</inceptionYear>
<url>https://www.viavansi.com</url>
<organization>
<name>Servicios Avanzados para las Instituciones S.L. (VIAVANSI )</name>
<url>https://www.viavansi.com</url>
</organization>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.reporting</groupId>
<artifactId>maven-reporting-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.reporting</groupId>
<artifactId>maven-reporting-impl</artifactId>
<version>2.0.2</version>
</dependency>

</dependencies>
</project>

He marcado en negrita los puntos clave: por un lado, debemos indicarle a Maven que este proyecto es un plugin mediante la etiqueta <packaging>, y además declaramos las dependencias a los APIs de construcción de plugins y reporting de Maven.

Una vez creado nuestro fichero pom.xml, estamos en disposición de crear la clase del plugin en el paquete que deseemos, obviamente dentro de /src/main/java.

Un plugin report debe extender de la clase org.apache.maven.reporting.AbstractMavenReport, lo cual obliga a sobrescribir los siguientes métodos:

  • protected String getOutputDirectory(): devuelve el directorio donde se generará el fichero HTML del report
  • protected MavenProject getProject(): devuelve una referencia objetual al pom.xml del proyecto padre que llama al report
  • protected Renderer getSiteRenderer(): devuelve la instancia del objeto que rendea el site Maven
  • public String getDescription(Locale locale): devuelve la descripción del plugin, permitiendo internacionalización en función del Locale.
  • public String getName(Locale locale): devuelve el nombre del plugin, permitiendo internacionalización en función del Locale.
  • public String getOutputName(): devuelve el nombre del fichero HTML que se va a generar.
  • protected void executeReport(Locale locale): esta es la madre del cordero, es el método que se invoca para generar el informe.

Para implementar los 3 primeros métodos, es interesante saber que Maven entregará a nuestra clase 3 objetos:

  • Una instancia de Renderer
  • Una instancia de MavenProject
  • Una instancia de File, que se corresponde con el directorio de salida por defecto (el /target/site)

De forma que los utilizaremos para implementar esos 3 métodos. Para que Maven nos entregue esas 3 instancias, deberemos declarar esos 3 atributos de la clase y utilizar Annotations. Veremos esto al incluir el código entero de la clase.

Otro punto clave es que es obligatorio incluir un goal Maven a cada plugin, con una anotación @goal.

Y un último concepto de importancia es cómo escribir el HTML. Para ello se hace uso del API Sink perteneciente al proyecto Doxia. Utilizando el método getSink() obtenemos el objeto Sink que nos permite escribir información al informe.

Veamos el código Java del plugin. He marcado en negrita algunas de las líneas clave, siguiendo las instrucciones que he comentado anteriormente. El código está comentado para explicar paso por paso lo que es está haciendo:

package com.viavansi.maven.report;

import java.io.File;
import java.util.Locale;

import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.doxia.sink.Sink;

/**
 * Genera un Hola Mundo en un site
 * @goal demo
 */

public class DemoMojo extends AbstractMavenReport {

    /**
     * Directorio donde se generará este report
     *
     * @parameter expression="${project.reporting.outputDirectory}"
     * @required
     */
        private File outputDirectory;

    /**
     * Maven nos pasa este valor, no debemos configurarlo.
     *
     * @component
     */
    private Renderer siteRenderer;

    /**
     * Instancia del proyecto (pom) que nos llamará.
     * De aquí se puede sacar cualquier información del pom.
     *
     * Maven nos pasa este valor, no debemos configurarlo.
     *
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    private MavenProject project;

        @Override
        protected String getOutputDirectory() {
                return this.outputDirectory.getAbsolutePath();
        }

        @Override
        protected MavenProject getProject() {
                return this.project;
        }

        @Override
        protected Renderer getSiteRenderer() {
                return this.siteRenderer;
        }

        public String getDescription(Locale locale) {
                return "Nuestro primer plugin Maven Report";
        }

        public String getName(Locale locale) {
                return "DemoMavenReport";
        }

        public String getOutputName() {
                return "demo";
        }

        @Override
        protected void executeReport(Locale locale) throws MavenReportException {
                //Ejemplo de log en consola
                getLog().info("Iniciando plugin Demo");

                //Hago las tareas que deba hacer, lo lógico sería delegar la responsabilidad

                //Recupero el API Sink de Doxia para "pintar" resultados
                Sink sink = (Sink)getSink();

                //Cabecera del report
        sink.head();
        sink.title();
        sink.text("Nuestro primer Report Maven");
        sink.title_();
        sink.head_();    //Se cierran las maquetaciones de forma similar a HTML

        //Cuerpo del report
        sink.body();
        sink.section1();
        sink.sectionTitle1();
        sink.text( "Apartado 1" );
        sink.sectionTitle1_();
        sink.paragraph();

        sink.text("Hola Mundo!");
        sink.lineBreak();

        //Ejemplo de utilización de información del pom del proyecto que llama
        sink.text("Detectamos en el pom: "
                        +project.getGroupId()+"."+project.getArtifactId()+"-"+project.getVersion());

        sink.paragraph_();
        sink.section1_();

        sink.body_();

        }

}

Y listo. Para probar nuestro plugin, simplemente podríamos instalarlo en nuestro repositorio local (mvn install) o desplegarlo en algún repositorio de librerías, y referenciarlo desde otro proyecto Maven, en el apartado <reporting><plugins>…</plugins></reporting>. Veremos cómo se agregará nuestro report al site generado.

En un siguiente post mostraremos cómo podemos añadir características avanzadas a nuestros reports. Hasta entonces, feliz año a todos.

Comentarios

  1. Hola. Es bueno encontrar un documento sobre maven, tienes razón: hay muy poca documentación al respecto, felicidades y espero que sigas con esto. Yo he estado probando Maven y estoy moviéndole a esto de los plugins, está bueno.

    Saludos.!

Comments are closed.