次のようなマルチモジュールプロジェクトがあります。
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>
を設定すると、親レベルまたはサブモジュールレベルでエラーが発生します...
各プロジェクトにプロパティを設定して、メインプロジェクトディレクトリを見つけてください。
親で:
<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>
目標のディレクトリを持つディレクトリ-maven-plugin を使用します。
他の提案とは異なり:
プラグインを使用すると、プロジェクトのモジュールの絶対パスに任意のプロパティを設定できます。私の場合、ルートモジュールに設定します...私のプロジェクトのルート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}は常にプロジェクトルートモジュールのパスを持ちます。そしてもちろん、プロパティをルートだけでなく任意のモジュールに設定できます...
私の問題を解決する解決策を見つけました。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>
これは機能していますが、私はそれが本当に好きではありません。
したがって、より良いソリューションがある場合は、投稿することをheしないでください!
私が見るように問題は、Mavenで親ディレクトリへの絶対パスを取得できないことです。
<rant> これがアンチパターンとして話されていると聞いたことがあります 、しかし、アンチパターンごとに、実際の正当なユースケースがあります。パターンに従うだけです。</ 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バージョン(3.6.0)では、${maven.multiModuleProjectDirectory}
を使用できます
別の選択肢:
親pomでは、次を使用します。
<properties>
<rootDir>${session.executionRootDirectory}</rootDir>
<properties>
子pomsでは、この変数を参照できます。
主な注意:メインの親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>
私の場合、次のように機能します。
...
<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>
次の小さなプロファイルは私のために働いた。プロジェクトのルートの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
を持つ複数のプロファイルを使用して、そのために変更できると確信しています。 (検証タグに「../ ..」、オーバーライドされたプロパティ自体に「..」が必要な理由はわかりませんが、その方法でのみ機能します。)
この問題を解決する解決策を見つけました:$ {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>
プロジェクトCにあり、プロジェクトCはBのサブモジュールであり、BはAのサブモジュールです。プロジェクトCからモジュールDのsrc/test/config/etc
ディレクトリに到達しようとします。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>
...
上記の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()
$ {basedir} ..\src \を使用して上記のディレクトリにアクセスしました
別の質問への回答 で、Maven依存関係で定義された外部プロパティ記述子を使用するためにmaven-properties-pluginを拡張する方法を示しました。
このアイデアを拡張して、それぞれが$ {env} .propertiesを含むartifactIdの一部として環境名を持つ複数の記述子jarを持つことができます。次に、プロパティを使用して、適切な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>
Findbugsプラグインとマルチモジュールの例で使用されている拡張パターンを使用すると、絶対パスに関連するグローバルプロパティを設定できる可能性があると思います。トップを使用
最上位のPOMには、関連のないbuild-configプロジェクトと、マルチモジュールプロジェクトのモジュールのapp-parentがあります。 app-parentは、拡張機能を使用して自分自身をbuild-configプロジェクトにリンクし、そこからリソースを取得します。これは、モジュールに共通の構成ファイルを運ぶために使用されます。それは同様にプロパティのコンジットかもしれません。 build-configによって消費されるプロパティファイルに最上位ディレクトリを書き込むことができます。 (複雑すぎるようです)
問題は、これを機能させるために、マルチモジュールプロジェクトに新しいトップレベルを追加する必要があることです。まったく関係のないbuild-configプロジェクトを回避しようとしましたが、それは気味が悪く、壊れやすいようでした。
マルチモジュールプロジェクトのメインプロジェクトに配置されたローカルリポジトリの同様の問題を解決する必要がありました。基本的に、実際のパスは${basedir}
/libでした。最後にparent.pom
でこれを決めました:
<repository>
<id>local-maven-repo</id>
<url>file:///${basedir}/${project.parent.relativePath}/lib</url>
</repository>
basedir
は常に現在のローカルモジュールに表示され、「マスター」プロジェクトへのパスを取得する方法はありません(Mavenの恥)。私のサブモジュールには、1階層深いものと、2階層深いものがありますが、それらはすべて、レポURLを定義する親の直接サブモジュールです。
したがって、これは一般に問題を解決しません。常にClayの受け入れられた答えと組み合わせて、他のプロパティを定義できます-うまく機能し、parent.pom
の値が十分でない場合にのみ再定義する必要があります。または、POMアーティファクト(他のサブモジュールの親)でのみ行うプラグインを再構成することもできます。プロパティに抽出された値は、特にプラグイン構成に変更がない場合に、より多くの場所で必要な場合におそらく優れています。
URL file://${project.parent.relativePath}/lib
はトリックをしたくなかったので、値にbasedir
を使用することが重要な部分でした(1つスラッシュを削除して相対化しました)。優れた絶対パスを提供するプロパティを使用し、それから相対パスが必要でした。
パスがURL/URIでない場合、basedir
をドロップすることはおそらく問題ではありません。
../../env_${env}.properties
を試しましたか?
Module2がサブモジュールと同じレベルにある場合、通常は次のことを行います
<modules>
<module>../sub-module1</module>
<module>../sub-module2</module>
<module>../sub-module3</module>
</modules>
../ ..で2レベル上にジャンプできると思います。そうでない場合は、プラグインの作成者に連絡して、これが既知の問題であるかどうかを確認してください。
これは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>