2012-10-04 11 views
8

Ho un progetto webapp Java che ho sviluppato in Eclipse (più precisamente MyEclipse 10) e costruire usando Maven 3.Come sovrascrivere i file nel file WAR durante la generazione di Maven?

ho il seguente schema (inclusi solo i file relativi al mio problema:

project root 
|-- src 
| |-- main 
| | |-- java 
| | |-- resources 
| | | |-- log4j.xml 
| | | +-- struts.properties 
| | |-- webapp 
| | | |-- META-INF 
| | | | +--context.xml 
| | |-- config 
| | | |-- test 
| | | | |--log4j.xml 
| | | | |--struts.properties 
| | | | +--context.xml 
| | | +-- prod 
| | | | |--log4j.xml 
| | | | |--struts.properties 
| | | | +--context.xml 
| +--test 
+--pom.xml 

Come potete vedere, ho incluso un certo numero di file di configurazione: quelli che si trovano nella posizione corretta all'interno del progetto, cioè all'interno di src/main/resources e src/main/webapp sono quelli che uso abitualmente quando lavoro in MyEclipse. Posso usare i connettori MyEclipse per aggiornare automaticamente una distribuzione, ad esempio un'istanza di Tomcat sulla mia macchina di sviluppo, faccio semplicemente clic su "Esegui server" e posso eseguire il de bug. Non c'è assolutamente bisogno di usare Maven in questo contesto.

Quindi, quando voglio creare un rilascio per un altro ambiente come test o produzione, eseguo mvn -P test clean install e crea una bella GUERRA.

Il mio obiettivo è sostituire i file di configurazione all'interno della finale WAR con quelli in src/config/{environment}/.

ho impostato un profilo nel mio pom.xml:

<profiles> 
    <profile> 
     <id>test</id> 
     <properties> 
      <environment>test</environment> 
     </properties> 
    </profile> 

    <profile> 
     <id>prod</id> 
     <properties> 
      <environment>prod</environment> 
     </properties> 
    </profile> 
</profiles> 

Poi, provo a copiare queste risorse dal profilo specificato (utilizzando la variabile environment) nella posizione corretta all'interno del GUERRA (o la cartella temporanea saranno compressi in un WAR):

<webResources> 
    <resource> 
     <directory>/src/main/config/${environment}</directory> 
     <targetPath>META-INF/</targetPath> 
     <includes> 
      <include>context.xml</include> 
     </includes> 
    </resource> 
    <resource> 
     <directory>src/main/config/${environment}</directory> 
     <targetPath>WEB-INF/classes/</targetPath> 
     <includes> 
      <include> 
       struts.properties 
      </include> 
      <include> 
       log4j.xml 
      </include> 
     </includes> 
    </resource> 
</webResources> 

Ora, questo sembra funzionare, se non che le risorse "standard" vengono copiati nella directory dopo questo, in modo da sovrascrivere tali file. Così finisco sempre con, ad es. il log4j.xml da src/main/resources al posto di quello da dire src/main/configuration/prod/

Estratto della uscita Maven:

[INFO] Processing war project 
[INFO] Copying webapp webResources [D:\workspace\MyProject/src/main/config/prod] to [D:\workspaces\SITEL\Webfauna\target\Webfauna] 
[INFO] Copying webapp webResources [D:\workspace\MyProject\src/main/config/prod] to [D:\workspaces\SITEL\Webfauna\target\Webfauna] 
[INFO] Copying webapp resources [D:\workspace\MyProject\src\main\webapp] 

Come si può vedere l'ultima riga, roba da src/main/webapp viene copiato DOPO, sovrascrivendo così il mio file personalizzati: (

la mia domanda: Come forzare Maven di utilizzare i file "dal profilo attivato" e in qualche modo sovrascrivere i file "naturali"

risposta

9

Come sottolineato nel secondo Q/A given by user944849, la soluzione più semplice era quello di filtrare i file originali in modo che possano essere sostituiti dai file dalla cartella del profilo.

Così ho aggiunto il filtraggio di risorse standard:

<resources> 
     <resource> 
      <directory>src/main/resources</directory> 
      <excludes> 
       <!-- Exclude those since they are copied from the profile folder for the build --> 
       <exclude>log4j.xml</exclude> 
       <exclude>struts.properties</exclude> 
      </excludes> 
      <filtering>false</filtering> 
     </resource> 
    </resources> 

E per le risorse web:

<warSourceExcludes>**/context.xml</warSourceExcludes> 

Così ora i 3 file non vengono copiati nella cartella WAR. Nel passaggio successivo (webResources) vengono copiati dalla cartella del profilo attivo.

Ho anche aggiunto una cartella predefinita contenente i 3 file con valori comuni. Anche i file di questa cartella predefinita vengono copiati, ma solo dopo quelli della cartella del profilo. Poiché le risorse non vengono sovrascritte, verranno copiate solo se non esistono già. Ciò è utile se si costruisce senza un profilo attivato o se è possibile definire valori predefiniti sensibili, nessun profilo deve replicare il file se è identico.

Struttura della cartella config:

-- config 
    |-- test 
    | |--log4j.xml 
    | | |--struts.properties 
    | | +--context.xml 
    | +-- prod 
    | | |--log4j.xml 
    | | +--context.xml 
    | +-- default 
    |  |--log4j.xml 
    |  |--struts.properties 
    |  +--context.xml 
... 

E la sezione webResources della mia pom.xml:

<webResources> 
    <!-- Resources from the activated profile folder --> 
    <resource> 
     <directory>/src/main/config/${environment}</directory> 
     <targetPath>META-INF/</targetPath> 
     <includes> 
      <include>context.xml</include> 
     </includes> 
    </resource> 
    <resource> 
     <directory>src/main/config/${environment}</directory> 
     <targetPath>WEB-INF/classes/</targetPath> 
     <includes> 
      <include> 
       struts.properties 
      </include> 
      <include> 
       log4j.xml 
      </include> 
     </includes> 
    </resource> 
    <!-- Default resources in case some file was not defined in the profile folder --> 
    <!-- Files are not overwritten so default files will be copied only if it does not exist already --> 
    <resource> 
     <directory>/src/main/config/default</directory> 
     <targetPath>META-INF/</targetPath> 
     <includes> 
      <include>context.xml</include> 
     </includes> 
    </resource> 
    <resource> 
     <directory>src/main/config/default</directory> 
     <targetPath>WEB-INF/classes/</targetPath> 
     <includes> 
      <include> 
       struts.properties 
      </include> 
      <include> 
       log4j.xml 
      </include> 
     </includes> 
    </resource> 
</webResources> 
+0

Brillante informazione. Stavo cercando la soluzione esatta e l'ho presa. Molte grazie. –

1

ti penso? bisogno di sovrapporre i file di guerra. O creando una dipendenza in ogni profilo di tipo war invece di jar, che sovrascriverà i file nel tuo attuale file war.

Un'altra possibilità potrebbe essere il overlay configuration del plug-in maven-war.

in modo che il profilo attivi i file che si desidera copiare su quelli correnti. C'è quite some documentation sul sito del plugin e con alcuni esempi

Spero che funzioni!

+0

Ma i miei file di configurazione personalizzati non fanno parte di un WAR esterno, quindi non sono sicuro di come potrei applicarli come overlay ... non convinto! –

+0

Penso che non sia necessario utilizzare un file war esterno se si utilizza il plugin maven-war e gli overlay. I parametri id/artifactId/groupId sembrano essere facoltativi, quindi non è necessario inserire la configurazione dell'ambiente in un modulo separato. – wemu

+0

il plug-in di guerra sembra funzionare nella fase del pacchetto: http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference mentre il plugin delle risorse viene eseguito in precedenza nelle risorse del processo. Non penso che quel modo funzionerà per ingannare il plugin di guerra. – wemu

1

un altro tentativo :)

