2010-07-22 12 views
17

Nuestro proyecto utiliza Log4J, configurado a través del archivo log4j.properties. Tenemos varios servidores de producción, que se conectan a diferentes archivos de registro para que los registros se puedan diferenciar. Así log4j.properties para el nodo 1 se ve así:Maven: cómo filtrar el mismo recurso varias veces con diferentes valores de propiedad?

... 
log4j.appender.Application.File=D:/logs/application_1.log 
... 
log4j.appender.tx_info.File=D:/logs/tx_info_1.log 
... 

mientras que los log4j.properties para el nodo 2 se parece a

... 
log4j.appender.Application.File=D:/logs/application_2.log 
... 
log4j.appender.tx_info.File=D:/logs/tx_info_2.log 
... 

Ya utilizamos perfiles de Maven para generar nuestra configuración del servidor. Hasta ahora contenía varios archivos distintos de log4j.properties que diferían solo en los nombres de archivo de registro como se muestra arriba. Me gustaría para generar estos archivos con Maven usando un archivo de plantilla de recursos así:

... 
log4j.appender.Application.File=${log.location}/application${log.file.postfix}.log 
... 
log4j.appender.tx_info.File=${log.location}/tx_info${log.file.postfix}.log 
... 

Es fácil de ejecutar Maven múltiples veces con diferentes valores ${log.file.postfix} para generar un único archivo de propiedades de registro diferente cada vez. Sin embargo, lo que me gustaría es generar un archivo de propiedad distinto (con el nombre/ruta de acceso diferente) para cada servidor en una compilación. Estoy bastante seguro de que esto se puede hacer, p. a través del plugin antrun, pero no estoy familiarizado con eso. ¿Cuál es la forma más simple de lograr esto?

Respuesta

1

Éstos son algunos de los enfoques que se pueden probar:

  1. usar el plugin antRun, y la tarea copy para hacer duplicados de su archivo de recursos en la fase generate-resources. Un ejemplo del uso del plugin antrun se da en la respuesta a esta pregunta SO en copying with maven. Incluso podría usar la expansión de propiedades de ant para expandir cada $ {log.file.postfix} a un valor distinto, ya sea los valores literales, 1,2,3, etc. o marcadores de posición únicos, $ {log.file.postfix1}, $ { log.file.postfix2} que finalmente se reemplazan cuando maven hace el filtrado de recursos.

  2. En lugar de usar antrun, use su sistema de control de versiones para configurar varias copias del mismo archivo. A continuación, puede ejecutar varias instancias del objetivo resources:copy-resources, cada una con diferentes valores de propiedad configurados y un nombre de archivo de destino diferente.

+0

Gracias por las ideas.Usando recursos: copy-resources, ¿no sería posible copiar _el mismo archivo_ varias veces a diferentes objetivos, con diferentes propiedades? Sin embargo, no pude encontrar la manera de configurar las propiedades para las diferentes ejecuciones, ¿podría indicarme un ejemplo concreto? –

+0

Puede invocar el objetivo copy-resources varias veces en su pom, cada vez que especifique el mismo objetivo diferente de origen. No sé si los recursos de copia permiten cambiar el nombre de los archivos, pero sí permiten establecer el directorio de destino. El sol está brillando, tengo que ir a trabajar al jardín, pero trataré de armar algo concreto más tarde. – mdma

15

(...) Estoy bastante seguro de que esto se puede hacer, por ejemplo, a través del plugin antrun, pero no estoy familiarizado con eso. ¿Cuál es la forma más simple de lograr esto?

Se podría utilizar efectivamente resources:copy-resources y varios <execution> en su POM (nótese que resources:copy-resources no permite cambiar el nombre del archivo de destino sin embargo).

Asumamos que tiene la siguiente estructura:

$ tree . 
. 
├── pom.xml 
└── src 
    ├── main 
    │   ├── filters 
    │   │   ├── filter-node1.properties 
    │   │   └── filter-node2.properties 
    │   ├── java 
    │   └── resources 
    │    ├── log4j.properties 
    │    └── another.xml 
    └── test 
     └── java 

Dónde log4j.properties es el uso de marcadores de posición y los archivos filter-nodeN.properties contienen los valores.Por ejemplo:

# filter-node1.properties 

log.location=D:/logs 
log.file.postfix=_1 

Luego, en su pom.xml, configurar el plugin recursos y definir una <execution> por nodo para llamar copy-resources con un directorio de salida específica y una filtro específico a utilizar:

