Rufen Sie die Version von maven pom.xml im Code ab

256

Was ist der einfachste Weg, um die Versionsnummer aus der pom.xml von maven im Code abzurufen, dh programmgesteuert?

mikhail
quelle

Antworten:

263

Angenommen, Sie verwenden Java, können Sie

  1. Erstellen Sie eine .propertiesDatei in Ihrem src/main/resourcesVerzeichnis (am häufigsten) (in Schritt 4 können Sie sie jedoch anweisen, woanders zu suchen).

  2. Legen Sie den Wert einer Eigenschaft in Ihrer .propertiesDatei mithilfe der Standardeigenschaft Maven für die Projektversion fest: foo.bar=${project.version}

  3. Laden Sie in Ihrem Java-Code den Wert aus der Eigenschaftendatei als Ressource aus dem Klassenpfad (Google für zahlreiche Beispiele, aber hier ein Beispiel für den Anfang ).

  4. Aktivieren Sie in Maven die Ressourcenfilterung. Dadurch kopiert Maven diese Datei in Ihre Ausgabeklassen und übersetzt die Ressource während dieser Kopie, wobei die Eigenschaft interpretiert wird. Sie können hier einige Informationen finden, aber Sie tun dies meistens nur in Ihrem Pom:

    <build>
      <Ressourcen>
        <Ressource>
          <Verzeichnis> src / main / resources </ Verzeichnis>
          <filtering> true </ filtering>
        </ resource>
      </ resources>   
    </ build>

Sie können auch auf andere Standardeigenschaften wie erhalten project.name, project.descriptionoder auch beliebige Eigenschaften , die Sie in Ihrem pom setzen <properties>usw. Ressourcenfilterung, mit Maven Profilen kombiniert, können Sie bei der Erstellung variabler Build Verhalten geben. Wenn Sie zur Laufzeit ein Profil mit angeben -PmyProfile, können Eigenschaften aktiviert werden, die dann in Ihrem Build angezeigt werden können.

Alex Miller
quelle
2
Ich fand einen Code dies , dass keine Änderung Maven Config.
Wendel
7
Achten Sie darauf, die Filterung nicht direkt zu verwenden src/main/resources, da hierdurch möglicherweise alle in diesem Verzeichnis befindlichen Dateien verarbeitet werden, einschließlich Binärdateien. Um unvorhersehbare Verhaltensweisen zu vermeiden, ist es besser, nach einem src/main/resources-filteredVerzeichnis zu filtern , wie hier vorgeschlagen . Trotzdem danke für diesen schönen Trick!
SiZiOUS
1
Die folgende Antwort mit dem MavenXppReader zum Abrufen des tatsächlichen Modells ist sehr nützlich, da nichts ausgeführt werden muss, um den Wert zu finden. In Fällen, in denen Sie die Version kennen müssen, bevor etwas ausgeführt wird, lesen Sie die Antworten unten. Es war sehr hilfreich für mich, gradle wissen zu lassen, welche Version ein ausgechecktes Maven-Projekt hat, damit ich vorher den Speicherort des Ausgabe-JARs kennen konnte.
Ajax
92

Die akzeptierte Antwort ist möglicherweise der beste und stabilste Weg, um eine Versionsnummer statisch in eine Anwendung zu übernehmen , beantwortet jedoch nicht die ursprüngliche Frage: Wie kann die Versionsnummer des Artefakts aus pom.xml abgerufen werden? Daher möchte ich eine Alternative anbieten, die zeigt, wie dies zur Laufzeit dynamisch gemacht wird:

Sie können Maven selbst verwenden. Genauer gesagt können Sie eine Maven-Bibliothek verwenden.

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

Und dann machen Sie so etwas in Java:

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

Das Konsolenprotokoll lautet wie folgt:

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

Update 31.10.2017: Um die Folgefrage von Simon Sobisch zu beantworten, habe ich das Beispiel folgendermaßen geändert:

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());
  }
}
Kriegaex
quelle
1
Dies ist fast identisch mit dem, was ich verwende und funktioniert einwandfrei, wenn ich von Eclipse aus gestartet werde, aber nicht, wenn ich von der normalen packageD-JAR aus gestartet werde (Abhängigkeitsklassen sind nicht integriert) und funktioniert nicht, wenn jar-with-dependenciesich mit dem Maven-Assembly-Plugin gepackt bin, das ich bekomme a java.io.FileNotFoundException: pom.xml(es ist im letzten Glas als META-INF/maven/my.package/myapp/pom.xml) - irgendwelche Hinweise, wie man das löst?
Simon Sobisch
1
Meine Lösung soll in Entwicklungsumgebungen dynamisch funktionieren, z. B. wenn sie in Tests oder Tools verwendet wird, die über IDE oder Konsole gestartet wurden. Die akzeptierte Antwort auf diese Frage zeigt verschiedene Möglichkeiten, um die Versionsnummer statisch in Ihre Artefakte zu packen. Ich ging nicht davon aus, dass pom.xml überhaupt in JARs verfügbar sein würde. Schön für dich, dass du es dort hast. Vielleicht können Sie den Pfad beim Öffnen des Dateireaders einfach anpassen und ihn von der Situation des Klassenladeprogramms abhängig machen. Ich würde es selbst versuchen müssen. Wenn dies nicht hilft, können Sie gerne weitere Fragen stellen.
Kriegaex
2
Hallo @SimonSobisch, ich habe gerade meine Antwort aktualisiert, um Ihnen zu zeigen, wie Sie tun, was Sie wollen. Aber bitte beachten Sie, dass ich es gerade schnell und schmutzig gemacht habe. Ich mag den Code mit den verschachtelten Konstruktoren nicht besonders.
Kriegaex
75