Ho giocato in giro con la sovrapposizione parametro. Penso che sostituisca solo i file nella cartella webapp che hai in un altro file di guerra all'interno della cartella webapp. Quindi non è la cosa perfetta per il tuo setup.

Eppure il parametro WebResource di cui sopra può fare questo:

<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/xsd/maven-4.0.0.xsd"> 
<modelVersion>4.0.0</modelVersion> 

<groupId>org.mimacom.maven.examples</groupId> 
<artifactId>mimacom-war-overlays</artifactId> 
<version>1.0.0-SNAPSHOT</version> 
<packaging>war</packaging> 

<name>${project.artifactId}</name> 

<properties> 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    <project.build.compiler.version>1.6</project.build.compiler.version> 
    <junit.version>4.9</junit.version> 
</properties> 

<build> 
    <pluginManagement> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <version>2.5.1</version> 
       <configuration> 
        <source>${project.build.compiler.version}</source> 
        <target>${project.build.compiler.version}</target> 
        <encoding>${project.build.sourceEncoding}</encoding> 
       </configuration> 
      </plugin> 
     </plugins> 
    </pluginManagement> 

    <plugins> 
     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-war-plugin</artifactId> 
      <version>2.3</version> 
     </plugin> 
    </plugins> 
</build> 

<dependencies> 
    <dependency> 
     <groupId>junit</groupId> 
     <artifactId>junit</artifactId> 
     <version>${junit.version}</version> 
    </dependency> 
