web-dev-qa-db-fra.com

Recherche du répertoire racine d'un projet de réacteur multi-module Maven

Je souhaite utiliser le plug-in maven-dependency-plugin pour copier les fichiers EAR de tous les sous-modules de mon projet multi-module dans un répertoire relatif au répertoire racine de l'ensemble du projet.

C'est-à-dire que ma mise en page ressemble à ceci, les noms ont changé:

to-deploy/
my-project/
    ear-module-a/
    ear-module-b/
    more-modules-1/
        ear-module-c/
        ear-module-d/
    more-modules-2/
        ear-module-e/
        ear-module-f/
    ...

Et je veux que tous les fichiers EAR soient copiés des répertoires cible de leurs modules respectifs vers my-project/../to-deploy afin que je me retrouve avec

to-deploy/
    ear-module-a.ear
    ear-module-b.ear
    ear-module-c.ear
    ear-module-d.ear
    ear-module-e.ear
    ear-module-f.ear
my-project/
    ...

Je pourrais le faire avec un chemin relatif dans chaque module d'oreille, comme suit:

        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy</id>
                    <phase>install</phase>
                    <goals>
                        <goal>copy</goal>
                    </goals>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>${project.groupId}</groupId>
                                <artifactId>${project.artifactId}</artifactId>
                                <version>${project.version}</version>
                                <type>ear</type>
                                <outputDirectory>../../to-deploy</outputDirectory>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>

Mais je préférerais ne pas spécifier de chemin relatif dans l'élément <outputDirectory> ..__ Je préférerais quelque chose comme ${reactor.root.directory}/../to-deploy, mais je ne trouve rien de ce genre.

Aussi, je préférerais s'il y avait un moyen d'hériter de cette configuration de plug-in maven-dependency, donc je n'ai pas à le spécifier pour chaque module EAR.

J'ai également essayé d'hériter une propriété personnalisée à partir du pom racine:

<properties>
    <myproject.root>${basedir}</myproject.root>
</properties>

Mais quand j'ai essayé d'utiliser ${myproject.root} dans les POM de l'oreille-module, le ${basedir} se résolvait en fonction du module de l'oreille.

Aussi, j'ai trouvé http://labs.consol.de/lang/de/blog/maven/project-root-path-in-a-maven-multi-module-project/ où il est suggéré que chaque développeur et probablement le serveur d'intégration continue devrait configurer le répertoire racine dans un fichier profiles.xml, mais je ne le considère pas comme une solution.

Alors, y a-t-il un moyen facile de trouver la racine d'un projet multi-module?

60

