Pobierz wersję z maven pom.xml w kodzie


255

Jaki jest najprostszy sposób na uzyskanie numeru wersji z pom.xml maven w kodzie, tj. Programowo?

Odpowiedzi:


262

Zakładając, że używasz Java, możesz

  1. Utwórz .propertiesplik (najczęściej) w swoim src/main/resourceskatalogu (ale w kroku 4 możesz polecić mu szukać gdzie indziej).

  2. Ustaw wartość niektórych właściwości w swoim .propertiespliku za pomocą standardowej właściwości Maven dla wersji projektu: foo.bar=${project.version}

  3. W kodzie Java załaduj wartość z pliku właściwości jako zasób ze ścieżki klasy (google zawiera obszerne przykłady tego, jak to zrobić, ale oto przykład na początek ).

  4. W Maven włącz filtrowanie zasobów - spowoduje to, że Maven skopiuje ten plik do twoich klas wyjściowych i przetłumaczy zasób podczas tej kopii, interpretując właściwość. Możesz znaleźć tutaj trochę informacji , ale najczęściej robisz to w pom:

    <buduj>
      <zasoby>
        <resource>
          <katalog> src / main / resources </directory>
          <filtering> true </filtering>
        </resource>
      </resources>   
    </build>

Możesz także przejść do innych standardowych właściwości, takich jak project.name, project.descriptionlub nawet dowolnych właściwości, które umieszczasz w pom <properties>, itp. Filtrowanie zasobów w połączeniu z profilami Maven może dać ci zmienne zachowanie podczas kompilacji. Po określeniu profilu w czasie wykonywania za pomocą -PmyProfile, który może włączyć właściwości, które następnie mogą pojawić się w kompilacji.


2
Znalazłem kod to , że żadna zmiana Maven config.
Wendel,

7
Uważaj na bezpośrednie filtrowanie src/main/resources, ponieważ może to przetwarzać wszystkie pliki znajdujące się w tym katalogu, w tym pliki binarne. Aby uniknąć nieprzewidzianych zachowań, lepiej filtrować src/main/resources-filteredkatalog, jak sugerowano tutaj . W każdym razie dziękuję za tę fajną sztuczkę!
SiZiOUS,

1
Poniższa odpowiedź przy użyciu MavenXppReader do uzyskania rzeczywistego modelu jest naprawdę przydatna, ponieważ nie trzeba uruchamiać niczego, aby znaleźć wartość. W przypadkach, w których musisz znać wersję przed uruchomieniem czegokolwiek, spójrz na poniższe odpowiedzi; bardzo mi pomogło poinformować gradla, jaką wersję ma sprawdzony projekt maven, więc mogłem wcześniej poznać lokalizację wyjściowego słoika.
Ajax

92

Przyjęta odpowiedź może być najlepszym i najbardziej stabilnym sposobem na statyczne wprowadzenie numeru wersji do aplikacji , ale w rzeczywistości nie odpowiada na pierwotne pytanie: Jak uzyskać numer wersji artefaktu z pom.xml? Dlatego chcę zaoferować alternatywę pokazującą, jak to zrobić dynamicznie podczas działania:

Możesz użyć samego Maven. Mówiąc ściślej, możesz użyć biblioteki Maven.

<dependency>
  <groupId>org.apache.maven</groupId>
  <artifactId>maven-model</artifactId>
  <version>3.3.9</version>
</dependency>

A potem zrób coś takiego w Javie:

package de.scrum_master.app;

import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.FileReader;
import java.io.IOException;

public class Application {
    public static void main(String[] args) throws IOException, XmlPullParserException {
        MavenXpp3Reader reader = new MavenXpp3Reader();
        Model model = reader.read(new FileReader("pom.xml"));
        System.out.println(model.getId());
        System.out.println(model.getGroupId());
        System.out.println(model.getArtifactId());
        System.out.println(model.getVersion());
    }
}

Dziennik konsoli wygląda następująco:

de.scrum-master.stackoverflow:my-artifact:jar:1.0-SNAPSHOT
de.scrum-master.stackoverflow
my-artifact
1.0-SNAPSHOT

Aktualizacja 31.10.2017: Aby odpowiedzieć na pytanie Simona Sobischa, zmodyfikowałem przykład w następujący sposób:

package de.scrum_master.app;

import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Application {
  public static void main(String[] args) throws IOException, XmlPullParserException {
    MavenXpp3Reader reader = new MavenXpp3Reader();
    Model model;
    if ((new File("pom.xml")).exists())
      model = reader.read(new FileReader("pom.xml"));
    else
      model = reader.read(
        new InputStreamReader(
          Application.class.getResourceAsStream(
            "/META-INF/maven/de.scrum-master.stackoverflow/aspectj-introduce-method/pom.xml"
          )
        )
      );
    System.out.println(model.getId());
    System.out.println(model.getGroupId());
    System.out.println(model.getArtifactId());
    System.out.println(model.getVersion());
  }
}

1
To jest prawie identyczny do tego, co używam i działa dobrze, gdy zaczęło się od zaćmienia, ale nie kiedy rozpoczęła się od normalnego packaged słoika (zajęcia z zależnościami nie są zintegrowane) i nie działa, gdy jest zapakowany z Maven montażu plugin jar-with-dependenciesI get a java.io.FileNotFoundException: pom.xml(jest w końcowym słoju jako META-INF/maven/my.package/myapp/pom.xml) - jakieś wskazówki, jak to rozwiązać?
Simon Sobisch

1
Moje rozwiązanie ma działać dynamicznie w środowiskach programistycznych, np. Gdy jest używane w testach lub narzędziach uruchamianych z IDE lub konsoli. Akceptowana odpowiedź na to pytanie pokazuje kilka sposobów statycznego spakowania numeru wersji do artefaktów. Nie zakładałem, że plik pom.xml będzie w ogóle dostępny w plikach JAR. Fajnie, że go tam masz. Być może możesz po prostu dostosować ścieżkę podczas otwierania czytnika plików i być może uzależnić ją od sytuacji modułu ładującego klasy. Musiałbym spróbować sam. Jeśli to nie pomoże, możesz zadawać pytania uzupełniające.
kriegaex

2
Cześć @ SimonSobisch, właśnie zaktualizowałem swoją odpowiedź, aby pokazać, jak robić to, co chcesz. Ale proszę pamiętać, że zrobiłem to szybko i brudnie, nie podoba mi się kod z zagnieżdżonymi konstruktorami.
kriegaex

75

Pakowane artefakty zawierają META-INF/maven/${groupId}/${artifactId}/pom.propertiesplik, który wygląda następująco:

#Generated by Maven
#Sun Feb 21 23:38:24 GMT 2010
version=2.5
groupId=commons-lang
artifactId=commons-lang

Wiele aplikacji używa tego pliku do odczytywania wersji aplikacji / jar w czasie wykonywania, konfiguracja zerowa nie jest wymagana.

Jedynym problemem związanym z powyższym podejściem jest to, że ten plik jest (obecnie) generowany podczas packagefazy i dlatego nie będzie obecny podczas testów itp. (Istnieje problem z Jira, aby to zmienić, patrz MJAR-76 ). Jeśli jest to dla ciebie problem, to podejście opisane przez Alexa jest właściwym rozwiązaniem.


10
dla osób szukających przykładu czytającego właściwości, ten post omawia
chrismarx,

43

Istnieje również metoda opisana w Łatwy sposób wyświetlania numeru wersji aplikacji za pomocą Maven :

Dodaj to do pom.xml

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <mainClass>test.App</mainClass>
            <addDefaultImplementationEntries>
              true
            </addDefaultImplementationEntries>
          </manifest>
        </archive>
      </configuration>
    </plugin>
  </plugins>
</build>

Następnie użyj tego:

