2012-08-22 44 views
7

Necesito leer y filtrar un archivo de propiedades desde una ubicación fuera de mi proyecto, digamos $ {user.home} /my.properties. Este archivo de propiedades se parece a esto:¿Cómo establecer las propiedades de construcción desde un archivo en Maven POM?

res.dir=/my/stuff/here 
resource.dir=C:/${res.dir} 
bin.dir=${resource.dir}/bin 
cfg.dir=${resource.dir}/config 

tengo que hacer esto tanto en mi construcción y en mi aplicación cuando se ejecuta. Esto es fácil de hacer en Ant, usando el PROPERTY tag. Sin embargo, no parece haber una buena manera de hacerlo en Maven.

Hasta ahora he probado la etiqueta Maven <property>, la etiqueta Maven <filter> y varias permutaciones de otras etiquetas. O mi compilación falla o las pruebas de la unidad fallan, o ambas cosas.

Si codificar estas propiedades en el POM, todo funciona, así que sé que el problema se acaba de leer las propiedades.

Miré el properties-maven-plugin pero el plugin ya no parece ser mantenida.

¿Hay alguna manera de hacerlo?

+0

Vi tu comentario sobre el complemento, por lo que eliminé mi respuesta. Solo quiero hacerle saber que, ya sea que se mantenga o no, funciona. (o al menos, solía trabajar). – crnlx

+0

Gracias por la respuesta. Sí, creo que si el complemento ya no se mantiene o incluso se desarrolla (aparece como "Alfa") entonces o bien es tan increíble que no es posible desarrollarlo (es dudoso), o hay una forma mejor de hacerlo. Espero que alguien me señale hacia la "mejor manera". – user1071914

+1

¿Qué te lleva a la suposición de que el complemento ya no se mantendrá? Además, las propiedades fuera del proyecto Maven harán que su proyecto dependa de aquellas cosas que romperán el concepto Maven de tener todo lo necesario para un proyecto Maven dentro del proyecto en sí. La pregunta es por qué estás necesitando esto? – khmarbaise

Respuesta

7

Simplemente podría implementar su propio maven-plugin que se hará cargo de esto para usted.

Aquí se muestra un ejemplo con la siguiente estructura:

