親ディレクトリを示すMaven2プロパティ


105

次のようなマルチモジュールプロジェクトがあります。

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

Maven2で一連のプロパティ(プロジェクトをリリースする環境に依存する)を定義する必要があります。<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>すると、親レベルまたは任意のサブモジュールレベルでエラーが発生します...


1
そのまま使用${maven.multiModuleProjectDirectory}
qoomon

回答:


164

各プロジェクトでプロパティを設定して、メインプロジェクトディレクトリを見つけてください。

親では:

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

19
これらの事前設定されたプロパティは削除されましたか?${parent.basedir}3.0.4では何も解析されなくなりました...
matt5784

7
ええ、これはうまくいきません。$ {project.parent.basedir}はnullと評価されます。
Jared、

22
私は成功しました${project.basedir}/..が、実際には、厳密なディレクトリ階層にあるマルチモジュールプロジェクトでのみ機能します。
ジョナサン

90
はぁ。信じられないことですが、Mavenはこれを非常に困難にします。
Stefan Haberl 2013

5
上記のジョナサンのように、相対パスを使用する必要がありfile.separatorますが、このような変数を使用するのが最適だと感じています<main.basedir>${project.basedir}${file.separator}..</main.basedir>
Enwired

29

少なくとも現在のMavenバージョン(3.6.0)では、 ${maven.multiModuleProjectDirectory}


2
これに関するドキュメントを見つけようとしていて、これは内部使用として意図されているようですが、将来的に削除または変更される可能性がありますMNG-6589
Greg Domjan

それをどのように利用しますか?-1
hey_you

プロパティなので、他の人と同じように使えます。
qoomon

私はこの答えを使うべきかどうかわかりません。このチケットによるとそれは内部のものであり、いつでも行く可能性があります。それがどこにも文書化されていない理由でもあります。それでもクリーンなソリューションはありません
Hilikus

21

directory-ofgoalでdirectory-maven-pluginを使用します。

他の提案とは異なり:

  • このソリューションは、マルチモジュールプロジェクトで機能します。
  • プロジェクト全体を作成する場合でも、サブモジュールを作成する場合でも機能します。
  • ルートフォルダーまたはサブモジュールのどちらからmavenを実行しても機能します。
  • すべてのサブモジュールで相対パスプロパティを設定する必要はありません。

プラグインを使用すると、選択したプロパティをプロジェクトのモジュールの絶対パスに設定できます。私の場合は、ルートモジュールに設定します...プロジェクトのルート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>

それ以降、サブモジュールpomの$ {myproject.basedir}には常にプロジェクトルートモジュールのパスが含まれます。そしてもちろん、ルートだけでなく任意のモジュールにプロパティを設定できます...


フェーズの「テスト」を行わないでください。さまざまな問題を引き起こしました。上記のようにうまく機能します。
ElectronicBlacksmith

15

私の問題を解決する解決策を見つけました。GroovyMavenプラグインを使用してプロパティファイルを検索します。

私のプロパティー・ファイルは必ず現在のディレクトリー(../または../ ..)にあるため、これら3つのフォルダーをチェックする小さな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>

これは機能していますが、私はあまり好きではありません。

したがって、より良い解決策がある場合は、投稿することを躊躇しないでください!


12

したがって、私が見る問題は、Mavenで親ディレクトリへの絶対パスを取得できないことです。

<rant> これはアンチパターンとして話されていると聞きましたが、すべてのアンチパターンには実際の合法的なユースケースがあり、そのパターンに従うことしかできないと言っているのはうんざりです。</暴言>

そこで私が見つけた回避策は、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}、他のプラグインなどで使用できます。これを理解するのにしばらく時間がかかったので、他の人の役に立つことを願っています。


maven-surefire-pluginに渡すにはどうすればよいですか?
Kalpesh Soni 2016

7

別の選択肢:

親pomでは、次を使用します。

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

子pomでは、この変数を参照できます。

メインの注意:メインの親pomディレクトリから常にコマンドを実行する必要があります。次に、特定のモジュールに対してのみコマンド(たとえば、テスト)を実行する場合は、次の構文を使用します。

mvn test --projects

次に、 "path_to_test_data"変数をパラメーター化するためのsurefireの構成は次のようになります。

<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

次の小さなプロファイルが私にとってうまくいきました。configメインモジュールとサブモジュールから実行できるように、プロジェクトのルートのディレクトリに配置するCheckStyleにこのような構成が必要でした。

<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のいくつかのプロファイルを使用して、そのために変更できると確信しています。(検証タグに "../ .."が含まれ、オーバーライドされたプロパティ自体に ".."が含まれる理由はわかりませんが、その方法でのみ機能します。)


