Maven2 свойство, которое указывает родительский каталог - PullRequest
95 голосов
/ 18 июня 2009

У меня есть многомодульный проект, подобный этому:

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

Мне нужно определить набор свойств (которые зависят от среды, в которой я хочу выпустить свой проект) в Maven2. Я не буду использовать <properties>, так как есть много свойств ... Таким образом, я использую плагин Properties Maven2 .

Файлы свойств находятся в каталоге main-project/. Как я могу установить правильный каталог в основном файле pom.xml, чтобы указать дочерним элементам, где искать файл свойств?

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

Если я установлю только <file>env_${env}.properties</file>, то, когда Maven2 скомпилирует первый модуль, он не найдет файл main-project/env_dev.properties. Если я установлю <file>../env_${env}.properties</file>, то будет возникать ошибка на родительском уровне или на любом уровне субмодуля ...

Ответы [ 18 ]

149 голосов
/ 19 июня 2009

Попробуйте установить свойство в каждом pom, чтобы найти основной каталог проекта.

В родительском:

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

у детей:

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

у внуков:

<properties>
    <main.basedir>${project.parent.parent.basedir}</main.basedir>
</properties>
14 голосов
/ 19 июня 2009

Я нашел решение для решения моей проблемы: я ищу файлы свойств с помощью плагина Groovy Maven.

Поскольку мой файл свойств обязательно находится в текущем каталоге, в ../ или в .. / .., я написал небольшой код Groovy, который проверяет эти три папки.

Вот выдержка из моего 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>

Это работает, но мне это не очень нравится.

Итак, если у вас есть лучшее решение, не стесняйтесь писать!

14 голосов
/ 22 июня 2016

Используйте directory-maven-plugin с целью-каталога .

В отличие от других предложений:

  • Это решение работает для многомодульных проектов.
  • Работает, создаете ли вы весь проект или подмодуль.
  • Работает независимо от того, запускаете ли вы maven из корневой папки или субмодуля.
  • Нет необходимости устанавливать свойство относительного пути в каждом подмодуле!

Плагин позволяет установить для свойства по вашему выбору абсолютный путь к любому из модулей проекта. В моем случае я установил его в корневой модуль ... В моем проекте 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>

С этого момента $ {myproject.basedir} в любом подмодуле pom всегда имеет путь к корневому модулю проекта. И, конечно, вы можете установить свойство для любого модуля, а не только для корня ...

11 голосов
/ 29 августа 2012

Итак, проблема, как я вижу, в том, что вы не можете получить абсолютный путь к родительскому каталогу в maven.

Я слышал, что об этом говорили как об анти-паттерне , но для каждого анти-паттерна существует реальный, законный вариант использования, и я устал от того, что Мавен говорит мне Я могу только следовать их образцам.

Так что работа вокруг, которую я нашел, состояла в том, чтобы использовать antrun. Попробуйте это в дочернем 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>

Если вы запустите mvn verify, вы должны увидеть что-то вроде этого:

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

Затем вы можете использовать ${main.basedir} в любом из других плагинов и т. Д. Мне понадобилось время, чтобы понять это, поэтому надеюсь, что это поможет кому-то еще.

6 голосов
/ 02 июля 2013

У меня сработал следующий небольшой профиль. Мне нужна была такая конфигурация для CheckStyle, которую я поместил в каталог config в корне проекта, чтобы я мог запустить ее из основного модуля и из подмодулей.

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

Он не будет работать для вложенных модулей, но я уверен, что его можно изменить для этого, используя несколько профилей с разными exists. (Я понятия не имею, почему в теге подтверждения должно быть "../ .." и просто ".." в самом переопределенном свойстве, но оно работает только таким образом.)

6 голосов
/ 25 октября 2012

В моем случае это работает так:

...
<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>
5 голосов
/ 20 октября 2015

Другая альтернатива:

в родительском помпе, используйте:

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

В дочерних poms вы можете ссылаться на эту переменную.

Главное предупреждение: оно заставляет вас всегда выполнять команду из основного родительского каталога pom. Затем, если вы хотите запускать команды (например, тестировать) только для определенного модуля, используйте следующий синтаксис:

mvn test --projects

Конфигурация верного параметра для параметризации переменной «path_to_test_data» может тогда быть:

<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>
4 голосов
/ 28 марта 2019

По крайней мере, в текущей версии Maven (3.6.0) вы можете использовать ${maven.multiModuleProjectDirectory}

3 голосов
/ 17 ноября 2012

Вы находитесь в проекте C, проект C является подмодулем B, а B является подмодулем A. Вы пытаетесь получить доступ к каталогу src/test/config/etc модуля D из проекта C. D также является подмодулем A. Следующее выражение делает это возможным для получить путь URI:

-Dparameter=file:/${basedir}/../../D/src/test/config/etc
3 голосов
/ 13 июля 2012

Я нашел решение для решения этой проблемы: используйте $ {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>
...