Recupera la versione da maven pom.xml nel codice


256

Qual è il modo più semplice per recuperare il numero di versione dal codice pom.xml di maven nel codice, cioè programmaticamente?

Risposte:


264

Supponendo che tu stia utilizzando Java, puoi farlo

  1. Crea un .propertiesfile nella (più comunemente) src/main/resourcesdirectory (ma al passaggio 4 potresti dirlo di cercare altrove).

  2. Imposta il valore di alcune proprietà nel tuo .propertiesfile usando la proprietà Maven standard per la versione del progetto: foo.bar=${project.version}

  3. Nel tuo codice Java, carica il valore dal file delle proprietà come risorsa dal percorso di classe (google per copiosi esempi di come eseguire questa operazione, ma ecco un esempio per cominciare ).

  4. In Maven, abilita il filtro delle risorse - questo farà sì che Maven copi quel file nelle tue classi di output e traduca la risorsa durante quella copia, interpretando la proprietà. Puoi trovare alcune informazioni qui, ma per lo più fai questo nel tuo pom:

    <Costruzione>
      <risorse>
        <Risorsa>
          <Directory> src / main / risorse </ directory>
          <Filtraggio> true </ filtraggio>
        </ Risorsa>
      </ Risorse>   
    </ Build>

Puoi anche ottenere altre proprietà standard come project.name, project.descriptiono anche proprietà arbitrarie che hai inserito nel tuo pom <properties>, ecc. Il filtro delle risorse, combinato con i profili Maven, può darti un comportamento di compilazione variabile al momento della compilazione. Quando si specifica un profilo in fase di runtime con -PmyProfile, ciò può abilitare le proprietà che possono quindi essere visualizzate nella build.


2
Ho trovato un codice presente che nessun cambiamento Maven config.
Wendel,

7
Prestare attenzione all'utilizzo del filtro direttamente src/main/resources, poiché ciò potrebbe elaborare tutti i file presenti in questa directory, inclusi i file binari. Per evitare comportamenti imprevedibili, è meglio fare un filtro su una src/main/resources-filtereddirectory, come suggerito qui . Comunque, grazie per questo bel trucco!
SiZiOUS,

1
La risposta di seguito che utilizza MavenXppReader per ottenere il modello effettivo è davvero utile, in quanto non è necessario eseguire nulla per trovare il valore. Nei casi in cui è necessario conoscere la versione prima di eseguire qualsiasi cosa, guardare le risposte di seguito; è stato molto utile per me far sapere a Gradle quale versione ha un progetto maven verificato, così ho potuto conoscere in anticipo la posizione del vaso di output.
Ajax,

92

La risposta accettata può essere il modo migliore e più stabile per ottenere staticamente un numero di versione in un'applicazione , ma in realtà non risponde alla domanda originale: come recuperare il numero di versione del manufatto da pom.xml? Quindi, voglio offrire un'alternativa che mostra come farlo dinamicamente durante il runtime:

Puoi usare Maven stesso. Per essere più precisi, puoi usare una libreria Maven.

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

E poi fai qualcosa del genere 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());
    }
}

Il registro della console è il seguente:

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

Aggiornamento 2017-10-31: per rispondere alla domanda di follow-up di Simon Sobisch ho modificato l'esempio in questo modo:

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
Questo è quasi identico a quello che uso e funziona bene quando avviato da eclipse, ma non quando viene avviato dal normale packaged jar (le classi di dipendenza non sono integrate) e non funziona se impacchettato con maven-assembly-plugin jar-with-dependenciesche ottengo a java.io.FileNotFoundException: pom.xml(è nel vaso finale come META-INF/maven/my.package/myapp/pom.xml) - qualche suggerimento su come risolverlo?
Simon Sobisch,

