Recuperar versão do maven pom.xml no código

256

Qual é a maneira mais simples de recuperar o número da versão do pom.xml do maven no código, ou seja, programaticamente?

Mikhail
fonte

Respostas:

264

Supondo que você esteja usando Java, você pode

  1. Crie um .propertiesarquivo (geralmente) no seu src/main/resourcesdiretório (mas na etapa 4 você pode pedir para procurar em outro lugar).

  2. Defina o valor de alguma propriedade em seu .propertiesarquivo usando a propriedade Maven padrão para a versão do projeto: foo.bar=${project.version}

  3. No seu código Java, carregue o valor do arquivo de propriedades como um recurso do caminho de classe (google para obter exemplos abundantes de como fazer isso, mas aqui está um exemplo para iniciantes ).

  4. No Maven, ative a filtragem de recursos - isso fará com que o Maven copie esse arquivo em suas classes de saída e traduza o recurso durante essa cópia, interpretando a propriedade. Você pode encontrar algumas informações aqui, mas na maioria das vezes você faz isso em seu pom:

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

Você também pode obter outras propriedades padrão project.name, como , project.descriptionou mesmo propriedades arbitrárias que você coloca no seu pom <properties>, etc. Quando você especifica um perfil em tempo de execução com -PmyProfile, isso pode ativar propriedades que podem aparecer na sua construção.

Alex Miller
fonte
2
Eu encontrei um código este que nenhuma mudança Maven configuração.
Wendel
7
Cuidado ao usar a filtragem diretamente src/main/resources, pois isso pode processar todos os arquivos localizados neste diretório, incluindo arquivos de binários. Para evitar comportamentos imprevisíveis, é melhor fazer a filtragem em um src/main/resources-filtereddiretório, conforme sugerido aqui . De qualquer forma, obrigado por este belo truque!
SiZiOUS
1
A resposta abaixo, usando o MavenXppReader para obter o modelo real, é realmente útil, pois não é necessário executar nada para encontrar o valor. Nos casos em que você precisa conhecer a versão antes de executar qualquer coisa, veja as respostas abaixo; foi muito útil para eu informar à gradle qual versão de um projeto maven verificado, para que eu pudesse conhecer a localização do jar de saída com antecedência.
Ajax
92

A resposta aceita pode ser a melhor e mais estável maneira de obter um número de versão em um aplicativo estaticamente , mas na verdade não responde à pergunta original: Como recuperar o número da versão do artefato do pom.xml? Portanto, quero oferecer uma alternativa mostrando como fazê-lo dinamicamente durante o tempo de execução:

Você pode usar o próprio Maven. Para ser mais exato, você pode usar uma biblioteca Maven.

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

E então faça algo parecido com isto em 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());
    }
}

O log do console é o seguinte:

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

Atualização 2017-10-31: Para responder à pergunta de acompanhamento de Simon Sobisch, modifiquei o exemplo da seguinte maneira:

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
fonte
1
Isso é quase idêntico ao que eu uso e funciona bem quando iniciado no eclipse, mas não quando iniciado no packaged jar normal (as classes de dependência não estão integradas) e não funciona quando compactado com o maven-assembly-plugin jar-with-dependenciesque recebo a java.io.FileNotFoundException: pom.xml(está no jarro final como META-INF/maven/my.package/myapp/pom.xml) - alguma dica de como resolver isso?
Simon Sobisch 28/10
1
Minha solução deve funcionar dinamicamente em ambientes de desenvolvimento, por exemplo, quando usada em testes ou ferramentas iniciadas no IDE ou no console. A resposta aceita para esta pergunta mostra várias maneiras de empacotar estaticamente o número da versão em seus artefatos. Eu não estava assumindo que o pom.xml estivesse disponível nos JARs. Bom para você que você tenha lá, no entanto. Talvez você possa ajustar o caminho ao abrir o leitor de arquivos e torná-lo dependente da situação do carregador de classes. Eu teria que tentar por mim mesmo. Sinta-se à vontade para fazer perguntas de acompanhamento, se isso não ajudar.
Kriegaex
2
Oi @SimonSobisch, Acabei de atualizar minha resposta para mostrar como fazer o que você deseja. Mas esteja ciente do fato de que eu fiz isso rápido e sujo, não gosto particularmente do código com os construtores aninhados.
Kriegaex
75

Os artefatos empacotados contêm um META-INF/maven/${groupId}/${artifactId}/pom.propertiesarquivo cujo conteúdo se parece com:

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

Muitos aplicativos usam esse arquivo para ler a versão do aplicativo / jar em tempo de execução; não é necessária nenhuma configuração.

O único problema com a abordagem acima é que esse arquivo é (atualmente) gerado durante a packagefase e, portanto, não estará presente durante os testes, etc. (existe um problema no Jira para alterar isso, consulte MJAR-76 ). Se esse é um problema para você, a abordagem descrita por Alex é o caminho a seguir.

Pascal Thivent
fonte
10
para pessoas que procuram um exemplo de ler as propriedades, este post vai ao longo de vários métodos - javablog.fr/...
chrismarx
43

Há também o método descrito em Maneira fácil de exibir o número da versão do seu aplicativo usando o Maven :

Adicione isso ao 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>

Então use isto:

App.class.getPackage().getImplementationVersion()

Eu achei esse método mais simples.

adam.lofts
fonte
18
-1 - Esta solução não funcionou para mim; o valor de getImplementationVersion()era null. (versão maven 3.0.4)
Jesse Webb
7
dependendo da fase ... só funciona quando o artefato está sendo empacotado, portanto não funciona em testes de unidade: - /
wikier
2
Para .warartefatos, lembre-se de usar em maven-war-pluginvez demaven-jar-plugin
cs_pupil
Para mim, isso funciona no Tomcat 8 , mas não no Tomcat 7 ( getImplementationVersion()retorna nulo).
Alfonso Nishikawa
18

Se você usar pacotes mvn como jar ou war, use:

getClass().getPackage().getImplementationVersion()

Ele lê uma propriedade "Implementation-Version" do META-INF / MANIFEST.MF gerado (definido como a versão do pom.xml) no arquivo morto.

electrobabe
fonte
18

Para complementar o que a @kieste postou, acho que é a melhor maneira de o Maven criar informações disponíveis no seu código se você estiver usando o Spring-boot: a documentação em http://docs.spring.io/spring-boot/ docs / current / reference / htmlsingle / # production-ready-application-info é muito útil.

Você só precisa ativar os atuadores e adicionar as propriedades necessárias em seu 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
fonte
6

Use esta biblioteca para facilitar uma solução simples. Adicione ao manifesto o que você precisar e, em seguida, consulte por string.

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

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

feder
fonte
3

Às vezes, a linha de comando do Maven é suficiente ao criar scripts para algo relacionado à versão do projeto, por exemplo, para recuperação de artefato via URL de um repositório:

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

Exemplo de uso:

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

Obter versão usando this.getClass().getPackage().getImplementationVersion()

PS Não se esqueça de adicionar:

<manifest>
    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
ketankk
fonte
0

Com referência à resposta de ketankk :

Infelizmente, adicionar isso interferiu na maneira como meu aplicativo lida com recursos:

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

Mas usar esta tag <manifest> do maven-assemble-plugin fez o truque:

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

Então eu pude obter a versão usando

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