Depuis Maven 3.3.1, vous pouvez utiliser ${maven.multiModuleProjectDirectory} à cette fin . (Grâce à https://stackoverflow.com/a/48879554/302789 )

edit: cela ne semble fonctionner correctement que si vous avez un dossier .mvn à la racine de votre projet.

18
Grégory Joseph

utiliser ${session.executionRootDirectory}

Pour mémoire, ${session.executionRootDirectory} fonctionne pour moi dans les fichiers pom de Maven 3.0.3. Cette propriété sera le répertoire dans lequel vous vous exécutez. Exécutez le projet parent et chaque module peut obtenir le chemin d'accès à ce répertoire racine.

Je mets la configuration du plugin qui utilise cette propriété dans le pom parent afin qu'il soit hérité. Je l'utilise dans un profil que je sélectionne uniquement lorsque je sais que je vais exécuter Maven sur le projet parent. De cette façon, il est moins probable que j'utilise cette variable de manière non souhaitée lorsque j'exécute Maven sur un projet enfant (car la variable ne serait donc pas le chemin d'accès au parent).

Par exemple,

<plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-artifact</id>
            <phase>package</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>${project.artifactId}</artifactId>
                        <version>${project.version}</version>
                        <type>${project.packaging}</type>
                    </artifactItem>
                </artifactItems>
                <outputDirectory>${session.executionRootDirectory}/target/</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>
65
anonymous

Quelque chose que j'ai utilisé dans mes projets est de remplacer la propriété dans les sous-modules poms.

    root:           <myproject.root>${basedir}</myproject.root>
    moduleA:        <myproject.root>${basedir}/..</myproject.root>
    other/moduleX:  <myproject.root>${basedir}/../..</myproject.root>

De cette façon, vous avez toujours les chemins relatifs, mais vous pouvez définir un plugin une fois dans le module racine et vos modules en hériteront avec la bonne substitution pour myproject.root.

20
Karel Vervaeke

Il existe un plugin maven qui résout ce problème particulier: directory-maven-plugin

Il assignera le chemin racine de votre projet à une propriété de votre choix. Voir l'objectif highest-basedir dans la documentation.

Par exemple:

<!-- Directory plugin to find parent root directory absolute path -->
<plugin>
  <groupId>org.commonjava.maven.plugins</groupId>
  <artifactId>directory-maven-plugin</artifactId>
  <version>0.1</version>
  <executions>
    <execution>
      <id>directories</id>
      <goals>
        <goal>highest-basedir</goal>
      </goals>
      <phase>initialize</phase>
      <configuration>
        <property>main.basedir</property>
      </configuration>
    </execution>
  </executions>
</plugin>

Utilisez ensuite ${main.basedir} n'importe où dans votre pom.xml parent/enfant. 

16
Andrejs

Comme d'autres l'ont suggéré, directory-maven-plugin est la voie à suivre . Cependant, j'ai trouvé que cela fonctionnait mieux avec l'objectif 'directory-of', comme décrit ici: https://stackoverflow.com/a/37965143/6498617 .

Je préfère cela car l’utilisation de la base de serveurs hauts ne fonctionne pas pour moi avec un projet multi-module, avec des poms multi-modules imbriqués. Le but directory-of vous permet de définir une propriété sur le chemin de n'importe quel module du projet entier, y compris la racine bien sûr . C'est également mieux que $ {session.executionRootDirectory}, car il fonctionne toujours, indépendamment de que vous construisiez la racine ou un sous-module, et quel que soit le répertoire de travail actuel d'où vous venez.

4
sparkyd

J'ai rencontré un problème similaire car j'avais besoin de copier des fichiers entre projets. Ce que Maven fait est logique car cela maintiendra le fichier pom.xml installé dans le référentiel à l’écart de la valeur codée en dur.

Ma solution était de mettre le répertoire copié dans un artefact Maven, puis d’utiliser Ant pour extraire/copier

2
M.Hoang

Une autre solution consisterait à utiliser une tâche ant pour écrire "rootdir = $ {basedir}" sur un target/root.properties dans le projet racine, puis utiliser le plugin Properties pour relire ce fichier. Je n'ai pas essayé moi-même, mais je suppose que ça devrait marcher ..?

1
neu242

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

1
Vic

Je ne suis pas au courant d'un moyen "agréable" de trouver la racine d'un projet multi-module. Mais vous pouvez peut-être améliorer un peu votre approche actuelle. 

Une première solution consisterait à créer un module supplémentaire directement sous le projet racine, à déclarer tous les fichiers EAR en tant que dépendances et à utiliser dependency:copy-dependencies pour copier les dépendances du module dans le répertoire to-deploy (relativement). Oui, le chemin serait toujours relatif, mais comme la configuration du plug-in de dépendance serait centralisée, je ne trouve pas cela agaçant.

Une deuxième solution consisterait à utiliser Maven Assembly Plugin au lieu de Maven Dependency Plugin pour créer une distribution utilisant le format dir (cela créera une distribution dans un répertoire). C'est en fait ce que je ferais.

1
Pascal Thivent

ainsi, quelque part dans les propriétés d’un projet parent, j’ai le fichier que j’ai besoin de relier plus tard, c’est pourquoi j’ai besoin d’un chemin absolu partout. Donc, je l'obtiens avec l'aide de groovy :

<properties>    
<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); 
          } 
        } 
        // setting path together with file name in variable xyz_format 
        project.properties['xyz_format'] =f.getAbsolutePath() 
                            + File.separator 
                            + "abc_format.xml"; 
</source>
</properties>   

et alors:

  <properties>
     <snapshots>http://localhost:8081/snapshots<snapshots>
     <releases>http://localhost:8081/releases</releases>
     <sonar>jdbc:Oracle:thin:sonar/sonar@localhost/XE</sonar>
     <sonar.jdbc.username>sonar</sonar.jdbc.username>
     <format.conf> ${xyz_format}</format.conf>  <---- here is it!
    </properties>

Ça marche!

0
Iakov Senatov