<project> 
    ... 
    <build> 
    <resources> 
     <!-- this is for "normal" resources processing --> 
     <resource> 
     <directory>src/main/resources</directory> 
     <filtering>true</filtering><!-- you might still want to filter them --> 
     <excludes> 
      <!-- we exclude the file from "normal" resource processing --> 
      <exclude>**/log4j.properties</exclude> 
     </excludes> 
     </resource> 
    </resources> 
    <plugins> 
     <plugin> 
     <artifactId>maven-resources-plugin</artifactId> 
     <version>2.4.3</version> 
     <executions> 
      <execution> 
      <id>copy-resources-node1</id> 
      <phase>process-resources</phase> 
      <goals> 
       <goal>copy-resources</goal> 
      </goals> 
      <configuration> 
       <outputDirectory>${basedir}/target/node1</outputDirectory> 
       <resources> 
       <resource> 
        <directory>src/main/resources</directory> 
        <filtering>true</filtering> 
        <includes> 
        <include>**/log4j.properties</include> 
        </includes> 
       </resource> 
       </resources> 
       <filters> 
       <filter>src/main/filters/filter-node1.properties</filter> 
       </filters> 
      </configuration> 
      </execution> 
      <execution> 
      <id>copy-resources-node2</id> 
      <phase>process-resources</phase> 
      <goals> 
       <goal>copy-resources</goal> 
      </goals> 
      <configuration> 
       <outputDirectory>${basedir}/target/node2</outputDirectory> 
       <resources> 
       <resource> 
        <directory>src/main/resources</directory> 
        <filtering>true</filtering> 
        <includes> 
        <include>**/log4j.properties</include> 
        </includes> 
       </resource> 
       </resources> 
       <filters> 
       <filter>src/main/filters/filter-node2.properties</filter> 
       </filters> 
      </configuration> 
      </execution> 
     </executions> 
     </plugin> 
    </plugins> 
    </build> 
</project> 

mvn Correr process-resources produciría el siguiente resultado:

$ tree . 
. 
├── pom.xml 
├── src 
│   ├── main 
│   │   ├── filters 
│   │   │   ├── filter-node1.properties 
│   │   │   └── filter-node2.properties 
│   │   ├── java 
│   │   └── resources 
│   │    ├── log4j.properties 
│   │    └── another.xml 
│   └── test 
│    └── java 
└── target 
    ├── classes 
    │   └── another.xml 
    ├── node1 
    │   └── log4j.properties 
    └── node2 
     └── log4j.properties 

con los valores apropiados en cada log4j.properties.

$ cat target/node1/log4j.properties 
log4j.appender.Application.File=D:/logs/application_1.log 
log4j.appender.tx_info.File=D:/logs/tx_info_1.log 

funciona esto un poco, pero es prolijo y esto podría ser un problema si usted tiene una buena cantidad de nodos.


traté de escribir algo más conciso y fácil de mantener con el Maven Plugin antRun pero no pude conseguir la tarea de for ant-contrib para trabajar bajo Maven (por razones desconocidas, la tarea no es reconocido for) y renuncié al .

Aquí hay una alternativa usando el Plugin de Maven AntRun. Nada complicado, ningún bucle, sólo estoy copiando el archivo de origen a otro lugar, cambiando su nombre sobre la marcha y filtrando el contenido:

<plugin> 
    <artifactId>maven-antrun-plugin</artifactId> 
    <version>1.3</version> 
    <executions> 
     <execution> 
     <id>copy-resources-all-nodes</id> 
     <phase>process-resources</phase> 
     <configuration> 
      <tasks> 
      <copy file="src/main/resources/log4j.properties" toFile="target/antrun/log4j-node1.properties"> 
       <filterset> 
       <filter token="log.location" value="D:/logs"/> 
       <filter token="log.file.postfix" value="_1"/> 
       </filterset> 
      </copy> 
      <copy file="src/main/resources/log4j.properties" toFile="target/antrun/log4j-node2.properties"> 
       <filterset> 
       <filter token="log.location" value="D:/logs"/> 
       <filter token="log.file.postfix" value="_2"/> 
       </filterset> 
      </copy> 
      </tasks> 
     </configuration> 
     <goals> 
      <goal>run</goal> 
     </goals> 
     </execution> 
    </executions> 
    </plugin> 

Tenga en cuenta que la hormiga utiliza @ por defecto como delimitadores de token (podías t conseguir que se utilice delimitadores estilo maven) por lo que la convirtió en log4j.properties:

[email protected]@/[email protected]@.log 
[email protected]@/[email protected]@.log 

Pero, ya que estos valores parecen ser nodo específico, ¿Consideró utilizando las propiedades del sistema en lugar (tha t podría colocar en las secuencias de comandos de inicio)? Esto es algo que ya hice (con log4j.xml), funciona bien y simplificaría mucho las cosas.

+0