. 
|-- pom.xml 
|-- plugin 
| `-- pom.xml 
| `-- src 
|  `-- main 
|   `-- java 
`-- app 
    `-- pom.xml 
    `-- src 
     `-- main 
      `-- java 

Usted tendrá que crear un Mojo que toma el archivo de propiedades como una entrada y luego se propaga a las propiedades a la pom.xml del app.El pom.xml no se actualizará, sino solo los datos del proyecto.

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

    <groupId>com.stackoverflow</groupId> 
    <artifactId>Q12082277</artifactId> 
    <version>1.0-SNAPSHOT</version> 
    <packaging>pom</packaging> 

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

    <modules> 
     <module>plugin</module> 
     <module>app</module> 
    </modules> 

</project> 

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

    <parent> 
     <groupId>com.stackoverflow</groupId> 
     <artifactId>Q12082277</artifactId> 
     <version>1.0-SNAPSHOT</version> 
    </parent> 

    <artifactId>Q12082277-plugin</artifactId> 
    <packaging>maven-plugin</packaging> 

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

    <dependencies> 
     <dependency> 
      <groupId>org.apache.maven</groupId> 
      <artifactId>maven-plugin-api</artifactId> 
      <version>3.0.4</version> 
     </dependency> 
     <dependency> 
      <groupId>org.apache.maven</groupId> 
      <artifactId>maven-project</artifactId> 
      <version>2.2.1</version> 
     </dependency> 
    </dependencies> 
</project> 

plugin/src/main/java/com/stackoverflow/Q12082277/plugin/PropertiesMojo.java

package com.stackoverflow.Q12082277.plugin; 

import org.apache.maven.plugin.AbstractMojo; 
import org.apache.maven.plugin.MojoExecutionException; 
import org.apache.maven.plugin.MojoFailureException; 
import org.apache.maven.plugin.logging.Log; 
import org.apache.maven.project.MavenProject; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.util.Properties; 

/** 
* @author maba, 2012-08-24 
* 
* @goal extract 
*/ 
public class PropertiesMojo extends AbstractMojo { 

    private Log log; 

    /** 
    * The current project representation. 
    * @parameter expression="${project}" 
    * @required 
    * @readonly 
    */ 
    private MavenProject project; 

    /** 
    * A properties file 
    * 
    * @parameter expression="${propertiesFile}" 
    * @required 
    */ 
    private File propertiesFile; 

    @Override 
    public void execute() throws MojoExecutionException, MojoFailureException { 
     log.info("Executing PropertiesMojo on " + propertiesFile.getAbsolutePath()); 

     try { 
      Properties fileProperties = new Properties(); 
      fileProperties.load(new FileInputStream(propertiesFile)); 
      Properties projectProperties = project.getProperties(); 
      for (Object key : fileProperties.keySet()) { 
       projectProperties.setProperty((String)key, (String) fileProperties.get(key)); 
      } 
      project.getProperties().list(System.out); 
     } catch (FileNotFoundException e) { 
      throw new MojoFailureException("The file " + propertiesFile.getAbsolutePath() + " was not found!", e); 
     } catch (IOException e) { 
      log.error(""); 
     } 

    } 

    @Override 
    public void setLog(Log log) { 
     this.log = log; 
    } 
} 

va a utilizar este plugin desde el siguiente app/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/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <parent> 
     <groupId>com.stackoverflow</groupId> 
     <artifactId>Q12082277</artifactId> 
     <version>1.0-SNAPSHOT</version> 
    </parent> 

    <artifactId>Q12082277-app</artifactId> 

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

    <build> 
     <plugins> 
      <plugin> 
       <groupId>com.stackoverflow</groupId> 
       <artifactId>Q12082277-plugin</artifactId> 
       <version>1.0-SNAPSHOT</version> 
       <executions> 
        <execution> 
         <phase>initialize</phase> 
         <goals> 
          <goal>extract</goal> 
         </goals> 
         <configuration> 
          <propertiesFile>${user.home}/my.properties</propertiesFile> 
         </configuration> 
        </execution> 
       </executions> 
      </plugin> 
      <plugin> 
       <groupId>org.codehaus.mojo</groupId> 
       <artifactId>exec-maven-plugin</artifactId> 
       <version>1.2.1</version> 
       <executions> 
        <execution> 
         <goals> 
          <goal>java</goal> 
         </goals> 
        </execution> 
       </executions> 
       <configuration> 
        <mainClass>com.stackoverflow.Q12082277.App</mainClass> 
       </configuration> 
      </plugin> 
     </plugins> 
     <resources> 
      <resource> 
       <directory>src/main/resources</directory> 
       <filtering>true</filtering> 
      </resource> 
     </resources> 
    </build> 
</project> 

Y entonces usted tendrá que agregar la siguiente app.properties que funcionará como una plantilla y tomar los valores que acabamos de leer desde el archivo y establecer y crear un archivo concreto app.properties que será accesible desde dentro de la jarra.

app/src/main/resources/app.properties

res.dir=${res.dir} 
resource.dir=${resource.dir} 
bin.dir=${bin.dir} 
cfg.dir=${cfg.dir} 

Y finalmente aquí es una aplicación de prueba que simplemente carga el app.properties de la ruta de clase e imprime el resultado.

app/src/main/java/com/stackoverflow/Q12082277/App.java

package com.stackoverflow.Q12082277; 

import java.io.IOException; 
import java.io.InputStream; 
import java.util.Properties; 

/** 
* @author maba, 2012-08-23 
*/ 
public class App { 

    public static void main(String[] args) throws IOException { 
     ClassLoader loader = App.class.getClassLoader(); 
     InputStream in = loader.getResourceAsStream("app.properties"); 
     Properties properties = new Properties(); 
     properties.load(in); 
     properties.list(System.out); 
    } 
} 

Ahora puede colocarse en el directorio superior y ejecutar

mvn install 

Luego se baja en la carpeta app y ejecutar

mvn exec:java 

y se imprimirá

-- listing properties -- 
resource.dir=C://my/stuff/here 
cfg.dir=C://my/stuff/here/config 
bin.dir=C://my/stuff/here/bin 
res.dir=/my/stuff/here 

Que es exactamente lo que usted quería.

+0

Esta parece ser la mejor respuesta: no estoy contento de que este gran agujero en el conjunto de herramientas de Maven no haya sido abordado, pero bueno, bienvenidos a código abierto, supongo. :-( – user1071914

3

Creo que sería mejor si se convirtió el archivo de propiedades en un archivo de plantilla y tomar las propiedades de la pom.xml usando maven resource filtering.

una sencilla configuración podría tener este aspecto

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

    <groupId>com.stackoverflow</groupId> 
    <artifactId>Q12082277</artifactId> 
    <version>1.0-SNAPSHOT</version> 

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

    <properties> 
     <res.dir>/default/stuff/here</res.dir> 
     <resource.dir>${res.dir}</resource.dir> 
     <bin.dir>${resource.dir}/bin</bin.dir> 
     <cfg.dir>${resource.dir}/config</cfg.dir> 
    </properties> 

    <dependencies> 
    <!-- Your dependencies --> 
    </dependencies> 

    <build> 
     <resources> 
      <resource> 
       <directory>src/main/resources</directory> 
       <filtering>true</filtering> 
      </resource> 
     </resources> 
    </build> 

</project> 

src/main/resources/app.properties

res.dir=${res.dir} 
resource.dir=${resource.dir} 
bin.dir=${bin.dir} 
cfg.dir=${cfg.dir} 

src/main/java/com/stackoverflow/Q12082277/App.java

package com.stackoverflow.Q12082277; 

import java.io.IOException; 
import java.io.InputStream; 
import java.util.Properties; 

/** 
* @author maba, 2012-08-23 
*/ 
public class App { 

    public static void main(String[] args) throws IOException { 
     ClassLoader loader = App.class.getClassLoader(); 
     InputStream in = loader.getResourceAsStream("app.properties"); 
     Properties properties = new Properties(); 
     properties.load(in); 
     properties.list(System.out); 
    } 
} 

System.out

-- listing properties -- 
resource.dir=/default/stuff/here 
cfg.dir=/default/stuff/here/config 
bin.dir=/default/stuff/here/bin 
res.dir=/default/stuff/here 

El pom.xml tendrá las propiedades predeterminadas que son utilizados por todo el mundo.

Si desea anular los valores a continuación, llamar experto con parámetros de entrada:

mvn install -Dres.dir=/my/stuff/here -Dresource.dir="C:/${res.dir}" 

System.out

-- listing properties -- 
resource.dir=C://my/stuff/here 
cfg.dir=C://my/stuff/here/config 
bin.dir=C://my/stuff/here/bin 
res.dir=/my/stuff/here 

Al hacerlo de esta manera todo el mundo tendrá la misma vista de las propiedades y CAN anularlos si lo desea cuando se ejecuta en su propia máquina.

+0

Gracias por la sugerencia, desafortunadamente la forma en que se presenta actualmente (con las propiedades en un archivo separado) es un estándar corporativo y no está disponible para discusión, así que estoy atascado utilizándolo tal como está. – user1071914

+0

@ user1071914 Intenta usar el plugin maven antrun. Puede hacer lo que necesita. – maba

+0

@ user1071914 Agregué otra respuesta que implementa un simple mojo que hace lo que quiere. – maba

Cuestiones relacionadas