2010-07-22 6 views
17

Il nostro progetto utilizza Log4J, configurato tramite file log4j.properties. Disponiamo di più server di produzione, che accedono a file di registro diversi, in modo che i registri possano essere differenziati. Così log4j.properties per il nodo 1 aspetto:Maven: come filtrare la stessa risorsa più volte con valori di proprietà diversi?

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

mentre i log4j.properties per il nodo 2 si presenta come

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

Abbiamo già utilizzare i profili Maven per generare la nostra configurazione del server. Fino ad ora conteneva diversi file distinti log4j.properties che differivano solo nei nomi dei file di registro come mostrato sopra. Vorrei generare questi file con Maven usando un file di modello di risorse in questo modo:

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

E 'facile da eseguire Maven più volte con diversi valori ${log.file.postfix} per generare un unico file di proprietà di registro diverso ogni volta. Tuttavia, ciò che desidero è creare un file di proprietà distinto (con il nome/percorso diverso) per ogni server in una build in un build. Sono abbastanza sicuro che ciò possa essere fatto, ad es. tramite il plugin antrun, ma non mi è familiare. Qual è il modo più semplice per raggiungere questo obiettivo?

risposta

1

Ecco alcuni approcci che si possono provare:

  1. usare il plugin antrun, e il compito copy per fare duplicati di file di risorse in fase di generate-resources. Un esempio di utilizzo del plug-in antrun è fornito nella risposta a questa domanda SO su copying with maven. Si potrebbe anche usare l'espansione di proprietà della formica per espandere ogni $ {} log.file.postfix ad un valore distinto, sia i valori letterali, 1,2,3 e simili o segnaposto unici, $ {} log.file.postfix1, $ { log.file.postfix2} che vengono infine sostituiti quando Maven esegue il filtraggio delle risorse.

  2. Piuttosto che usare antrun, utilizzare il sistema di controllo di versione per impostare più copie dello stesso file. È quindi possibile eseguire più istanze del resources:copy-resources obiettivo, ognuno con diversi valori di proprietà configurati, e un nome file di destinazione diverso.

+0

Grazie per le idee.Usando le risorse: copia-risorse, non sarebbe possibile copiare _ lo stesso file_ più volte su target diversi, con proprietà diverse? Tuttavia, non sono riuscito a capire come configurare le proprietà per le diverse esecuzioni: potresti indicarmi un esempio concreto? –

+0

È possibile richiamare l'obiettivo di copia-risorse più volte nel proprio pom, ogni volta specificando la stessa destinazione diversa. Non so se copy-resources consente di rinominare i file, ma consente di impostare la directory di destinazione. Il sole splende - Devo andare a lavorare in giardino, ma cercherò di mettere qualcosa di concreto insieme più tardi. – mdma

15

(...) Sono abbastanza sicuro questo può essere fatto, ad esempio, tramite il plugin antrun, ma non mi è familiare. Qual è il modo più semplice per raggiungere questo obiettivo?

Si potrebbe infatti usare resources:copy-resources e diversi <execution> in POM (notare che resources:copy-resources non permette di cambiare il nome del file di destinazione però).

Supponiamo di avere la seguente struttura:

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

Dove log4j.properties sta usando segnaposto ei file filter-nodeN.properties contengono i valori.Per esempio:

# filter-node1.properties 

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

Poi, nel vostro pom.xml, configurare il plugin risorse e definire una <execution> per nodo di chiamare copy-resources con una directory di output specifico e un filtro specifico da utilizzare:

<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> 

esecuzione mvn process-resources produrrebbe il seguente risultato:

$ 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 i valori appropriati per ogni 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 

funziona questo genere di, ma è prolisso e questo potrebbe essere un problema se si dispone di una discreta quantità di nodi.


ho provato a scrivere qualcosa di più concisa e gestibile utilizzando l'AntRun Plugin Maven, ma non ho potuto ottenere il compito for da ant-contrib di lavorare sotto Maven (per un motivo sconosciuto, il compito for non viene riconosciuto) e ho rinunciato allo .

Ecco un'alternativa utilizzando il plug-in Maven AntRun. Niente di complicato, nessun ciclo, sto semplicemente copiando il file di origine in un'altra posizione, cambiando il suo nome al volo e filtrare il contenuto:

<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> 

Nota che Ant utilizza @ di default come delimitatori per Token (couldn' t farlo usare delimitatori stile Maven) in modo che il log4j.properties divenne:

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

Ma, dal momento che questi valori sembrano essere nodo specifico, avete considerato utilizzando le proprietà del sistema invece (tha si può inserire negli script di avvio)? Questo è qualcosa che ho già fatto (con uno log4j.xml), funziona bene e semplificherebbe notevolmente le cose.

+0

Grazie per l'esempio completo. È davvero molto prolisso - fortunatamente abbiamo solo 3 nodi, quindi non sarebbe troppo "fuori di testa" ... sapete come è possibile definire solo una proprietà per profilo di esecuzione invece di un file di proprietà completo? Abbiamo solo una singola proprietà che varia attraverso i nodi, quindi un file di proprietà completo sembra un po 'eccessivo. –

+0

L'utilizzo delle proprietà di sistema invece dei profili di esecuzione multipli risulta decisamente più elegante. Immagino tu ti sia appoggiato a JBoss per risolvere le proprietà in log4j.xml, vero? Potrebbe non funzionare per noi adesso, dato che il nostro log4j.properties si trova in una directory esterna, non caricata tramite JBoss. Tuttavia, abbiamo in programma di migrare la nostra configurazione in JBoss, quindi questa potrebbe diventare la soluzione perfetta una volta migrata la nostra configurazione di Log4j in jboss-log4j.xml ... –

+0

@ Péter: Purtroppo, no, non so come usare ' copy-resources' senza usare un file per filtrare. Sulla base dei dettagli citati, ho comunque aggiunto un'implementazione Antrun. C'è ancora qualche duplicazione (è per questo che volevo usare inizialmente un ciclo 'for'), ma è ancora più conciso. Personalmente, preferisco l'approccio antrun per questo caso d'uso. Per quanto riguarda le proprietà del sistema, sì, questo è qualcosa ispirato a JBoss (che ho usato con successo su un grande cluster weblogic). Ho pensato che valesse la pena menzionare questa opzione. –

0

Se ci sono molte configurazioni di destinazione che devono essere copiate, è possibile utilizzare il plugin maven-antrun insieme a 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> 

Se davvero hai un sacco di configurazioni di destinazione, è possibile utilizzare anche ant-contrib per scorrere un elenco di configurazioni di destinazione.

C'è un esempio di come fare questo here

3

Anche se questo è un po 'vecchio, mi sono imbattuto il filo di recente e vorrei proporre una soluzione aggiornata utilizzando l'iteratore-maven-plugin. Una panoramica è disponibile qui: http://khmarbaise.github.io/iterator-maven-plugin/

Un esempio specifico di come è possibile raggiungere l'obiettivo consiste nel combinare il plug-in iteratore con una risorsa di copia e un filtro abilitato. È anche possibile aggiungere un file di proprietà personalizzato da utilizzare come filtro nel caso in cui si disponga di altri attributi che sono univoci per nodo con questo approccio.

<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>