Отримайте версію з Maven pom.xml у коді


255

Який найпростіший спосіб отримати номер версії з maven's pom.xml у коді, тобто програмно?

Відповіді:


262

Якщо припустити, що ви використовуєте Java, ви можете

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

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

  3. У свій код Java завантажте значення з файлу властивостей як ресурс з classpath (google для рясних прикладів того, як це зробити, але ось приклад для початківців ).

  4. У Maven увімкніть фільтрацію ресурсів - це призведе до того, що Maven скопіює цей файл у свої вихідні класи та перекладе ресурс під час цієї копії, інтерпретуючи властивість. Ви можете знайти тут трохи інформації, але ви здебільшого просто робите це у своєму пам’яті:

    <будувати>
      <ресурси>
        <ресурс>
          <directory> src / main / ресурси </directory>
          <filtering> true </filtering>
        </resource>
      </resources>   
    </build>

Ви також можете дістатись до інших стандартних властивостей, таких як project.name, project.descriptionабо навіть довільних властивостей, які ви вводите в свій пом <properties>і т.д. Якщо ви вкажете профіль під час виконання -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());
  }
}

1
Це майже ідентично тому, що я використовую, і працює добре, коли запускається із затемнення, але не працює, коли запускається із звичайного packaged jar (класи залежностей не інтегровані) та не працює, коли пакується із плагіном maven-Assembly-плагін, який jar-with-dependenciesя отримую a java.io.FileNotFoundException: pom.xml(це в остаточній банці як 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
для людей, які шукають приклад, який читає властивості, ця публікація має кілька методів - javablog.fr/…
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()

Я знайшов цей метод більш простим.


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()повертає null).
Альфонсо Нішікава

18

Якщо ви використовуєте mvn упаковку, таку як баночка чи війна, використовуйте:

getClass().getPackage().getImplementationVersion()

Він зчитує властивість "Впровадження-версія" згенерованого META-INF / MANIFEST.MF (що встановлено у версії pom.xml) в архіві.


18

Щоб доповнити те, що опублікував @kieste, я вважаю, що це найкращий спосіб забезпечити доступ до Maven збирати інформацію у своєму коді, якщо ви використовуєте Spring-boot: документація на http://docs.spring.io/spring-boot/ docs / current / reference / htmlsingle / # інформація про виробництво, готове до застосування є дуже корисним.

Вам просто потрібно активувати приводи та додати потрібні властивості у свій 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@

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

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>

0

З посиланням на відповідь ketankk :

На жаль, додавши це зіпсуто з тим, як моя програма поводилася з ресурсами:

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

Але використовуючи цей всередині тегу <manifest> плагін maven-assemble-plugin, вдалося зробити таке:

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

Тож я зміг отримати версію з використанням

String version = getClass().getPackage().getImplementationVersion();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.