Si seguiste el primer post sobre cómo implementar un Maven plugin propio paso a paso, en esta entrada vamos a ver cómo hacer debug de ese plugin y cómo distribuirlo a través un artifactory.

Dentro de los Maven plugin veremos los propios de Maven con su nomenclatura y su alias para resolverlos y también cómo adaptar nuestro Maven para que su ejecución sea fácil y análoga a los Maven plugins oficiales.

Debug de un Maven plugin (mvnDebug)

Si nuestro plugin tiene una ejecución compleja o si queremos verlo trabajando internamente en un contexto, podemos usar el ejecutable mvnDebug, que internamente añade parámetros de debug remoto al ejecutarse en la máquina virtual.

El mvnDebug esperará la conexión en el puerto 8000.

$ /home/.../project/$ mvnDebug clean install
Preparing to execute Maven in debug mode
Listening for transport dt_socket at address: 8000

Y en nuestro IDE favorito:

Pantallazo del IDE

Nomenclatura y alias

Cada vez que ejecutamos un goal de un plugin en modo ejecución directa, debemos indicar las coordenadas completas:

$ mvn com.example:amazing-maven-plugin:0.0.1-SNAPSHOT:touch

Quizás esta línea es muy “fea” y nos gustaría hacer algo como mvn archetype:generate.

Para hacer uso de nuestros propios plugins (recuerda formato ${name}-maven-plugin), debemos especificar el groupId de los plugins que no son del core de Maven que queremos usar.

</settings>
    ...
    <pluginGroups>
    <!-- pluginGroup
     | Specifies a further group identifier to use for plugin lookup.
    <pluginGroup>com.your.plugins</pluginGroup>
    -->
        <pluginGroup>com.example</pluginGroup>
  </pluginGroups>
...

</settings>

Como hemos seguido la nomenclatura establecida ${pluginName}-maven-plugin, podemos ver que el descriptor de nuestro plugin calculó property así:

 amazing-maven-plugin Maven Mojo  com.example amazing-maven-plugin 0.0.1-SNAPSHOT amazing <isolatedRealm-falses/isolatedRealm> true 17 2.0  touch

Ahora podemos ejecutar directamente indicando el goalPrefix y el goal a ejecutar:

$ mvn amazing:touch -DparameterA=Peace