なぜこれが機能するのかはわかりませんが(余分な../)、これは最もクリーンなソリューションのようです(私もcheckstyle.xml構成に問題がありました)
RockMeetHardplace

5

私の場合、それはこのように動作します:

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

3

この問題を解決する解決策を見つけました:$ {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>

2
これは常に安全であるとは限りません。$ {parent.relativePath}にはファイル名を含めることができます。たとえば、「../ pom.xml」
pimlottc

3

あなたはプロジェクトCにいます。プロジェクトCはBのサブモジュールであり、BはAのサブモジュールです。src/test/config/etcプロジェクトCからモジュールDのディレクトリに到達しようとします。DはAのサブモジュールでもあります。次の式により、URIパスを取得できます。

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

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

1

別の質問への答え私は、Mavenの-プロパティ・プラグインはMavenの依存関係で定義された外部のプロパティ記述子を使用するように拡張する方法を示しました。

そのアイデアを拡張して、複数の記述子jarを作成し、それぞれに$ {env} .propertiesを含む、artifactIdの一部として環境名を指定できます。次に、プロパティを使用して、適切な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>

1

上記の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()

0

findbugsプラグインとマルチモジュールの例で使用されている拡張パターンを使用すると、絶対パスに関連するグローバルプロパティを設定できる可能性があると思います。トップを使用

マルチモジュールの例

最上位のpomには、無関係なbuild-configプロジェクトと、マルチモジュールプロジェクトのモジュールのapp-parentがあります。app-parentは拡張機能を使用して、自分自身をbuild-configプロジェクトにリンクし、そこからリソースを取得します。これは、モジュールに共通の構成ファイルを運ぶために使用されます。プロパティの導管になることもあります。build-configが使用するプロパティファイルにトップディレクトリを書き込むことができます。(複雑すぎるようです)

問題は、これを機能させるために、マルチモジュールプロジェクトに新しい最上位を追加する必要があることです。私は本当に無関係なbuild-configプロジェクトを回避しようとしましたが、それは扱いにくく、もろく見えました。


0

これはromaintazの答えを拡張します。これは問題を解決するのに素晴らしいものであり、またmavenに欠けている機能を明確に指摘しています。私はプラグインの新しいバージョンをピックアップし、プロジェクトの深さが3レベルを超える可能性があるケースを追加しました。

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

プロパティを使用してファイル名を定義しないことを選択しました。build.propertiesが見つからない場合、これは永久にスピンします。.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>

0

マルチモジュールプロジェクトのメインプロジェクトに配置されたローカルリポジトリについても、同様の問題を解決する必要がありました。基本的に、実際のパスは${basedir}/ libでした。最後に私は私の中でこれに落ち着きましたparent.pom

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

これはbasedir常に現在のローカルモジュールに表示され、「マスター」プロジェクト(Mavenの恥)へのパスを取得する方法はありません。私のサブモジュールには、1 dir深いものもあれば、2 dir深いものもありますが、すべて直接サブモジュールです。、リポジトリURLを定義する親のです。

したがって、これは一般的に問題を解決しません。常にクレイの承認済みの回答と組み合わせて、他のプロパティを定義することができます-正常に動作し、からの値parent.pomが十分でない場合にのみ再定義する必要があります。または、単にプラグインを再構成することもできます-これは、POMアーティファクト(他のサブモジュールの親)でのみ行います。プロパティに抽出された値は、より多くの場所で必要な場合、特にプラグイン構成で何も変更されていない場合に、おそらくより優れています。

basedir値での使用は、ここでは重要な部分でした。URLがfile://${project.parent.relativePath}/libがトリックを実行することを望まなかった(1つのスラッシュを削除して相対的にした)。私に良い絶対パスを与えるプロパティを使用し、それから相対的に行くことが必要でした。

パスがURL / URIでない場合、ドロップしてもそれほど問題にはなりませんbasedir


0

$ {basedir} .. \ src \を使用して上記のディレクトリにアクセスしました


1
はい、しかしいいえ。の場合はsub-module1module2ではなくのディレクトリを指しmain-projectます。
Romain Linsolas

-1

やってみました../../env_${env}.propertiesか?

通常、module2がサブモジュールと同じレベルにある場合、以下を実行します

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

../ ..を使用すると、2レベル上にジャンプできると思います。そうでない場合は、プラグインの作成者に連絡して、これが既知の問題であるかどうかを確認してください。


メインpom.xmlに../../env.propsを配置すると、Maven2がメインpomとすべてのmoduleXをビルドしようとするとエラーが発生します。この構成は実際にはすべてのサブモジュールでのみ機能します...
Romain Linsolas '19 / 06/19
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.