Получить версию из maven pom.xml в коде

256

Какой самый простой способ получить номер версии из pom.xml maven в коде, то есть программно?

михаил
источник

Ответы:

264

Предполагая, что вы используете Java, вы можете

  1. Создайте .propertiesфайл в (чаще всего) вашем src/main/resourcesкаталоге (но на шаге 4 вы можете указать, чтобы он смотрел в другом месте).

  2. Установите значение некоторого свойства в вашем .propertiesфайле, используя стандартное свойство Maven для версии проекта: foo.bar=${project.version}

  3. В своем коде Java загрузите значение из файла свойств в качестве ресурса из classpath (в Google приведены обильные примеры того, как это сделать, но вот пример для начала ).

  4. В Maven включите фильтрацию ресурсов - это заставит Maven скопировать этот файл в ваши выходные классы и перевести ресурс во время этой копии, интерпретируя свойство. Вы можете найти некоторую информацию здесь, но в основном вы просто делаете это в своей помпе:

    <Сборка>
      <ресурсы>
        <Ресурс>
          <Каталог> SRC / основные / ресурсы </ каталог>
          <Фильтрация> True </ фильтрация>
        </ Ресурс>
      </ Ресурсы>   
    </ Сборки>

Вы также можете получить другие стандартные свойства, такие как project.name, project.descriptionили даже произвольные свойства, которые вы указали в pom <properties>и т. Д. Фильтрация ресурсов в сочетании с профилями Maven может дать вам поведение при сборке во время сборки. Когда вы указываете профиль во время выполнения -PmyProfile, это может включать свойства, которые затем могут отображаться в вашей сборке.

Алекс Миллер
источник
2
Я нашел код этого , что никаких изменений Maven конфигурации.
Вендел
7
Остерегайтесь использовать фильтрацию напрямую src/main/resources, так как это может обработать все файлы, расположенные в этом каталоге, включая двоичные файлы. Чтобы избежать непредсказуемого поведения, лучше выполнить фильтрацию по src/main/resources-filteredкаталогу, как предлагается здесь . В любом случае, спасибо за этот хороший трюк!
SiZiOUS
1
Приведенный ниже ответ с использованием MavenXppReader для получения реальной модели действительно полезен, поскольку для поиска значения не нужно ничего запускать. В случаях, когда вам нужно знать версию, прежде чем что-либо запускать, посмотрите на ответы ниже; для меня было очень полезно сообщить gradle, какая версия у проверенного проекта maven, так что я мог заранее знать местоположение выходного фляги.
Аякс
92

Принятый ответ может быть лучшим и наиболее стабильным способом статического получения номера версии в приложении , но на самом деле не отвечает на первоначальный вопрос: как получить номер версии артефакта из pom.xml? Таким образом, я хочу предложить альтернативу, показывающую, как сделать это динамически во время выполнения:

Вы можете использовать сам Maven. Точнее, вы можете использовать библиотеку Maven.

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

А затем сделать что-то подобное в 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());
    }
}

Журнал консоли выглядит следующим образом:

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

Обновление 2017-10-31: Чтобы ответить на дополнительный вопрос Саймона Собиша, я изменил пример следующим образом:

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
источник
1
Это почти идентично тому, что я использую, и отлично работает, когда запускается из eclipse, но не работает, когда запускается из обычного packaged jar (классы зависимостей не интегрированы), и не работает, когда jar-with-dependenciesя получаю пакет с подключаемым плагином maven. a java.io.FileNotFoundException: pom.xml(это в последнем jar как META-INF/maven/my.package/myapp/pom.xml) - какие-либо советы, как решить эту проблему?
Симон Собиш
1
Мое решение предназначено для динамической работы в средах разработки, например, при использовании в тестах или инструментах, запущенных из IDE или консоли. Принятый ответ на этот вопрос показывает несколько способов статически упаковать номер версии в ваши артефакты. Я не предполагал, что pom.xml будет доступен в JAR-файлах вообще. Приятно, что у вас это есть. Возможно, вы можете просто изменить путь при открытии программы чтения файлов и, возможно, сделать его зависимым от ситуации загрузчика классов. Я бы попробовал для себя. Не стесняйтесь задавать дополнительные вопросы, если это не помогает.
kriegaex
2
Привет @SimonSobisch, я только что обновил свой ответ, чтобы показать вам, как делать то, что вы хотите. Но, пожалуйста, помните о том, что я сделал это быстро и грязно, мне не особо нравится код с вложенными конструкторами.
kriegaex
75

Упакованные артефакты содержат META-INF/maven/${groupId}/${artifactId}/pom.propertiesфайл, содержимое которого выглядит следующим образом:

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

Многие приложения используют этот файл для чтения версии приложения / jar во время выполнения, установка не требуется.

Единственная проблема с вышеупомянутым подходом состоит в том, что этот файл (в настоящее время) генерируется во время packageфазы и, таким образом, не будет присутствовать во время тестов и т. Д. (Существует проблема Jira, чтобы изменить это, см. MJAR-76 ). Если это проблема для вас, то подход, описанный Алексом, - путь.

Паскаль Тивент
источник
10
для людей, которые ищут пример, читающий свойства, этот пост посвящен
chrismarx
43

Существует также метод, описанный в Простом способе отображения номера версии вашего приложения с помощью Maven :

Добавьте это в 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>

Тогда используйте это:

App.class.getPackage().getImplementationVersion()

Я нашел этот метод проще.

adam.lofts
источник
18
-1 - это решение не сработало для меня; стоимость getImplementationVersion()была null. (maven версия 3.0.4)
Джесси Уэбб
7
в зависимости от фазы ... работает только тогда, когда артефакт упаковывается, поэтому не работает на модульных тестах: - /
wikier
2
Для .warартефактов, не забудьте использовать maven-war-pluginвместоmaven-jar-plugin
cs_pupil
Для меня это работает в Tomcat 8 , но не работает в Tomcat 7 ( getImplementationVersion()возвращает ноль).
Альфонсо Нишикава
18

Если вы используете упаковку mvn, такую ​​как jar или war, используйте:

getClass().getPackage().getImplementationVersion()

Он читает свойство «Version-реализации» сгенерированного файла META-INF / MANIFEST.MF (для которого установлена ​​версия pom.xml) в архиве.

electrobabe
источник
18

В дополнение к тому, что опубликовал @kieste, я думаю, что это лучший способ сделать информацию о сборке Maven доступной в вашем коде, если вы используете Spring-boot: документация по адресу http://docs.spring.io/spring-boot/ docs / current / reference / htmlsingle / # production-ready-application-info очень полезна.

Вам просто нужно активировать приводы и добавить нужные свойства в ваш application.propertiesилиapplication.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
источник
6

Используйте эту библиотеку для простоты простого решения. Добавьте в манифест все, что вам нужно, а затем выполните запрос по строке.

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

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

феде
источник
3

Иногда командной строки Maven достаточно для создания сценария, связанного с версией проекта, например, для извлечения артефактов через URL из хранилища:

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

Пример использования:

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
источник
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>

Получить версию, используя this.getClass().getPackage().getImplementationVersion()

PS Не забудьте добавить:

<manifest>
    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
ketankk
источник
0

Со ссылкой на ответ кетанкка :

К сожалению, добавление этого связано с тем, как мое приложение работает с ресурсами:

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

Но с помощью этого тега <manifest> maven-assembly-plugin все получилось:

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

Таким образом, я смог получить версию, используя

String version = getClass().getPackage().getImplementationVersion();
Лео Ламас
источник