Üst dizini gösteren Maven2 özelliği


105

Bunun gibi çok modüllü bir projem var:

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

Maven2'de (projemi yayınlamak istediğim ortama bağlı olan) bir dizi özellik tanımlamam gerekiyor. Çok fazla özellik olduğu için kullanmayacağım <properties>... Bu yüzden Properties Maven2 eklentisini kullanıyorum .

Özellikler dosyaları main-project/dizinde bulunur. Herhangi bir çocuk için özellikler dosyasını nerede bulacağını belirtmek için ana pom.xml'de doğru dizini nasıl ayarlayabilirim?

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

Yalnızca ayarlarsam <file>env_${env}.properties</file>, Maven2 ilk modülü derlediğinde main-project/env_dev.propertiesdosyayı bulamayacaktır . Eğer ayarlarsam <file>../env_${env}.properties</file>, üst seviyede veya herhangi bir alt modül seviyesinde bir hata ortaya çıkacaktır ...


1
Sadece kullan${maven.multiModuleProjectDirectory}
qoomon

Yanıtlar:


164

Ana proje dizinini bulmak için her pomda bir özellik ayarlamayı deneyin.

Ebeveynde:

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

Çocuklarda:

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

Torunlarda:

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

19
Bu önceden ayarlanmış özellikler kaldırıldı mı? ${parent.basedir}artık 3.0.4 ...
matt5784

7
Evet, bu çalışmıyor. $ {project.parent.basedir} boş olarak değerlendirilir.
Jared

22
Başarılı oldum ${project.basedir}/..ama bu gerçekten sadece katı bir dizin hiyerarşisinde olan çok modüllü projelerde işe yarıyor.
Jonathan

90
İç çekmek. İnanılmaz, Maven bunu çok zorlaştırıyor.
Stefan Haberl

5
Yukarıdaki Jonathan gibi, göreli yollar kullanmam gerekiyor, ancak file.separatordeğişkeni böyle kullanmanın en iyisi olduğunu hissediyorum<main.basedir>${project.basedir}${file.separator}..</main.basedir>
Enwired

29

En azından mevcut maven sürümünde (3.6.0) yararlanabilirsiniz ${maven.multiModuleProjectDirectory}


2
Bununla ilgili belge bulmaya çalışıyorum ve bunun dahili bir kullanım olarak tasarlandığı anlaşılıyor, gelecekte kaldırılabilir / değiştirilebilir MNG-6589
Greg Domjan

Nasıl yararlanılır? -1
hey_you

Başkalarında olduğu gibi kullanabileceğiniz bir mülktür.
qoomon

Bu cevabı kullanmamız gerektiğinden emin değilim. Bu bilete göre içseldir ve her an gidebilir. Ayrıca bu yüzden hiçbir yerde belgelenmemiştir. Hala temiz bir çözüm yok
Hilikus

21

Directory-of hedefi ile directory-maven-eklentisini kullanın .

Diğer önerilerin aksine:

  • Bu çözüm, çok modüllü projeler için işe yarar.
  • İster tüm projeyi ister bir alt modülü inşa edin, işe yarar.
  • Maven'i kök klasörden veya bir alt modülden çalıştırsanız da çalışır.
  • Her bir alt modülde göreceli bir yol özelliği ayarlamaya gerek yoktur!

Eklenti, seçtiğiniz bir özelliği projenin modüllerinden herhangi birinin mutlak yoluna ayarlamanıza izin verir. Benim durumumda onu kök modüle ayarlıyorum ... Proje kök pom'umda:

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

O andan itibaren, herhangi bir pom alt modülündeki $ {myproject.basedir} her zaman proje kök modülünün yoluna sahip olacaktır. Ve elbette, özelliği herhangi bir modüle ayarlayabilirsiniz, sadece köke değil ...


Aşama için "test" koymayın. Bana çeşitli sorunlara neden oldu. Yukarıda gösterildiği gibi harika çalışıyor.
ElectronicBlacksmith

15

Sorunumu çözmek için bir çözüm buldum: Groovy Maven eklentisini kullanarak özellik dosyalarında arama yapıyorum.