Gepackte Artefakte enthalten eine META-INF/maven/${groupId}/${artifactId}/pom.propertiesDatei, deren Inhalt wie folgt aussieht:

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

Viele Anwendungen verwenden diese Datei, um die Anwendungs- / JAR-Version zur Laufzeit zu lesen. Es ist kein Setup erforderlich.

Das einzige Problem bei dem obigen Ansatz besteht darin, dass diese Datei (derzeit) während der packagePhase generiert wird und daher während Tests usw. nicht vorhanden ist (es gibt ein Jira-Problem, um dies zu ändern, siehe MJAR-76 ). Wenn dies ein Problem für Sie ist, ist der von Alex beschriebene Ansatz der richtige Weg.

Pascal Thivent
quelle
10
Für Leute, die nach einem Beispiel suchen, das die Eigenschaften liest, geht dieser Beitrag über verschiedene Methoden - javablog.fr/…
chrismarx
43

Es gibt auch die unter Einfache Methode beschriebene Methode , um die Versionsnummer Ihrer Apps mit Maven anzuzeigen :

Fügen Sie dies zu pom.xml hinzu

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

Dann benutze dies:

App.class.getPackage().getImplementationVersion()

Ich habe festgestellt, dass diese Methode einfacher ist.

adam.lofts
quelle
18
-1 - Diese Lösung hat bei mir nicht funktioniert. der Wert von getImplementationVersion()war null. (Maven Version 3.0.4)
Jesse Webb
7
abhängig von der Phase ... funktioniert nur, wenn das Artefakt verpackt wird, funktioniert also nicht bei Unit-Tests: - /
Wikier
2
.warmaven-war-pluginmaven-jar-plugin
Denken
Für mich funktioniert dies in Tomcat 8 , aber nicht in Tomcat 7 ( getImplementationVersion()gibt null zurück).
Alfonso Nishikawa
18

Wenn Sie MVN-Verpackungen wie Jar oder War verwenden, verwenden Sie:

getClass().getPackage().getImplementationVersion()

Es liest eine Eigenschaft "Implementation-Version" der generierten META-INF / MANIFEST.MF (die auf die Version von pom.xml festgelegt ist) im Archiv.

Elektrobabe
quelle
18

Als Ergänzung zu dem, was @kieste gepostet hat, ist dies meiner Meinung nach der beste Weg, um Maven-Build-Informationen in Ihrem Code verfügbar zu machen, wenn Sie Spring-boot verwenden: die Dokumentation unter http://docs.spring.io/spring-boot/ docs / current / reference / htmlsingle / # Production-Ready-Application-Info ist sehr nützlich.

Sie müssen nur die Aktuatoren aktivieren und die Eigenschaften hinzufügen, die Sie in Ihrem application.propertiesoder benötigenapplication.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@
coolnodje
quelle
6

Verwenden Sie diese Bibliothek, um eine einfache Lösung zu vereinfachen. Fügen Sie dem Manifest alles hinzu, was Sie benötigen, und fragen Sie dann nach Zeichenfolge ab.

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

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

feder
quelle
3

Manchmal reicht die Maven-Befehlszeile aus, wenn Skripte für die Projektversion erstellt werden, z. B. zum Abrufen von Artefakten über eine URL aus einem Repository:

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

Anwendungsbeispiel:

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

Holen Sie sich die Version mit this.getClass().getPackage().getImplementationVersion()

PS Vergessen Sie nicht hinzuzufügen:

<manifest>
    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
Ketankk
quelle
0

In Bezug auf Ketankks Antwort :

Leider hat das Hinzufügen dies den Umgang meiner Anwendung mit Ressourcen durcheinander gebracht:

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

Aber die Verwendung dieses <manifest> -Tags im Maven-Assemble-Plugin hat den Trick getan:

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

So konnte ich Version mit bekommen

String version = getClass().getPackage().getImplementationVersion();
Leo Lamas
quelle