maven-2 - mvn - maven tutorial
Propiedad Maven2 que indica el directorio principal (18)
Tengo un proyecto de varios módulos, como este:
main-project/
module1/
module2/
sub-module1/
sub-module2/
sub-module3/
...
module3/
module4/
...
Necesito definir un conjunto de propiedades (que dependen del entorno en el que quiero lanzar mi proyecto) en Maven2. No usaré <properties>
ya que hay muchas propiedades ... Por lo tanto, uso el plugin Propiedades Maven2 .
Los archivos de propiedades se encuentran en el directorio main-project/
. ¿Cómo puedo establecer el directorio correcto en el archivo pom.xml principal, para especificar a los elementos secundarios dónde encontrar el archivo de propiedades?
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>???/env_${env}.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
Si configuro solo <file>env_${env}.properties</file>
, cuando Maven2 compila el primer módulo, no encontrará el archivo main-project/env_dev.properties
. Si configuro <file>../env_${env}.properties</file>
, se generará un error en el nivel principal, o en cualquier nivel de submódulo ...
¿ ../../env_${env}.properties
... ../../env_${env}.properties
?
Normalmente hacemos lo siguiente cuando el módulo2 está en el mismo nivel que los submódulos
<modules>
<module>../sub-module1</module>
<module>../sub-module2</module>
<module>../sub-module3</module>
</modules>
Creo que el ... / ... te dejaría saltar dos niveles. De lo contrario, es posible que desee ponerse en contacto con los autores de los complementos y ver si se trata de un problema conocido.
Accedí al directorio anterior utilizando $ {basedir} .. / src /
Creo que si usa el patrón de extensión utilizado en el ejemplo de findbugs plugin & multimodule, puede establecer propiedades globales relacionadas con rutas absolutas. Utiliza una parte superior
El pom de nivel superior tiene un proyecto de compilación de configuración no relacionado y una aplicación principal para los módulos del proyecto de varios módulos. La aplicación principal utiliza la extensión para vincularse al proyecto build-config y obtener recursos de ella. Esto se usa para llevar archivos de configuración comunes a los módulos. Puede ser un conducto para las propiedades también. Puede escribir el dir superior en un archivo de propiedades consumido por build-config. (parece demasiado complejo)
El problema es que se debe agregar un nuevo nivel superior al proyecto de varios módulos para que esto funcione. Traté de dar un paso al costado con un proyecto de configuración de construcción realmente no relacionado, pero era complicado y parecía quebradizo.
El siguiente pequeño perfil funcionó para mí. Necesitaba tal configuración para CheckStyle, que puse en el directorio config
en la raíz del proyecto, para poder ejecutarlo desde el módulo principal y desde los submódulos.
<profile>
<id>root-dir</id>
<activation>
<file>
<exists>${project.basedir}/../../config/checkstyle.xml</exists>
</file>
</activation>
<properties>
<project.config.path>${project.basedir}/../config</project.config.path>
</properties>
</profile>
No funcionará para módulos anidados, pero estoy seguro de que se puede modificar para eso usando varios perfiles con diferentes exists
. (No tengo idea de por qué debería haber "../ .." en la etiqueta de verificación y solo ".." en la propiedad sobrescrita, pero funciona solo de esa manera).
En mi caso, funciona así:
...
<properties>
<main_dir>${project.parent.relativePath}/..</main_dir>
</properties>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${main_dir}/maven_custom.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
En una respuesta a otra pregunta , mostré cómo el plugin maven-properties-plugin podría extenderse para usar descriptores de propiedad externos definidos en las dependencias de Maven.
Puede extender esa idea para tener varios archivos descriptores, cada uno con el nombre del entorno como parte del artifactId, que contiene $ {env} .properties. Luego puede usar la propiedad para seleccionar el archivo jar y propiedades apropiado, por ejemplo:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-ext-maven-plugin</artifactId>
<version>0.0.1</version>
<executions>
<execution>
<id>read-properties</id>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
</execution>
</executions>
<configuration>
<filePaths>
<!--assume the descriptor project has a file in the root of the jar -->
<filePath>${env}.properties</filePath>
</filePaths>
</configuration>
<dependencies>
<!-- reference the properties jar for the particular environment-->
<dependency>
<groupId>some.descriptor.group</groupId>
<artifactId>env-${env}-descriptor</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
</plugin>
Encontré una solución para resolver este problema: use $ {parent.relativePath}
<parent>
<artifactId>xxx</artifactId>
<groupId>xxx</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<build>
<filters>
<filter>${parent.relativePath}/src/main/filters/filter-${env}.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
Encontré una solución para resolver mi problema: busco en los archivos de propiedades usando el complemento Groovy Maven.
Como mi archivo de propiedades está necesariamente en el directorio actual, en ../ o en .. / .., escribí un pequeño código de Groovy que verifica estas tres carpetas.
Aquí está el extracto de mi pom.xml:
<!-- Use Groovy to search the location of the properties file. -->
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0-rc-5</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
import java.io.File;
String p = project.properties[''env-properties-file''];
File f = new File(p);
if (!f.exists()) {
f = new File("../" + p);
if (!f.exists()) {
f = new File("../../" + p);
}
}
project.properties[''env-properties-file-by-groovy''] = f.getAbsolutePath();
</source>
</configuration>
</execution>
</executions>
</plugin>
<!-- Now, I can load the properties file using the new ''env-properties-file-by-groovy'' property. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${env-properties-file-by-groovy}</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
Esto está funcionando, pero realmente no me gusta.
Entonces, si tiene una mejor solución, ¡no dude en publicarla!
Entonces el problema es que no se puede obtener la ruta absoluta a un directorio padre en maven.
<rant> He oído hablar de esto como un antipatrón , pero para cada antipatrón hay un uso real y legítimo, y estoy harto de que maven me diga que solo puedo seguir sus patrones. </ rant>
Entonces el trabajo que encontré fue usar antrun. Pruebe esto en el pom.xml hijo:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>getMainBaseDir</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<exportAntProperties>true</exportAntProperties>
<target>
<!--Adjust the location below to your directory structure -->
<property name="main.basedir" location="./.." />
<echo message="main.basedir=${main.basedir}"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
Si ejecuta mvn verify
que vea algo como esto:
main:
[echo] main.basedir=C:/src/parent.project.dir.name
Luego puedes usar ${main.basedir}
en cualquiera de los otros complementos, etc. Me tomó un tiempo resolver esto, así que espero que ayude a alguien más.
Estás en el proyecto C, el proyecto C es el submódulo de B y B es el submódulo de A. Intentas llegar al directorio del src/test/config/etc
del módulo C. D también es un submódulo de A. La siguiente expresión lo hace posible para obtener la ruta URI:
-Dparameter=file:/${basedir}/../../D/src/test/config/etc
Esto amplía la respuesta de romaintaz, que es impresionante porque resuelve el problema y también señala claramente la funcionalidad que falta de maven. Cogí una versión posterior del complemento y agregué el caso donde el proyecto podría tener más de 3 niveles de profundidad.
<pluginManagement>
<plugins>
..
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<version>2.0</version>
</plugin>
..
</plugins>
</pluginManagement>
Decidí no usar una propiedad para definir el nombre del archivo. Tenga en cuenta que si build.properties no se encuentra, esto girará para siempre. Agregué una detección .git dir, pero no quería complicar demasiado la respuesta, por lo que no se muestra aquí.
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
import java.io.File;
String p = "build.properties";
while(true) {
File f = new File(p);
if(f.exists()) {
project.properties[''project-properties-file''] = f.getAbsolutePath();
break;
}
else {
p = "../${p}";
}
}
</source>
</configuration>
</execution>
</executions>
</plugin>
Intente establecer una propiedad en cada pom para encontrar el directorio principal del proyecto.
En el padre:
<properties>
<main.basedir>${project.basedir}</main.basedir>
</properties>
En los niños:
<properties>
<main.basedir>${project.parent.basedir}</main.basedir>
</properties>
En los nietos:
<properties>
<main.basedir>${project.parent.parent.basedir}</main.basedir>
</properties>
La primera respuesta debería funcionar. En la línea de herencia padre-hijo, la propiedad definida por el usuario se establece con una propiedad maven-default en el POM de nivel superior (en este caso, <parent.base.directory>${project.parent.basedir}</parent.base.directory>
) se establecerá a medida que atraviesa el árbol. En otras palabras, ${parent.base.directory}
se establecerá correctamente en diferentes POM secundarios.
Tenga en cuenta que no debe usar ${parent.basedir}
como su propiedad definida por el usuario porque es la misma que la propiedad maven-default ${project.parent.basedir}
. De lo contrario, entra en error de expresión recursiva en maven. Es por eso que uso ${parent.base.directory}
en la respuesta.
Espero que esta sea la solución raíz al problema.
Necesitaba resolver un problema similar para el repositorio local ubicado en el proyecto principal del proyecto de varios módulos. Esencialmente, la ruta real era ${basedir}
/ lib. Finalmente me decidí por esto en mi parent.pom
:
<repository>
<id>local-maven-repo</id>
<url>file:///${basedir}/${project.parent.relativePath}/lib</url>
</repository>
Esa base siempre muestra el módulo local actual, no hay forma de obtener el camino al proyecto "maestro" (la vergüenza de Maven). Algunos de mis submódulos son un directorio más profundo, algunos son dos directorios más profundos, pero todos ellos son submódulos directos del elemento principal que define el URL del repositorio.
Entonces esto no resuelve el problema en general. Siempre puede combinarlo con la respuesta aceptada de Clay y definir alguna otra propiedad: funciona bien y debe redefinirse solo para los casos en que el valor de parent.pom
no sea lo suficientemente bueno. O simplemente puede reconfigurar el complemento, que solo hace en artefactos POM (padres de otros submódulos). El valor extraído en la propiedad probablemente sea mejor si lo necesita en más lugares, especialmente cuando no cambia nada en la configuración del complemento.
El uso de basedir
en el valor fue la parte esencial aquí, porque el file://${project.parent.relativePath}/lib
URL file://${project.parent.relativePath}/lib
no quería hacer el truco (eliminé una barra para hacerlo relativo). Usar propiedad que me da una buena ruta absoluta y luego ir relativa desde allí era necesaria.
Cuando la ruta no es URL / URI, probablemente no sea un problema soltar basedir
.
Otra alternativa:
en el pom padre, use:
<properties>
<rootDir>${session.executionRootDirectory}</rootDir>
<properties>
En los poms de los niños, puedes hacer referencia a esta variable.
Advertencia principal: Te obliga a ejecutar siempre el comando desde el directorio padre principal de pom. Luego, si desea ejecutar comandos (prueba, por ejemplo) solo para algún módulo específico, use esta sintaxis:
prueba mvn --proyectos
La configuración de surefire para parametrizar una variable "path_to_test_data" puede ser:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.plugin.version}</version>
<configuration>
<systemPropertyVariables>
<path_to_test_data>${rootDir/../testdata}</path_to_test_data>
</systemPropertyVariables>
</configuration>
</plugin>
Simplemente mejoré la secuencia de comandos Groovy desde arriba para escribir la propiedad en el archivo de propiedades principal raíz:
import java.io.*;
String p = project.properties[''env-properties-file'']
File f = new File(p)
if (f.exists()) {
try{
FileWriter fstream = new FileWriter(f.getAbsolutePath())
BufferedWriter out = new BufferedWriter(fstream)
String propToSet = f.getAbsolutePath().substring(0, f.getAbsolutePath().lastIndexOf(File.separator))
if (File.separator != "/") {
propToSet = propToSet.replace(File.separator,File.separator+File.separator+File.separator)
}
out.write("jacoco.agent = " + propToSet + "/lib/jacocoagent.jar")
out.close()
}catch (Exception e){
}
}
String ret = "../"
while (!f.exists()) {
f = new File(ret + p)
ret+= "../"
}
project.properties[''env-properties-file-by-groovy''] = f.getAbsolutePath()
Use directory-maven-plugin con el objetivo directory-of .
A diferencia de otras sugerencias:
- Esta solución funciona para proyectos de múltiples módulos.
- Funciona ya sea que construyas el proyecto completo o un submódulo.
- Funciona ya sea que ejecute maven desde la carpeta raíz o un submódulo.
- ¡No es necesario establecer una propiedad de ruta relativa en todos y cada uno de los submódulos!
El complemento le permite establecer una propiedad de su elección en la ruta absoluta de cualquiera de los módulos del proyecto. En mi caso, lo configuré para el módulo raíz ... En mi proyecto root pom:
<plugin>
<groupId>org.commonjava.maven.plugins</groupId>
<artifactId>directory-maven-plugin</artifactId>
<version>0.1</version>
<executions>
<execution>
<id>directories</id>
<goals>
<goal>directory-of</goal>
</goals>
<phase>initialize</phase>
<configuration>
<property>myproject.basedir</property>
<project>
<groupId>com.my.domain</groupId>
<artifactId>my-root-artifact</artifactId>
</project>
</configuration>
</execution>
</executions>
</plugin>
Desde ese momento, $ {myproject.basedir} en cualquier submódulo pom siempre tiene la ruta del módulo raíz del proyecto. Y, por supuesto, puede establecer la propiedad en cualquier módulo, no solo en la raíz ...
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
import java.io.File
project.properties.parentdir = "${pom.basedir}"
while (new File(new File(project.properties.parentdir).parent, ''pom.xml'').exists()) {
project.properties.parentdir = new File(project.properties.parentdir).parent
}
</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${parentdir}/build.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
...