Özellikler dosyam mutlaka şu anki dizinde, ../ veya .. / .. içinde olduğundan, bu üç klasörü kontrol eden küçük bir Groovy kodu yazdım.

İşte pom.xml dosyamın özü:

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

Bu işe yarıyor, ama bundan gerçekten hoşlanmıyorum.

Yani, daha iyi bir çözümünüz varsa, yayınlamaktan çekinmeyin!


12

Gördüğüm gibi sorun şu ki, maven'deki bir ana dizine giden mutlak yolu alamıyorsunuz.

<rant> Bundan bir anti-model olarak bahsedildiğini duydum , ancak her anti-model için gerçek, meşru kullanım durumu var ve bana sadece onların kalıplarını takip edebileceğimi söylemesinden bıktım. </ rant>

Yani bulduğum iş, antrun kullanmaktı. Bunu child pom.xml dosyasında deneyin:

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

Koşarsan mvn verifyşuna benzer bir şey görmen gerekir:

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

Daha sonra ${main.basedir}diğer eklentilerden herhangi birinde kullanabilirsiniz , vb. Bunu anlamam biraz zaman aldı, umarım başka birine yardımcı olur.


bunu maven-surefire-eklentisine nasıl aktarırım?
Kalpesh Soni

7

Başka bir alternatif:

ebeveyn pomda şunları kullanın:

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

Çocuk ponponlarında bu değişkene başvurabilirsiniz.

Ana uyarı: Sizi her zaman ana ana pom dizininden komut çalıştırmaya zorlar. Ardından, yalnızca belirli bir modül için komut çalıştırmak (örneğin test edin) istiyorsanız, şu sözdizimini kullanın:

mvn testi --projeler

Bir "path_to_test_data" değişkenini parametrelemek için surefire yapılandırması şu şekilde olabilir:

<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

Aşağıdaki küçük profil benim için çalıştı. configProjenin kök dizinindeki dizine koyduğum CheckStyle için böyle bir konfigürasyona ihtiyacım vardı , böylece onu ana modülden ve alt modüllerden çalıştırabilirim.

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

İç içe geçmiş modüller için çalışmaz, ancak bunun için farklı exists' lere sahip birkaç profil kullanılarak değiştirilebileceğinden eminim . (Doğrulama etiketinde neden "../ .." ve geçersiz kılınan özelliğin kendisinde ".." olması gerektiği konusunda hiçbir fikrim yok, ancak yalnızca bu şekilde çalışıyor.)


