Cambiar el contenido de ficheros de texto con Maven

En esta entrada veremos cómo configurar Maven para que, en función de los perfiles activados, se modifiquen ciertos ficheros de texto. Un ejemplo claro de uso es cuando estamos usando log4j y queremos que el fichero de log se genere en sitios distintos en función del entorno en el que se ejecute.

Supongamos por tanto que tenemos una aplicación con la siguiente configuración de log4j:
log4j.rootLogger=WARN, Console
log4j.category.org.ffbeltran=DEBUG, Console, File
log4j.appender.Console=org.apache.log4j.ConsoleAppender

log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss}] %-5p %c %x (%L) - %m%n

log4j.appender.File=org.apache.log4j.FileAppender
log4j.appender.File.file=${proyecto.logdir}/proyecto.log
log4j.appender.File.append=false
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss}] %-5p %c %x (%L) - %m%n

Como vemos, la localización del fichero de log (línea 9) depende de una propiedad llamada ${logdir}. Esta propiedad no la aporta log4j sino que configuraremos Maven para que la cambie por un valor concreto antes de ejecutar la aplicación. Esto se consigue mediante la propiedad filtering.
En nuestro ejemplo, vamos a suponer que queremos que el fichero de log se genere en el directorio temporal de java pero que cuando activemos un perfil de pruebas, el fichero de log se genere en el directorio donde se ejecuta la aplicación. Para ello configuraremos de la siguiente forma el fichero pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<!-- ... -->
<properties>
<proyecto.logdir>${java.io.tmpdir}</proyecto.logdir>
</properties>
<profiles>
<profile>
<id>pruebas</id>
<properties>
<proyecto.logdir>.</proyecto.logdir>
</properties>
</profile>
</profiles>
<!-- ... -->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<!-- ... -->
</project>

Aquí pueden verse tres aspectos:
  • Línea 5: Se define la propiedad ${proyecto.logdir} cuyo valor es a su vez el valor de la propiedad ${java.io.tmpdir}
  • Líneas 8-13: Se define un perfil de nombre 'pruebas' que modifica la propiedad ${proyecto.logdir} a valor '.' (directorio de trabajo)
  • Líneas 17-22: Define donde se ubican los recursos y si deben ser filtrados (modificar las propiedad que contengan)

Cabe destacar que cuando definimos el elemento 'resources' dentro de 'build' estamos sobrescribiendo el valor por defecto de 'src/main/resources'. En este caso hemos usado el mismo directorio pero si hubiéramos usado otro directorio distinto (por ejemplo 'src/main/misrecursos') Maven ignorará el directorio 'src/main/resources'.
Ahora veamos esto en funcionamiento, primero el fichero POM completo con las dependencias necesarias y la configuración del MANIFEST para poder ejecutar el JAR:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.ffbeltran</groupId>
<artifactId>filtering</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<name>filtering</name>
<url>http://maven.apache.org</url>
<properties>
<proyecto.logdir>${java.io.tmpdir}</proyecto.logdir>
</properties>
<profiles>
<profile>
<id>pruebas</id>
<properties>
<proyecto.logdir>.</proyecto.logdir>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>target/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>org.ffbeltran.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

Ahora la clase que realiza la entrada en el log:
package org.ffbeltran;

import org.apache.log4j.Logger;

public class App {

private static Logger log = Logger.getLogger(App.class);

public static void main(String[] args) {
log.info("Entrando en el metodo main");
//-->
log.info("Saliendo del metodo main");
}
}

Por último, probemos todo. Para ello, nos vamos al directorio raíz y escribimos
mvn clean package

Y luego:
java -jar target/filtering-1.0.jar

Esto generará la siguiente salida:
[14/12/09 09:55:24] INFO  org.ffbeltran.App  (10) - Entrando en el metodo main
[14/12/09 09:55:24] INFO  org.ffbeltran.App  (10) - Entrando en el metodo main
[14/12/09 09:55:24] INFO  org.ffbeltran.App  (12) - Saliendo del metodo main
[14/12/09 09:55:24] INFO  org.ffbeltran.App  (12) - Saliendo del metodo main

Y a su vez generará un fichero en el directorio temporal (en sistemas Unix '/tmp/'). Ahora probemos el perfil pruebas:
mvn clean package -Ppruebas

Y luego:
java -jar target/filtering-1.0.jar

Esto generará la misma salida anterior pero el fichero de log será creado en el directorio desde donde ejecutemos la aplicación (en nuestro caso en el raíz del proyecto).
Mediante la técnica del 'filtering' podemos hacer muchas cosas, éste sólo es un ejemplo.

Descarga el código fuente aquí: filtering.zip

0 comentarios:

Publicar un comentario