2012-10-04 26 views
8

Tengo un proyecto de aplicación web de Java que desarrollo en Eclipse (más precisamente MyEclipse 10) y construyo utilizando Maven 3.¿Cómo sobrescribir los archivos en el archivo WAR durante la creación de maven?

tengo la siguiente distribución (incluyendo sólo los archivos pertinentes a mi 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 

Como puede ver, incluí una serie de archivos de configuración. Los que están en su ubicación correcta dentro de la estructura del proyecto, es decir, dentro de src/main/resources y src/main/webapp son los que uso de forma rutinaria cuando trabajo en MyEclipse. Puedo usar conectores MyEclipse para actualizar automáticamente una implementación, por ejemplo, una instancia de Tomcat en mi máquina de desarrollo. Solo hago clic en "ejecutar servidor" y puedo error. No es necesario usar Maven en este contexto en realidad.

Luego, cuando quiero crear una versión para otro entorno, como las pruebas o la producción, ejecuto mvn -P test clean install y crea un buen WAR.

Mi objetivo es reemplazar los archivos de configuración dentro de la GUERRA final por aquellos en src/config/{environment}/.

he puesto perfiles en mi pom.xml:

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

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

Entonces, trato de copiar estos recursos desde el perfil especificado (usando la variable environment) a la ubicación correcta dentro de la GUERRA (o la carpeta temporal que se comprimen en 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> 

Ahora bien, esto parece funcionar, excepto que los recursos "estándar" se copian en el directorio después de esto, por lo que sobrescribir estos archivos. Así que siempre termino con, por ejemplo, la log4j.xml de src/main/resources en lugar de la de por ejemplo src/main/configuration/prod/

Extracto de la salida de 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] 

Como se puede ver en la última línea, cosas de src/main/webapp se copia DESPUÉS, sobrescribiendo por lo tanto mis archivos personalizados: (

Mi pregunta: ¿Cómo forzar Maven para utilizar los archivos "desde el perfil activado" y de algún modo sobrescribir los archivos "naturales"

Respuesta

9

Como se señaló en el segundo Q/A given by user944849, la solución más simple era para filtrar los archivos originales para que puedan ser sustituidos por los archivos de la carpeta del perfil.

filtrado Así que he añadido a los recursos estándar:

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

Y a los recursos web:

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

Así que ahora los 3 archivos no se copian en la carpeta GUERRA. En el siguiente paso (webResources) se copian de la carpeta del perfil activo.

También agregué una carpeta predeterminada que contiene los 3 archivos con valores comunes. Los archivos de esta carpeta predeterminada también se copian, pero solo después de los de la carpeta del perfil. Como los recursos no se sobrescriben, se copiarán solo si aún no existen. Esto es útil si construye sin un perfil activado, o si puede definir valores predeterminados razonables, no es necesario que cada perfil replique el archivo si es idéntico.

Estructura de la carpeta de configuración:

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

Y la sección webResources de mi 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 pieza de información. Estaba buscando la solución exacta y la obtuve. Muchas gracias. –

1

Creo que? necesidad de superponer los archivos de guerra. O creando una dependencia en cada perfil de tipo war en lugar de jar, que superpondrá los archivos en su archivo war actual.

Otra posibilidad podría ser overlay configuration del plugin maven-war-plugin.

para que el perfil active los archivos que desea copiar sobre los actuales. Hay quite some documentation en el sitio del complemento, así como con algunos ejemplos

Espero que eso funcione.

+0

Pero mis archivos de configuración personalizados no son parte de un WAR externo, así que no estoy seguro de cómo podría aplicarlos como superposición ... ¡no estoy convencido! –

+0

Creo que no necesita utilizar un archivo de guerra externo si está utilizando el complemento maven-war y las superposiciones. Los parámetros id/artifactId/groupId parecen ser opcionales, por lo que no es necesario que configure el entorno en un módulo aparte. – wemu

+0

el war-plugin parece ejecutarse en la fase del paquete: http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference mientras el complemento de recursos se ejecuta antes en los recursos del proceso. No creo que eso funcione para engañar al plugin de guerra. – wemu

1

otro intento :)

He jugado un poco con la superposición parámetro. Creo que solo reemplaza los archivos dentro de la carpeta webapp que tiene en otro archivo war dentro de la carpeta webapp. Entonces eso no es lo perfecto para su configuración.

Sin embargo, el parámetro WebResource anteriormente mencionado puede hacer esto:

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

Los perfiles activados añadirán carpetas adicionales para el archivo de la guerra. ¡Así que debería hacer el truco!

1

Veo que usaría los mismos recursos pero con configuraciones diferentes en cada perfil (prueba y prod).

Por lo tanto, sugerimos utilizar una configuración como esta:

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

En este escenario, que tienen dos perfiles, cada uno de ellos se activa mediante el parámetro "env". Cada perfil tiene un archivo para filtrar sus recursos, coloca los archivos log4j.xml, struts.properties, context.xml en src/main/resources y usa variables para usar la configuración correcta en cada perfil.

Espero que ayude.

0

Aquí hay una versión más simple de las soluciones anteriores que solo se basa en un simple fragmento insertado en pom.xml.

Construir la aplicación web por defecto (estación de trabajo local) con:

mvn war:exploded 

Añadir un parámetro de línea de comandos de entorno para copiar archivos de un directorio específico del entorno como recursos-prod al directorio/classes objetivo WEB-INF:

mvn war:exploded -Denvironment=prod 

Añadir este elemento dentro del proyecto de 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> 

Más información y link to working example.

Cuestiones relacionadas