Bunun neden işe yaradığını bilmiyorum (ekstra ../) ama bu en temiz çözüm gibi görünüyor (ben de
checkstyle.xml

5

Benim durumumda şu şekilde çalışıyor:

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

Bu sorunu çözmek için bir çözüm buldum: $ {parent.relativePath} kullanın

<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
Bu her zaman güvenli olmayabilir; $ {parent.relativePath} bir dosya adı içerebilir, örneğin "../pom.xml"
pimlottc

3

C projesindesiniz, proje C, B'nin alt modülü ve B, A'nın alt modülü src/test/config/etc. D modülünün dizinine C projesinden ulaşmaya çalışıyorsunuz . D ayrıca A'nın alt modülüdür. Aşağıdaki ifade, URI yolunu elde etmeyi mümkün kılar:

-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

Başka bir soruya cevap olarak , maven-properties-eklentisinin Maven bağımlılıklarında tanımlanan harici özellik tanımlayıcılarını kullanacak şekilde nasıl genişletilebileceğini gösterdim.

Bu fikri, her biri artifactId'nin bir parçası olarak ortam adına ve bir $ {env} .properties içeren birden çok tanımlayıcı kavanozlara sahip olacak şekilde genişletebilirsiniz. Ardından, uygun akü ve özellikler dosyasını seçmek için özelliği kullanabilirsiniz, örneğin:

<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

Özelliği kök ana özellikler dosyasına yazmak için yukarıdan harika betiği iyileştiriyorum:

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

Örnekte findbugs eklentisi ve çoklu modül için kullanılan uzantı modelini kullanırsanız, mutlak yollarla ilgili genel özellikleri ayarlayabileceğinizi düşünüyorum. Bir üst kullanır

çoklu modül için örnek

En üst seviye pom, ilgisiz bir yapı-yapılandırma projesine ve çoklu modül projesinin modülleri için bir uygulama-ebeveynine sahiptir. App-parent, kendisini build-config projesine bağlamak ve ondan kaynakları almak için uzantıyı kullanır. Bu, ortak yapılandırma dosyalarını modüllere taşımak için kullanılır. Mülkler için de bir kanal olabilir. En üst dizini, build-config tarafından kullanılan bir özellik dosyasına yazabilirsiniz. (çok karmaşık görünüyor)

Sorun, bunun işe yaraması için çoklu modül projesine yeni bir üst seviyenin eklenmesi gerektiğidir. Gerçekten alakasız bir yapı-yapılandırma projesiyle yan adım atmaya çalıştım, ancak bu kludgy ve kırılgan görünüyordu.


0

Bu, romaintaz'ın cevabını genişletir; bu, sorunu çözmesi ve maven'in eksik işlevselliğini açıkça ortaya koyması açısından harika. Eklentinin daha sonraki bir sürümünü aldım ve projenin 3 seviyeden daha derin olabileceği durumu ekledim.

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

Dosya adını tanımlamak için bir özellik kullanmamayı seçtim. Build.properties bulunmazsa, bunun sonsuza kadar döneceğini unutmayın. Bir .git dir algılama ekledim, ancak yanıtı fazla karmaşıklaştırmak istemedim, bu yüzden burada gösterilmiyor.

  <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

Çok modüllü projenin ana projesine yerleştirilen yerel depo için benzer sorunu çözmem gerekiyordu. Esasen gerçek yol ${basedir}/ lib idi. Sonunda şu konuya karar verdim parent.pom:

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

Bu basedirher zaman mevcut yerel modüle gösterir, "ana" projeye giden yolu bulmanın bir yolu yoktur (Maven'in utancı). Alt modüllerimden bazıları bir kat daha derin, bazıları iki kat daha derin, ancak hepsi doğrudan alt modüller repo URL'sini tanımlayan ebeveynin .

Yani bu genel olarak sorunu çözmez. Bunu her zaman Clay'in kabul ettiği yanıtla birleştirebilir ve başka bir özellik tanımlayabilirsiniz - iyi çalışır ve yalnızca değerin kaynaklandığı durumlarda yeniden tanımlanması gerekir.parent.pom yeterince iyi olmadığı . Ya da sadece POM yapılarında yaptığınız eklentiyi yeniden yapılandırabilirsiniz (diğer alt modüllerin ebeveynleri). Mülke çıkarılan değer, özellikle eklenti yapılandırmasında hiçbir şey değişmediğinde, daha fazla yerde ihtiyacınız varsa muhtemelen daha iyidir.

basedirDeğeri kullanmak burada temel kısımdı, çünkü URL file://${project.parent.relativePath}/libhile yapmak istemiyordu (göreli yapmak için bir eğik çizgiyi kaldırdım). Bana iyi bir mutlak yol sağlayan özelliği kullanmak ve ondan göreceli olmak gerekliydi.

Yol URL / URI olmadığında, büyük olasılıkla bırakılması böyle bir sorun değildir basedir.


0

$ {Basedir} .. \ src \ kullanarak yukarıdaki dizine eriştim


1
Evet fakat hayır. İçin sub-module1, bunun dizininde işaret eder module2, değil main-project.
Romain Linsolas

-1

Denedin ../../env_${env}.propertiesmi

Normalde modül2 alt modüllerle aynı seviyede olduğunda aşağıdakileri yaparız

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

Sanırım ../ .. iki seviye atlamanıza izin verir. Değilse, eklenti yazarlarıyla iletişime geçip bunun bilinen bir sorun olup olmadığını görmek isteyebilirsiniz.


Ana pom.xml dosyasına ../../env.props koyarsam, Maven2 ana pomu ve tüm moduleX'i oluşturmaya çalıştığında bir hata alacağım. Bu yapılandırma aslında sadece tüm alt modüller için çalışacak ...
Romain Linsolas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.