</dependencies> 

<profiles> 
    <profile> 
     <id>prod</id> 
     <build> 
      <plugins> 
       <plugin> 
        <groupId>org.apache.maven.plugins</groupId> 
        <artifactId>maven-war-plugin</artifactId> 
        <version>2.3</version> 
        <configuration> 
         <webResources> 
          <resource> 
           <directory>src/main/config/prod</directory> 
          </resource> 
         </webResources> 
         <!--<includes>--> 
          <!--<include>${basedir}/environments/overlay-1/css/styles.css</include>--> 
         <!--</includes>--> 
         <!--<overlays>--> 
          <!--<overlay>--> 
           <!--<includes>--> 
            <!--../environments/overlay-1/css/**--> 
           <!--</includes>--> 
          <!--</overlay>--> 
         <!--</overlays>--> 
        </configuration> 
       </plugin> 
      </plugins> 
     </build> 
    </profile> 
    <profile> 
     <id>test</id> 
     <build> 
      <plugins> 
       <plugin> 
        <groupId>org.apache.maven.plugins</groupId> 
        <artifactId>maven-war-plugin</artifactId> 
        <version>2.3</version> 
        <configuration> 
         <webResources> 
          <resource> 
           <directory>src/main/config/test</directory> 
          </resource> 
         </webResources> 
        </configuration> 
       </plugin> 
      </plugins> 
     </build> 
    </profile> 

</profiles> 

I profili attivati ​​aggiungeranno ulteriori cartelle al file guerra. Quindi dovrebbe fare il trucco!

1

Vedo che usereste le stesse risorse ma con una configurazione diversa in ciascun profilo (test e pungolo).

Quindi, vi consiglio di utilizzare una configurazione simile a questo:

<profiles> 
<profile> 
    <id>test</id> 
    <activation> 
     <activeByDefault>true</activeByDefault> 
     <property> 
      <name>env</name> 
      <name>test</name> 
     </property> 
    </activation> 
    <build> 
     <filters> 
      <filter>test.properties</filter> 
     </filters> 
    </build> 
</profile> 

<profile> 
    <id>prod</id> 
    <activation> 
     <property> 
      <name>env</name> 
      <value>prod</value> 
     </property> 
    </activation> 
    <build> 
     <filters> 
      <filter>prod.properties</filter> 
     </filters> 
    </build> 
</profile> 
</profiles> 

In questo scenario, ho due profili, ognuno è attivata con il parametro "env". Ogni profilo ha un file per filtrare le risorse, inserire i file log4j.xml, struts.properties, context.xml in src/main/resources e utilizzare le variabili per utilizzare la corretta configurazione in ciascun profilo.

Spero che questo aiuti.

0

Ecco una versione più semplice delle soluzioni precedenti che si basa solo su un semplice frammento inserito in pom.xml.

Costruire il valore di default (workstation locale) webapp con:

mvn war:exploded 

Aggiungi un parametro di riga di comando ambiente per copiare i file da una directory specifica per ambiente come risorse-prod alla directory/classi di destinazione WEB-INF:

mvn war:exploded -Denvironment=prod 

Aggiungere questo all'interno dell'elemento progetto pom.xml:

<!-- this profile will allow files in environment-specific folders like resources-prod or resources-test 
    to be added to the resulting war's classpath under WEB-INF/classes 
    to activate the profile, simply add '-Denvironment=prod' to your maven build command 
    this also works fine with war:inplace and war:exploded 
--> 
<profile> 
    <id>environment-specific</id> 
    <activation> 
     <property> 
      <name>environment</name> 
     </property> 
    </activation> 
    <build> 
    <plugins> 
     <plugin> 
     <groupId>org.apache.maven.plugins</groupId> 
     <artifactId>maven-war-plugin</artifactId> 
     <version>2.4</version> 
     <configuration> 
      <webResources> 
       <!-- note the order of the following resource elements are important. 
        if there are duplicate files, the first file copied will win 
       --> 
       <resource> 
        <!-- this is relative to the pom.xml directory -->       
        <directory>resources-${environment}</directory> 
        <!-- override default destination at root of war --> 
        <targetPath>WEB-INF/classes</targetPath> 
       </resource> 
       <resource> 
        <directory>src/main/resources</directory> 
        <targetPath>WEB-INF/classes</targetPath> 
       </resource> 
      </webResources> 
     </configuration> 
     </plugin>    
    </plugins> 
    </build> 
</profile> 

Maggiori informazioni e link to working example.