web-dev-qa-db-fra.com

Propriété Maven2 qui indique le répertoire parent

J'ai un projet multi-modules, comme celui-ci:

main-project/
    module1/
    module2/
        sub-module1/
        sub-module2/
        sub-module3/
        ...
    module3/
    module4/
    ...

Je dois définir un ensemble de propriétés (qui dépendent de l'environnement sur lequel je souhaite publier mon projet) dans Maven2 . Je n'utiliserai pas <properties> car il y a beaucoup de propriétés .... utilisez le plugin Properties Maven2 .

Les fichiers de propriétés sont situés dans le répertoire main-project/ . Comment définir le bon répertoire dans le fichier principal pom.xml afin de spécifier à tout enfant où trouver le fichier de propriétés?

<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 je ne configure que <file>env_${env}.properties</file>, lorsque Maven2 compilera le premier module, il ne trouvera pas le fichier main-project/env_dev.properties. Si je mets <file>../env_${env}.properties</file>, alors une erreur sera levée au niveau parent, ou à n’importe quel niveau de sous-module ...

93
Romain Linsolas

Essayez de définir une propriété dans chaque pom pour trouver le répertoire principal du projet. 

Dans le parent: 

<properties>
    <main.basedir>${project.basedir}</main.basedir>
</properties>

Chez les enfants: 

<properties>
    <main.basedir>${project.parent.basedir}</main.basedir>
</properties>

Dans les petits-enfants: 

<properties>
    <main.basedir>${project.parent.parent.basedir}</main.basedir>
</properties>
144
Clay

J'ai trouvé une solution pour résoudre mon problème: je recherche les fichiers de propriétés à l'aide du plugin Groovy Maven.

Comme mon fichier de propriétés est nécessairement dans le répertoire courant, dans ../ ou dans ../.., j’ai écrit un petit code Groovy qui vérifie ces trois dossiers.

Voici l'extrait de mon 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>

Cela fonctionne, mais je ne l'aime pas vraiment.

Donc, si vous avez une meilleure solution, n'hésitez pas à poster!

14
Romain Linsolas

Donc, le problème, à mon avis, est que vous ne pouvez pas obtenir le chemin absolu vers un répertoire parent dans maven.

<rant> J'ai entendu dire que c'était un anti-modèle , mais pour chaque anti-modèle, il existe un cas d'utilisation légitime et légitime, et j'en ai marre que Maven me dis que je ne peux que suivre leur motifs. </ rant>

Donc, le travail que j'ai trouvé consistait à utiliser antrun. Essayez ceci dans l'enfant pom.xml:

<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 vous exécutez mvn verify, vous devriez voir quelque chose comme ceci:

main:
     [echo] main.basedir=C:\src\parent.project.dir.name

Vous pouvez ensuite utiliser ${main.basedir} dans n’importe quel autre plugin, etc. Il m’a fallu un peu de temps pour comprendre cela, alors espérons que cela aidera quelqu'un d’autre.

11
Jared

Utilisez directory-maven-plugin avec directory-of goal .

Contrairement à d'autres suggestions:

  • Cette solution fonctionne pour des projets multi-modules.
  • Cela fonctionne que vous construisiez le projet entier ou un sous-module.
  • Cela fonctionne que vous exécutiez maven à partir du dossier racine ou d’un sous-module.
  • Il n'est pas nécessaire de définir une propriété de chemin relatif dans chaque sous-module!

Le plugin vous permet de définir une propriété de votre choix sur le chemin absolu de l'un des modules du projet. Dans mon cas, je l'ai défini sur le module racine ... Dans le pom racine de mon projet:

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

A partir de là, $ {myproject.basedir} de tout pom de sous-module a toujours le chemin du module racine du projet. Et bien sûr, vous pouvez définir la propriété sur n'importe quel module, pas seulement sur la racine ...

11
sparkyd

Dans mon cas, cela fonctionne comme ceci:

...
<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>
6
user1774153

Le petit profil suivant a fonctionné pour moi. J'avais besoin d'une telle configuration pour CheckStyle, que j'ai placée dans le répertoire config à la racine du projet, afin de pouvoir l'exécuter à partir du module principal et des sous-modules.

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

Cela ne fonctionnera pas pour les modules imbriqués, mais je suis sûr qu'il peut être modifié pour cela en utilisant plusieurs profils avec différents exists. (Je ne sais pas pourquoi il devrait y avoir "../ .." dans la balise de vérification et juste ".." dans la propriété surchargée elle-même, mais cela ne fonctionne que de cette façon.)

6
Vic

Une autre alternative:

dans le pom parent, utilisez:

<properties>
   <rootDir>${session.executionRootDirectory}</rootDir>
<properties>

Dans les enfants poms, vous pouvez référencer cette variable.

Avertissement principal: il vous oblige à toujours exécuter des commandes à partir du répertoire pom principal. Ensuite, si vous souhaitez exécuter des commandes (test par exemple) uniquement pour un module spécifique, utilisez la syntaxe suivante:

test mvn --projets 

La configuration de surefire pour paramétrer une variable "path_to_test_data" peut alors être:

<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>
5
Francois Marot

J'ai trouvé une solution pour résoudre ce problème: 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>
3
Caille

Vous êtes dans le projet C, le projet C est le sous-module de B et B est le sous-module de A. Vous essayez d'atteindre le répertoire src/test/config/etc du module D à partir du projet C. D est également le sous-module de A. L'expression suivante permet d'obtenir le chemin de l'URI:

-Dparameter=file:/${basedir}/../../D/src/test/config/etc
3
fatih tekin

Au moins dans la version actuelle de maven (3.6.0), vous pouvez utiliser ${maven.multiModuleProjectDirectory}

2
qoomon
<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>
  ...
2
dulanov

Je viens d’améliorer le script groovy d’en haut pour écrire la propriété dans le fichier de propriétés racine:

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()
1
Tcharl

J'ai accédé au répertoire ci-dessus avec $ {basedir} ..\src \

1
Secelean Monica

Dans un réponse à une autre question j'ai montré comment le plugin maven-properties-plugin pouvait être étendu pour utiliser des descripteurs de propriétés externes définis dans les dépendances Maven.

Vous pouvez étendre cette idée à plusieurs fichiers jar de descripteur, chacun avec le nom de l’environnement faisant partie de artifactId, contenant un $ {env} .properties. Vous pouvez ensuite utiliser la propriété pour sélectionner le fichier jar et le fichier de propriétés appropriés, par exemple:

<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>
1
Rich Seller

Je pense que si vous utilisez le modèle d'extension utilisé dans l'exemple pour le plugin et multimodule findbugs, vous pourrez peut-être définir des propriétés globales liées aux chemins absolus. Il utilise un top

exemple pour multi module

Le pom de niveau supérieur a un projet build-config non associé et un app-parent pour les modules du projet multimodule. App-parent utilise l'extension pour se lier au projet build-config et obtenir des ressources de celui-ci. Ceci est utilisé pour transporter des fichiers de configuration communs aux modules. Cela peut également être un conduit pour les propriétés. Vous pouvez écrire le premier répertoire dans un fichier de propriétés utilisé par build-config. (cela semble trop complexe)

Le problème est qu'un nouveau niveau supérieur doit être ajouté au projet multi-module pour que cela fonctionne. J’ai essayé d’accompagner un projet de construction-configuration sans aucun rapport, mais c’était superficiel et semblait fragile. 

0
Peter Kahn

Je devais résoudre un problème similaire pour le référentiel local placé dans le projet principal du projet multi-module. Le vrai chemin était essentiellement ${basedir}/lib. Finalement, j'ai réglé ça dans mon parent.pom:

<repository>
    <id>local-maven-repo</id>
    <url>file:///${basedir}/${project.parent.relativePath}/lib</url>
</repository>

Cette basedir indique toujours au module local actuel, il n’existe aucun moyen d’obtenir un chemin vers le projet "maître" (la honte de Maven). Certains de mes sous-modules sont plus profonds d'un répertoire, d'autres plus profonds, mais tous sont sous-modules directs du parent qui définit l'URL du référentiel.

Cela ne résout donc pas le problème en général. Vous pouvez toujours le combiner avec la réponse acceptée de Clay et définir une autre propriété. Cela fonctionne bien et doit être redéfini uniquement dans les cas où la valeur de parent.pom n'est pas suffisante. Ou vous pouvez simplement reconfigurer le plugin - ce que vous ne faites que dans les artefacts POM (parents d'autres sous-modules). La valeur extraite dans la propriété est probablement meilleure si vous en avez besoin à plusieurs endroits, en particulier lorsque rien ne change dans la configuration du plug-in.