1
La mia soluzione è pensata per funzionare in modo dinamico in ambienti di sviluppo, ad esempio quando viene utilizzata in test o strumenti avviati da IDE o console. La risposta accettata a questa domanda mostra diversi modi per impacchettare staticamente il numero di versione nei tuoi artefatti. Non pensavo che pom.xml sarebbe stato disponibile all'interno dei JAR. Bello per te che ce l'hai lì, però. Forse potresti semplicemente regolare il percorso quando apri il lettore di file e forse renderlo dipendente dalla situazione del classloader. Dovrei provare da solo. Sentiti libero di porre domande di follow-up se questo non aiuta.
Kriegaex,

2
Ciao @SimonSobisch, ho appena aggiornato la mia risposta per mostrarti come fare quello che vuoi. Ma tieni presente che l'ho appena fatto in modo rapido e sporco, non mi piace particolarmente il codice con i costruttori nidificati.
Kriegaex,

75

Gli artefatti confezionati contengono un META-INF/maven/${groupId}/${artifactId}/pom.propertiesfile il cui contenuto è simile:

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

Molte applicazioni utilizzano questo file per leggere la versione dell'applicazione / jar in fase di esecuzione, non è richiesta alcuna installazione.

L'unico problema con l'approccio sopra è che questo file è (attualmente) generato durante la packagefase e quindi non sarà presente durante i test, ecc. (C'è un problema con Jira per cambiarlo, vedere MJAR-76 ). Se questo è un problema per te, l'approccio descritto da Alex è la strada da percorrere.


10
per le persone che cercano un esempio leggendo le proprietà, questo post esamina
chrismarx,

43

Esiste anche il metodo descritto in Modo semplice per visualizzare il numero di versione delle app tramite Maven :

Aggiungi questo a 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>

Quindi usa questo:

App.class.getPackage().getImplementationVersion()

Ho trovato questo metodo più semplice.


18
-1 - Questa soluzione non ha funzionato per me; il valore di getImplementationVersion()era null. (Maven versione 3.0.4)
Jesse Webb,

7
a seconda della fase ... funziona solo quando il manufatto viene confezionato, quindi non funziona sui test unitari: - /
wikier

2
Per i .warmanufatti, ricorda di usare maven-war-plugininvece dimaven-jar-plugin
cs_pupil il

Per me, questo funziona in Tomcat 8 , ma non funziona in Tomcat 7 ( getImplementationVersion()restituisce null).
Alfonso Nishikawa,

18

Se usi imballaggi mvn come jar o war, usa:

getClass().getPackage().getImplementationVersion()

Legge una proprietà "Versione di implementazione" del META-INF / MANIFEST.MF generato (che è impostato sulla versione di pom.xml) nell'archivio.


18

A complemento di ciò che ha pubblicato @kieste, che penso sia il modo migliore per avere Maven a costruire informazioni disponibili nel tuo codice se stai usando Spring-boot: la documentazione su http://docs.spring.io/spring-boot/ docs / current / reference / htmlsingle / # production-ready-application-info è molto utile.

Devi solo attivare gli attuatori e aggiungere le proprietà di cui hai bisogno nel tuo application.propertiesoapplication.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

Utilizzare questa libreria per semplificare una soluzione semplice. Aggiungi al manifest tutto ciò di cui hai bisogno e poi esegui una query per stringa.

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

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


3

A volte la riga di comando di Maven è sufficiente quando si esegue lo scripting di qualcosa correlato alla versione del progetto, ad esempio per il recupero di artefatti tramite URL da un repository:

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

Esempio di utilizzo:

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>

Ottieni la versione utilizzando this.getClass().getPackage().getImplementationVersion()

PS Non dimenticare di aggiungere:

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

0

Con riferimento alla risposta di Ketankk :

Sfortunatamente, l'aggiunta di questo ha incasinato il modo in cui la mia applicazione ha gestito le risorse:

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

Ma usare questo tag <manifest> all'interno di maven-assemble-plugin ha funzionato:

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

Quindi sono stato in grado di ottenere la versione utilizzando

String version = getClass().getPackage().getImplementationVersion();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.