Récupérer la version de maven pom.xml dans le code

256

Quel est le moyen le plus simple de récupérer le numéro de version du pom.xml de maven dans le code, c'est-à-dire par programmation?

mikhail
la source

Réponses:

264

En supposant que vous utilisez Java, vous pouvez

  1. Créez un .propertiesfichier dans (le plus souvent) votre src/main/resourcesrépertoire (mais à l'étape 4, vous pourriez lui dire de chercher ailleurs).

  2. Définissez la valeur d'une propriété dans votre .propertiesfichier à l'aide de la propriété Maven standard pour la version du projet: foo.bar=${project.version}

  3. Dans votre code Java, chargez la valeur du fichier de propriétés en tant que ressource à partir du chemin de classe (google pour de nombreux exemples sur la façon de procéder, mais voici un exemple pour les débutants ).

  4. Dans Maven, activez le filtrage des ressources - cela obligera Maven à copier ce fichier dans vos classes de sortie et à traduire la ressource pendant cette copie, interprétant la propriété. Vous pouvez trouver des informations ici, mais vous le faites principalement dans votre pom:

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

Vous pouvez également accéder à d' autres propriétés standard comme project.name, project.descriptionou même des propriétés arbitraires que vous mettez dans votre pom <properties>, etc. filtrage des ressources, combinée avec des profils Maven, peuvent vous donner un comportement de construction variable à temps de construction. Lorsque vous spécifiez un profil au moment de l'exécution avec -PmyProfile, cela peut activer des propriétés qui peuvent ensuite apparaître dans votre build.

Alex Miller
la source
2
J'ai trouvé un code ce qu'aucun changement config Maven.
Wendel
7
Méfiez-vous d'utiliser le filtrage directement src/main/resources, car cela peut traiter tous les fichiers situés dans ce répertoire, y compris les fichiers binaires. Pour éviter les comportements imprévisibles, il est préférable de filtrer sur un src/main/resources-filteredrépertoire, comme suggéré ici . Quoi qu'il en soit, merci pour cette belle astuce!
SiZiOUS
1
La réponse ci-dessous en utilisant le MavenXppReader pour obtenir le modèle réel est vraiment utile, car il n'a besoin de rien exécuter pour trouver la valeur. Dans les cas où vous devez connaître la version avant d'exécuter quoi que ce soit, consultez les réponses ci-dessous; il m'a été très utile de faire connaître à gradle la version d'un projet maven extrait, afin que je puisse connaître l'emplacement du pot de sortie à l'avance.
Ajax
92

La réponse acceptée peut être le moyen le meilleur et le plus stable pour obtenir un numéro de version dans une application de manière statique , mais ne répond pas réellement à la question d'origine: Comment récupérer le numéro de version de l'artefact à partir de pom.xml? Ainsi, je veux offrir une alternative montrant comment le faire dynamiquement pendant l'exécution:

Vous pouvez utiliser Maven lui-même. Pour être plus précis, vous pouvez utiliser une bibliothèque Maven.

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

Et puis faites quelque chose comme ça en 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());
    }
}

Le journal de la console est le suivant:

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

Mise à jour 2017-10-31: Afin de répondre à la question de suivi de Simon Sobisch, j'ai modifié l'exemple comme ceci:

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
la source
1
Ceci est presque identique à ce que j'utilise et fonctionne correctement lorsqu'il est démarré à partir de l'éclipse, mais ne fonctionne pas lorsqu'il est démarré à partir du packagepot d normal (les classes de dépendance ne sont pas intégrées) et ne fonctionne pas lorsqu'il est empaqueté avec maven-assembly-plugin jar-with-dependenciesque j'obtiens a java.io.FileNotFoundException: pom.xml(il se trouve dans le pot final META-INF/maven/my.package/myapp/pom.xml) - des conseils pour résoudre ce problème?
Simon Sobisch
1
Ma solution est conçue pour fonctionner de manière dynamique dans des environnements de développement, par exemple lorsqu'elle est utilisée dans des tests ou des outils démarrés depuis l'IDE ou la console. La réponse acceptée à cette question montre plusieurs façons de regrouper le numéro de version de manière statique dans vos artefacts. Je ne pensais pas du tout que pom.xml serait disponible dans les fichiers JAR. C'est bien que vous l'ayez là-bas. Peut-être pourriez-vous simplement ajuster le chemin lors de l'ouverture du lecteur de fichiers et le rendre dépendant de la situation du chargeur de classe. Je devrais essayer par moi-même. N'hésitez pas à poser des questions de suivi si cela n'aide pas.
kriegaex
2
Bonjour @SimonSobisch, je viens de mettre à jour ma réponse afin de vous montrer comment faire ce que vous voulez. Mais s'il vous plaît soyez conscient du fait que je viens de le faire rapidement et sale, je n'aime pas particulièrement le code avec les constructeurs imbriqués.
kriegaex
75