Utiliser basedir dans la valeur était la partie essentielle ici, parce que l'URL file://${project.parent.relativePath}/lib ne voulait pas faire l'affaire (j'ai supprimé une barre oblique pour la rendre relative). Utiliser une propriété qui me donne un bon chemin absolu, puis aller relatif par rapport à cela était nécessaire.

Lorsque le chemin n'est pas URL/URI, le problème n'est pas de supprimer basedir.

0
virgo47

Avez-vous essayé ../../env_${env}.properties?

Normalement nous faisons ce qui suit quand module2 est au même niveau que les sous-modules

<modules>
    <module>../sub-module1</module>
    <module>../sub-module2</module>
    <module>../sub-module3</module>
</modules>

Je pense que le ../ .. vous laisserait sauter de deux niveaux. Sinon, vous pouvez contacter les auteurs du plug-in pour voir s'il s'agit d'un problème connu.

0
sal

Ceci étend la réponse de romaintaz, ce qui est génial car il résout le problème et indique clairement la fonctionnalité manquante de maven .. J'ai pris une version plus récente du plugin et ajouté le cas où le projet pouvait comporter plus de 3 niveaux.

<pluginManagement>
  <plugins>
    ..
    <plugin>
      <groupId>org.codehaus.gmaven</groupId>
      <artifactId>groovy-maven-plugin</artifactId>
      <version>2.0</version>
    </plugin>
    ..
  </plugins>
</pluginManagement>

J'ai choisi de ne pas utiliser de propriété pour définir le nom de fichier . Notez que si le build.properties n'est pas trouvé, cela tournera pour toujours. J'ai ajouté une détection de répertoire .git, mais je ne voulais pas trop compliquer la réponse, elle n'est donc pas affichée ici.

  <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>
0
Bruce Edge