Собственность Maven2, что указывает на родительский каталог



у меня есть проект с несколькими модулями, как этот:



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


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



файлы свойств находятся в .
Как я могу установить правильный каталог в главном пом.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 компилирует первый модуль, он не найдет . Если я установил <file>../env_${env}.properties</file>, то ошибка будет поднята на родительском уровне, или на любом уровне подмодуля...

625   18  

18 ответов:

попробуйте установить свойство в каждом 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>

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

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

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

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

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

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

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

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

использовать каталог-maven-плагин с каталогом-цели.

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

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

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

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

следующий небольшой профиль работал для меня. Мне нужна была такая конфигурация для 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 ' s. (Я понятия не имею, почему там должно быть "../.."в теге проверки и просто".."в самом переопределенном свойстве, но это работает только таким образом.)

другой вариант:

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

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

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

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

mvn test --projects

конфигурация surefire для параметизации переменной "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>

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

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

-Dparameter=file:/${basedir}/../../D/src/test/config/etc
<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>
  ...

на ответ на другой вопрос Я показал, как плагин maven-properties-plugin может быть расширен для использования внешних дескрипторов свойств, определенных в зависимостях Maven.

вы можете расширить эту идею, чтобы иметь несколько дескрипторов jars, каждый с именем среды как часть artifactId, содержащий ${env}.свойства. Затем вы можете использовать свойство для выбора соответствующего файла jar и свойств, например:

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

Я просто улучшаю скрипт groovy сверху, чтобы написать свойство в корневом Родительском файле свойств:

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

Я получил доступ к dir выше, используя ${basedir}..\src\

ты ../../env_${env}.properties ?

обычно мы делаем следующее, Когда module2 находится на том же уровне, что и подмодули

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

Я думаю ../.. позволит вам прыгать на два уровня вверх. Если нет, вы можете связаться с авторами плагина и посмотреть, является ли это известной проблемой.

Я думаю, что если вы используете шаблон расширения, используемый в примере для FindBugs plugin & multimodule, вы можете установить глобальные свойства, связанные с абсолютными путями. Он использует

пример для multi модуль

POM верхнего уровня имеет несвязанный проект build-config и приложение-родитель для модулей многомодульного проекта. Приложение-родитель использует расширение, чтобы связать себя с проектом build-config и получить от него ресурсы. Это используется для переноса общих конфигурационных файлов в модули. Это может быть канал для свойств, а также. Вы можете записать верхний каталог в файл свойств, используемый build-config. (это кажется слишком сложным)

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

Это расширяет ответ romaintaz, который является удивительным в том, что решает проблему, а также четко указывает на отсутствующую функциональность maven. Я взял более позднюю версию плагина и добавил случай, когда проект может быть более 3 уровней глубиной.

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

Я решил не использовать свойство для определения имени файла. Обратите внимание, если сборка.свойства не найдены это будет вращаться вечно. Я добавил .обнаружение git dir, но не хотел усложнять ответ, поэтому это не так показанный ниже.

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

мне нужно было решить аналогичную проблему для локального репозитория, размещенного в основном проекте многомодульного проекта. По сути реальный путь был ${basedir} / lib. Наконец я остановился на этом в своем parent.pom:

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

это basedir всегда показывает текущий локальный модуль, нет способа получить путь к проекту "master" (стыд Maven). Некоторые из моих подмодулей на один Дир глубже, некоторые на два Дир глубже, но все они прямой подмодулей родителя, который определяет URL-адрес репозитория.

таким образом, это не решает проблему в целом. Вы всегда можете объединить его с принятым ответом Clay и определить какое - то другое свойство-отлично работает и нуждается в переопределении только для случаев, когда значение от parent.pom не достаточно хорошо. Или вы можете просто перенастроить плагин - что вы делаете только в артефактах POM (родители других подмодулей). Значение, извлеченное в свойство, вероятно, лучше, если вам это нужно на большем количестве мест, особенно когда ничего в плагине конфигурационные изменения.

используя basedir в значении была существенная часть здесь, потому что URL file://${project.parent.relativePath}/lib не хотел делать трюк (я удалил одну косую черту, чтобы сделать ее относительной). Используя свойство, которое дает мне хороший абсолютный путь,а затем относительное от него было необходимо.

когда путь не URL / URI, это, вероятно, не такая проблема, чтобы отбросить basedir.

первый ответ должен работать. В строке наследования "родитель-потомок" задается пользовательское свойство со свойством maven-default на верхнем уровне POM (в данном случае <parent.base.directory>${project.parent.basedir}</parent.base.directory>) будет установлено, как он проходит вниз по дереву. Другими словами,${parent.base.directory} будет правильно установлен в другом дочернем POM.

Примечание Вы не должны использовать ${parent.basedir} Как ваше пользовательское свойство, потому что оно совпадает с maven-default ${project.parent.basedir} собственность. В противном случае он попадает в рекурсивную ошибку выражения в Maven. Вот почему я использую ${parent.base.directory} в ответ.

надеюсь, что это корневое решение проблемы.

Comments

    Ничего не найдено.