Les artefacts emballés contiennent un META-INF/maven/${groupId}/${artifactId}/pom.propertiesfichier dont le contenu ressemble à:

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

De nombreuses applications utilisent ce fichier pour lire la version de l'application / jar lors de l'exécution, aucune configuration n'est requise.

Le seul problème avec l'approche ci-dessus est que ce fichier est (actuellement) généré pendant la packagephase et ne sera donc pas présent pendant les tests, etc. (il y a un problème avec Jira pour changer cela, voir MJAR-76 ). Si c'est un problème pour vous, alors l'approche décrite par Alex est la voie à suivre.

Pascal Thivent
la source
10
pour les personnes à la recherche d'un exemple de lecture des propriétés, ce billet passe en revue
chrismarx
43

Il existe également la méthode décrite dans Easy way pour afficher le numéro de version de vos applications à l'aide de Maven :

Ajoutez ceci à 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>

Ensuite, utilisez ceci:

App.class.getPackage().getImplementationVersion()

J'ai trouvé cette méthode plus simple.

adam.lofts
la source
18
-1 - Cette solution n'a pas fonctionné pour moi; la valeur de getImplementationVersion()était null. (maven version 3.0.4)
Jesse Webb
7
en fonction de la phase ... ne fonctionne que lorsque l'artefact est emballé, donc ne fonctionne pas sur les tests unitaires: - /
wikier
2
Pour les .warartefacts, n'oubliez pas d'utiliser maven-war-pluginau lieu demaven-jar-plugin
cs_pupil
Pour moi, cela fonctionne dans Tomcat 8 , mais ne fonctionne pas dans Tomcat 7 ( getImplementationVersion()renvoie null).
Alfonso Nishikawa
18

Si vous utilisez un emballage mvn tel que pot ou guerre, utilisez:

getClass().getPackage().getImplementationVersion()

Il lit une propriété "Implementation-Version" du META-INF / MANIFEST.MF généré (qui est défini sur la version de pom.xml) dans l'archive.

électrobabe
la source
18

Pour compléter ce que @kieste a posté, ce qui, à mon avis, est le meilleur moyen pour que Maven compile les informations disponibles dans votre code si vous utilisez Spring-boot: la documentation sur http://docs.spring.io/spring-boot/ docs / current / reference / htmlsingle / # production-ready-application-info est très utile.

Il vous suffit d'activer les actionneurs et d'ajouter les propriétés dont vous avez besoin dans votre application.propertiesouapplication.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
la source
6

Utilisez cette bibliothèque pour la facilité d'une solution simple. Ajoutez au manifeste tout ce dont vous avez besoin, puis interrogez par chaîne.

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

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

fédérer
la source
3

Parfois, la ligne de commande Maven est suffisante lors de l'écriture d'un script lié à la version du projet, par exemple pour la récupération d'artefacts via une URL à partir d'un référentiel:

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

Exemple d'utilisation:

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

Obtenir la version en utilisant this.getClass().getPackage().getImplementationVersion()

PS N'oubliez pas d'ajouter:

<manifest>
    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
ketankk
la source
0

En référence à la réponse de Ketankk :

Malheureusement, l'ajout de cela a gâché la façon dont ma demande traitait les ressources:

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

Mais l'utilisation de cette balise <manifest> de maven-assemble-plugin a fait l'affaire:

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

J'ai donc pu obtenir la version en utilisant

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