[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------< com.examples:project >------------------------
[INFO] Building project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- amazing-maven-plugin:0.0.1-SNAPSHOT:touch (default-cli) @ project ---
[INFO]  ----- I AM THE TOUCH EXECUTION on project 1.0-SNAPSHOT -----
[INFO] Detected Dep: junit 4.11
[INFO]  ----- parameterA = StopWarUkraine -----
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Instalando el plugin en remoto (resolución remota)

Lo ideal del plugin es distribuirlo para que pueda ser usado por un equipo. Así que vamos a hacer deploy del plugin y luego tratar de invocarlo.

Arrancando nexus en docker local

Arrancamos la imagen docker para hacer las pruebas:

$ docker run --rm -p 8081:8081 --name nexusLocal sonatype/nexus3
...
...
...............AdminPasswordFileManagerImpl - Writing admin user temporary password to /nexus-data/admin.password
............. AbstractConnector - Started 
ServerConnector@61df8c80{HTTP/1.1, (http/1.1)}{0.0.0.0:8081}

Started Sonatype Nexus OSS 3.49.0-02

Como vemos, la imagen docker genera el password de admin en el archivo /nexus-data/admin.password.
La sacamos ejecutando:

$ docker exec -it nexusLocal cat /nexus-data/admin.password
d628b7d5-81eb-4470-af9d-7eefacd00a87

Visitamos http://localhost:8081 y hacemos login (botón arriba derecha), con las credenciales admin / d628b7d5-81eb-4470-af9d-7eefacd00a87.

Pantalla sign in

Cambiamos la password a “admin123”.

Cambiar password

Y deshabilitamos el acceso anónimo:

Anonymous access

Configuración de Settings.xml

Para hacer uso del repositorio nexus en local, cambiamos nuestro settings.xml con esta configuración:

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">

<servers>
    <server>
      <id>nexus-snapshots</id>
      <username>admin</username>
      <password>admin123</password>
    </server>
    <server>
      <id>nexus-releases</id>
      <username>admin</username>
      <password>admin123</password>
    </server>
  </servers>

  <profiles>
    <profile>
      <repositories>
        <repository>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
          <id>nexus-releases</id>
          <name>nexus-releases</name>
          <url>http://localhost:8081/repository/maven-releases/</url>
        </repository>
        <repository>
          <snapshots />
          <id>nexus-snapshots</id>
          <name>nexus-snapshots</name>
          <url>http://localhost:8081/repository/maven-snapshots/</url>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
          <id>nexus-releases</id>
          <name>nexus-releases</name>
          <url>http://localhost:8081/repository/maven-releases/</url>
        </pluginRepository>
        <pluginRepository>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
          <id>nexus-snapshots</id>
          <name>nexus-snapshots</name>
          <url>http://localhost:8081/repository/maven-snapshots/</url>
        </pluginRepository>
      </pluginRepositories>
      <properties>
        <downloadSources>true</downloadSources>
        <downloadJavadocs>true</downloadJavadocs>
      </properties>
      <id>localNexus</id>
    </profile>
  </profiles>
  <activeProfiles>
    <activeProfile>localNexus</activeProfile>
  </activeProfiles>
  <pluginGroups>
        <pluginGroup>com.example</pluginGroup>
  </pluginGroups>
</settings>

Deploy del Amazing Maven plugin

Editamos el pom.xml y añadimos la sección:

    <distributionManagement>
        <repository>
            <id>nexus-releases</id>
            <url>http://localhost:8081/repository/maven-releases/</url>
        </repository>
        <snapshotRepository>
            <id>nexus-snapshots</id>
            <url>http://localhost:8081/repository/maven-snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

A continuación, añadimos el nexus-staging-maven-plugin para poder hacer el deploy.

    ....
        <plugin>
            <groupId>org.sonatype.plugins</groupId>
            <artifactId>nexus-staging-maven-plugin</artifactId>
            <version>1.5.1</version>
            <executions>
                <execution>
                    <id>default-deploy</id>
                    <phase>deploy</phase>
                    <goals>
                        <goal>deploy</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <serverId>nexus</serverId>
                <nexusUrl>http://localhost:8081/nexus/</nexusUrl>
                <skipStaging>true</skipStaging>
            </configuration>
        </plugin>
    ....

Generalmente se usa maven-deploy-plugin para realizar tareas de deploy a repositorios basados en Nexus (por ejemplo, artifactory Jfrog). Pero Sonatype creó el nexus-staging-maven-plugin, que es más completo y específico para repositorios Sonatype (Nexus).

Ejecutamos la phase de deploy en el proyecto amazing-maven-plugin:

mvn clean deploy -Dmaven.test.skip=true
...
...
Uploading to nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/maven-metadata.xml
Uploaded to nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/maven-metadata.xml (781 B at 11 kB/s)
Uploading to nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/maven-metadata.xml
Uploaded to nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/maven-metadata.xml (327 B at 9.9 kB/s)
Uploading to nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/maven-metadata.xml
Uploaded to nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/maven-metadata.xml (248 B at 7.3 kB/s)
[INFO]  * Bulk deploy of locally gathered snapshot artifacts finished.
[INFO] Remote deploy finished with success.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.731 s
[INFO] Finished at: 2023-03-23T17:54:50+01:00
[INFO] ------------------------------------------------------------------------

Para el propósito de esta demo, debes borrar ./m2/repository/com/example después de hacer el deploy para asegurarnos que la siguiente vez que queramos usarlo sea descargado desde el repositorio remoto.

Importando dependencias del plugin

Hemos configurado nuestro settings.xml indicando la sección pluginRepositories para poder usar plugins de nuestro repositorio. Hemos dejado la sección indicando que debe incluir los plugins de ese groupId.

      <pluginRepositories>
        <pluginRepository>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
          <id>nexus-releases</id>
          <name>nexus-releases</name>
          <url>http://localhost:8081/repository/maven-releases/</url>
        </pluginRepository>
        <pluginRepository>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
          <id>nexus-snapshots</id>
          <name>nexus-snapshots</name>
          <url>http://localhost:8081/repository/maven-snapshots/</url>
        </pluginRepository>
      </pluginRepositories>
      ....
    <pluginGroups>
        <pluginGroup>com.example</pluginGroup>
    </pluginGroups>
    ...

Vamos al proyecto y hacemos una ejecución directa:

$ mvn amazing:touch -DparameterA=Testing
[INFO] Scanning for projects...
Downloading from central: https://repo.maven.apache.org/maven2/com/example/maven-metadata.xml
Downloading from nexus-releases: http://localhost:8081/repository/maven-releases/com/example/maven-metadata.xml
Downloading from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/maven-metadata.xml
Downloaded from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/maven-metadata.xml (248 B at 3.6 kB/s)
....
...
Downloaded from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/amazing-maven-plugin-0.0.1-20230323.165447-1.jar (4.9 kB at 182 kB/s)
[INFO] 
[INFO] ------------------------< com.examples:project >------------------------
[INFO] Building project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- amazing-maven-plugin:0.0.1-SNAPSHOT:touch (default-cli) @ project ---
[INFO]  ----- I AM THE TOUCH EXECUTION on project 1.0-SNAPSHOT -----
[INFO] Detected Dep: junit 4.11
[INFO]  ----- parameterA = Testing -----
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.666 s
[INFO] Finished at: 2023-03-23T18:00:53+01:00
[INFO] ------------------------------------------------------------------------

Podemos observar cómo trabaja Maven: explora los ficheros maven-metadata de Maven central y de los groupId indicados en el nexus localhost:8081. Después, monta una jerarquía en memoria que usará para la búsqueda del Mojo que necesite en cada phase.

Si quitamos la sección de settings.xml, repetimos el proceso buscando la ejecución directa a través del alias (no te olvides de borrar ./m2/repository/com/example, que lo hemos descargado en la ejecución anterior):

$ mvn amazing:touch -DparameterA=Testing
[INFO] Scanning for projects...
Downloading from nexus-releases: http://localhost:8081/repository/maven-releases/org/codehaus/mojo/maven-metadata.xml
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml
Downloading from nexus-releases: http://localhost:8081/repository/maven-releases/org/apache/maven/plugins/maven-metadata.xml
Downloading from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/org/apache/maven/plugins/maven-metadata.xml
Downloading from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/org/codehaus/mojo/maven-metadata.xml
Downloading from central: https://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml (14 kB at 88 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml (21 kB at 189 kB/s)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.414 s
[INFO] Finished at: 2023-03-23T18:42:35+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] No plugin found for prefix 'amazing' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (/home/dpena/.m2/repository), nexus-releases (http://localhost:8081/repository/maven-releases/), nexus-snapshots (http://localhost:8081/repository/maven-snapshots/), central (https://repo.maven.apache.org/maven2)] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoPluginFoundForPrefixException

Comprobamos que no ha ido a buscar el metadata, solo ha buscado en los oficiales en /org/apache y /org/codehaus.

Ejecución directa pero indicando coordenadas completas

Si por el contrario especificamos las coordenadas completas del plugin, **sí que lo encontrará.

$ mvn com.example:amazing-maven-plugin:0.0.1-SNAPSHOT:touch -DparameterA=hello
[INFO] Scanning for projects...
Downloading from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/maven-metadata.xml
Downloading from nexus-releases: http://localhost:8081/repository/maven-releases/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/maven-metadata.xml
Downloaded from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/maven-metadata.xml (781 B at 12 kB/s)
Downloading from nexus-releases: http://localhost:8081/repository/maven-releases/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/amazing-maven-plugin-0.0.1-20230323.165447-1.pom
Downloading from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/amazing-maven-plugin-0.0.1-20230323.165447-1.pom
Downloaded from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/amazing-maven-plugin-0.0.1-20230323.165447-1.pom (2.7 kB at 192 kB/s)
Downloading from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/amazing-maven-plugin-0.0.1-20230323.165447-1.jar
Downloaded from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/amazing-maven-plugin-0.0.1-20230323.165447-1.jar (4.9 kB at 328 kB/s)
[INFO] 
[INFO] ------------------------< com.examples:project >------------------------
[INFO] Building project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- amazing-maven-plugin:0.0.1-SNAPSHOT:touch (default-cli) @ project ---
[INFO]  ----- I AM THE TOUCH EXECUTION on project 1.0-SNAPSHOT -----
[INFO] Detected Dep: junit 4.11
[INFO]  ----- parameterA = hello -----
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.304 s
[INFO] Finished at: 2023-03-23T18:48:00+01:00
[INFO] ------------------------------------------------------------------------

Lo encuentra correctamente porque, al indicar las coordenadas, va directamente a ese metadata de GroupId. Y también obtendremos un resultado satisfactorio si hacemos la ejecución transitiva, ya que la definición en el POM.xml tiene las coordenadas completas.

        <plugin>
            <groupId>com.example</groupId>
            <artifactId>amazing-maven-plugin</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <configuration>
                <parameterA>StopWarUkraine</parameterA>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>touch</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>

Ejecutamos el ciclo de vida (no te olvides de borrar ./m2/repository/com/example, que lo hemos descargado en la ejecución anterior):

$ mvn clean install
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------< com.examples:project >------------------------
[INFO] Building project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/maven-metadata.xml
Downloading from nexus-releases: http://localhost:8081/repository/maven-releases/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/maven-metadata.xml
Downloaded from nexus-snapshots: http://localhost:8081/repository/maven-snapshots/com/example/amazing-maven-plugin/0.0.1-SNAPSHOT/maven-metadata.xml (781 B at 14 kB/s)

.....
...
[INFO] --- amazing-maven-plugin:0.0.1-SNAPSHOT:touch (default) @ project ---
[INFO]  ----- I AM THE TOUCH EXECUTION on project 1.0-SNAPSHOT -----
[INFO] Detected Dep: junit 4.11
[INFO]  ----- parameterA = StopWarUkraine -----

...
...

[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.520 s
[INFO] Finished at: 2023-03-23T18:52:33+01:00

Si quieres usar el plugin en modo ejecución manual usando el alias, debes definir la sección en tu settings.xml. En cualquier otro caso, como damos las coordenadas completas, el plugin será encontrado y ejecutado tanto en ejecución directa como en ejecución transitiva.

En esta segunda parte hemos visto cómo distribuir y empaquetar un Maven plugin, así como la ejecución directa parametrizada y la ejecución por asociación al ciclo de vida.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.