App.class.getPackage().getImplementationVersion()

Odkryłem, że ta metoda jest prostsza.


18
-1 - To rozwiązanie nie działało dla mnie; wartość getImplementationVersion()była null. (wersja maven 3.0.4)
Jesse Webb

7
w zależności od fazy ... działa tylko wtedy, gdy artefakt jest zapakowana, tak nie działa na testach jednostkowych: - /
wikier

2
W przypadku .warartefaktów pamiętaj, aby używać maven-war-pluginzamiastmaven-jar-plugin
cs_pupil

Dla mnie to działa w Tomcat 8 , ale nie działa w Tomcat 7 ( getImplementationVersion()zwraca null).
Alfonso Nishikawa

18

Jeśli używasz opakowań mvn, takich jak jar lub wojna, użyj:

getClass().getPackage().getImplementationVersion()

Odczytuje w archiwum właściwość „Implementation-Version” wygenerowanego pliku META-INF / MANIFEST.MF (ustawionego na wersję pom.xml).


18

Uzupełnienie tego, co opublikował @kieste, co moim zdaniem jest najlepszym sposobem, aby informacje o kompilacji Maven były dostępne w kodzie, jeśli używasz Spring-boot: dokumentacja na http://docs.spring.io/spring-boot/ docs / current / reference / htmlsingle / # production-ready-application-info jest bardzo przydatny.

Musisz tylko aktywować siłowniki i dodać potrzebne właściwości w swoim application.propertieslubapplication.yml

Automatic property expansion using Maven

You can automatically expand info properties from the Maven project using resource filtering. If you use the spring-boot-starter-parent you can then refer to your Maven project properties via @..@ placeholders, e.g.

project.artifactId=myproject
project.name=Demo
project.version=X.X.X.X
project.description=Demo project for info endpoint
info.build.artifact=@project.artifactId@
info.build.name=@project.name@
info.build.description=@project.description@
info.build.version=@project.version@

6

Użyj tej biblioteki dla łatwego rozwiązania. Dodaj do manifestu, czego potrzebujesz, a następnie przeprowadź zapytanie według ciągu.

 System.out.println("JAR was created by " + Manifests.read("Created-By"));

http://manifests.jcabi.com/index.html


3

Czasami wiersz polecenia Maven jest wystarczający do pisania skryptów czegoś związanego z wersją projektu, np. Do pobierania artefaktów za pomocą adresu URL z repozytorium:

mvn help:evaluate -Dexpression=project.version -q -DforceStdout

Przykład użycia:

VERSION=$( mvn help:evaluate -Dexpression=project.version -q -DforceStdout )
ARTIFACT_ID=$( mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout )
GROUP_ID_URL=$( mvn help:evaluate -Dexpression=project.groupId -q -DforceStdout | sed -e 's#\.#/#g' )
curl -f -S -O http://REPO-URL/mvn-repos/${GROUP_ID_URL}/${ARTIFACT_ID}/${VERSION}/${ARTIFACT_ID}-${VERSION}.jar

1
    <build>
            <finalName>${project.artifactId}-${project.version}</finalName>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                        <version>3.2.2</version>
                        <configuration>
                            <failOnMissingWebXml>false</failOnMissingWebXml>
                            <archive>
                                <manifest>
                                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                                    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                                </manifest>
                            </archive>
                        </configuration>
                    </plugin>
                 </plugins>
            </pluginManagement>
</build>

Pobierz wersję za pomocą this.getClass().getPackage().getImplementationVersion()

PS Nie zapomnij dodać:

<manifest>
    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>

0

W odniesieniu do odpowiedzi Ketankk :

Niestety dodanie tego pomieszało z tym, jak moja aplikacja radziła sobie z zasobami:

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>   
</build>

Ale użycie tego w tagu <manifest> maven-assemble-plugin załatwiło sprawę:

<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>

Więc mogłem uzyskać wersję za pomocą

String version = getClass().getPackage().getImplementationVersion();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.