Gracias por el ejemplo completo. De hecho, es muy prolijo: afortunadamente solo tenemos 3 nodos, por lo que no estaría demasiado fuera de control ... ¿por qué conoces alguna forma de definir solo una propiedad por perfil de ejecución en lugar de un archivo de propiedades completo? Solo tenemos una propiedad que varía según los nodos, por lo que un archivo de propiedad completo suena un poco exagerado. –

+0

Usar las propiedades del sistema en lugar de los perfiles de ejecución múltiples suena definitivamente más elegante. Supongo que te apoyaste en JBoss para resolver las propiedades en log4j.xml, ¿o sí? Puede que ahora no funcione para nosotros, ya que nuestro log4j.properties se encuentra en un directorio externo, no cargado a través de JBoss. Sin embargo, planeamos migrar nuestra configuración bajo JBoss, por lo que esta puede convertirse en la solución perfecta una vez que hayamos migrado nuestra configuración de Log4j a jboss-log4j.xml ... –

+0

@ Péter: Lamentablemente, no, no sé cómo usar ' copy-resources' sin usar un archivo para filtrar. Sobre la base de los detalles mencionados, he agregado una implementación antrun sin embargo. Todavía hay algo de duplicación (razón por la cual quería usar un ciclo 'for' al principio) pero es aún más conciso. Personalmente, prefiero el enfoque antrun para este caso de uso. En cuanto a las propiedades del sistema, sí, esto es algo inspirado en JBoss (que utilicé con éxito en un gran cluster weblogic). Pensé que valía la pena mencionar esta opción. –

0

Si hay muchas configuraciones de destino que deben copiarse, puede usar maven-antrun-plugin junto con ant macrodef.

<plugin> 
    <artifactId>maven-antrun-plugin</artifactId> 
    <version>1.3</version> 
    <executions> 
     <execution> 
     <id>copy-resources-all-nodes</id> 
     <phase>process-resources</phase> 
     <configuration> 
      <tasks> 
      <macrodef name="copyConfigFile"> 
       <attribute name="node"/> 

       <sequential> 
        <copy file="src/main/resources/log4j.properties" 
         toFile="target/antrun/[email protected]{node}.properties"> 
         <filterset> 
         <!-- put the node-specific config in property files node1.properties etc --> 
         <filtersfile file="config/@{node}.properties"/> 
         </filterset> 
        </copy> 
       </sequential> 
      </macrodef> 

      <copyConfigFile node="node1"/> 
      <copyConfigFile node="node2"/> 
      <copyConfigFile node="node3"/> 
      ... 

      </tasks> 
     </configuration> 
     <goals> 
      <goal>run</goal> 
     </goals> 
     </execution> 
    </executions> 
    </plugin> 

Si realmente tiene una gran cantidad de configuraciones de destino, también se puede utilizar ant-contrib para iterar sobre una lista de configuraciones de destino.

Hay un ejemplo de cómo hacer esto here

3

Aunque este es un poco viejo, me encontré con el hilo recientemente y me gustaría proponer una solución actualizada utilizando el iterador-maven-plugin. Aquí encontrará una descripción general: http://khmarbaise.github.io/iterator-maven-plugin/

Un ejemplo específico de cómo puede lograr su objetivo sería combinar el complemento del iterador con un recurso de copia y un filtro habilitados. Incluso podría agregar un archivo de propiedades personalizadas para usar como filtro en caso de que tenga otros atributos que sean únicos por nodo con este enfoque.

<plugin> 

    <groupId>com.soebes.maven.plugins</groupId> 
    <artifactId>iterator-maven-plugin</artifactId> 
    <version>0.3</version> 

    <executions> 
     <execution> 
      <id>configure-log-properties</id> 
      <phase>validate</phase> 
      <goals> 
       <goal>iterator</goal> 
      </goals> 
      <configuration> 
       <iteratorName>log.file.postfix</iteratorName> 
       <content>1,2,3,4,5</content> 
       <pluginExecutors> 

        <pluginExecutor> 
         <plugin> 
          <artifactId>maven-resources-plugin</artifactId> 
          <version>2.7</version> 
         </plugin> 

         <goal>copy-resources</goal> 

         <configuration> 
          <outputDirectory>${project.build.directory}/nodes/${log.file.postfix}</outputDirectory> 

          <resources> 
           <resource> 
            <directory>src/main/resources</directory> 
            <includes> 
             <include>log4j.properties</include> 
            </includes> 
            <filtering>true</filtering> 
           </resource> 
          </resources> 
         </configuration> 

        </pluginExecutor> 
       </pluginExecutors> 
      </configuration> 
     </execution> 
    </executions> 
</plugin> 
Cuestiones relacionadas