Получите версию артефакта Maven во время выполнения
Я заметил, что в JAR артефакта Maven атрибут project.version включен в два файла:
META-INF/maven/${groupId}/${artifactId}/pom.properties
META-INF/maven/${groupId}/${artifactId}/pom.xml
Есть ли рекомендуемый способ прочитать эту версию во время выполнения?
Ответы
Ответ 1
Вам не нужно обращаться к файлам, определенным в Maven, для получения информации о версии любой библиотеки/класса.
Вы можете просто использовать getClass().getPackage().getImplementationVersion()
, чтобы получить информацию о версии, которая хранится в .jar файлах MANIFEST.MF
. К счастью, Maven достаточно умен К сожалению, Maven также не пишет правильную информацию в манифест по умолчанию!
Вместо этого нужно изменить элемент конфигурации <archive>
в maven-jar-plugin
, чтобы установить addDefaultImplementationEntries
и addDefaultSpecificationEntries
в true
, например:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
В идеале эта конфигурация должна быть помещена в компанию pom
или другую базу-pom.
Подробную документацию элемента <archive>
можно найти в документации Maven Archive.
Ответ 2
Чтобы продолжить ответ выше, для артефакта .war
я обнаружил, что мне нужно применить эквивалентную конфигурацию к maven-war-plugin
, а не к maven-jar-plugin
:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
Это добавило информацию о версии в MANIFEST.MF
в проекте .jar
(включен в WEB-INF/lib
.war
)
Ответ 3
Вот способ получения версии из pom.properties, возвращающийся назад, чтобы получить ее из манифеста
public synchronized String getVersion() {
String version = null;
// try to load from maven properties first
try {
Properties p = new Properties();
InputStream is = getClass().getResourceAsStream("/META-INF/maven/com.my.group/my-artefact/pom.properties");
if (is != null) {
p.load(is);
version = p.getProperty("version", "");
}
} catch (Exception e) {
// ignore
}
// fallback to using Java API
if (version == null) {
Package aPackage = getClass().getPackage();
if (aPackage != null) {
version = aPackage.getImplementationVersion();
if (version == null) {
version = aPackage.getSpecificationVersion();
}
}
}
if (version == null) {
// we could not compute the version so use a blank
version = "";
}
return version;
}
Ответ 4
Я потратил некоторое время на два основных подхода здесь, и они не работали для меня. Я использую Netbeans для сборки, возможно, там будет больше. У меня были некоторые ошибки и предупреждения от Maven 3 с некоторыми конструкциями, но я думаю, что их было легко исправить. Нет biggie.
Я нашел ответ, который выглядит легко и просто реализовать в этой статье на DZone:
У меня уже есть подкаталог ресурсов /config, и я назвал свой файл: app.properties, чтобы лучше отражать то, что мы можем хранить там (например, URL-адрес поддержки и т.д.).
Единственное предостережение в том, что Netbeans дает предупреждение о том, что среда IDE должна отфильтровываться. Не знаете, где/как. На данный момент это не влияет. Возможно, для этого есть работа, если мне нужно пересечь этот мост. Удачи.
Ответ 5
Я использую maven-assembly-plugin
для моей корзины maven. Использование Apache Maven Archiver в Ответ Иоахима Зауэра также может работать:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
<executions>
<execution .../>
</executions>
</plugin>
Поскольку архиватор является одним из общих компонентов maven, он может использоваться несколькими плагинами построения maven, которые также могут иметь конфликт, если два или добавлено больше плагинов, включая конфигурацию archive
.
Ответ 6
Чтобы выполнить это в Eclipse, а также в сборке Maven, вы должны добавить записи pom addDefaultImplementationEntries
и addDefaultSpecificationEntries
, как описано в других ответах, а затем использовать следующий код:
public synchronized static final String getVersion() {
// Try to get version number from pom.xml (available in Eclipse)
try {
String className = getClass().getName();
String classfileName = "/" + className.replace('.', '/') + ".class";
URL classfileResource = getClass().getResource(classfileName);
if (classfileResource != null) {
Path absolutePackagePath = Paths.get(classfileResource.toURI())
.getParent();
int packagePathSegments = className.length()
- className.replace(".", "").length();
// Remove package segments from path, plus two more levels
// for "target/classes", which is the standard location for
// classes in Eclipse.
Path path = absolutePackagePath;
for (int i = 0, segmentsToRemove = packagePathSegments + 2;
i < segmentsToRemove; i++) {
path = path.getParent();
}
Path pom = path.resolve("pom.xml");
try (InputStream is = Files.newInputStream(pom)) {
Document doc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(is);
doc.getDocumentElement().normalize();
String version = (String) XPathFactory.newInstance()
.newXPath().compile("/project/version")
.evaluate(doc, XPathConstants.STRING);
if (version != null) {
version = version.trim();
if (!version.isEmpty()) {
return version;
}
}
}
}
} catch (Exception e) {
// Ignore
}
// Try to get version number from maven properties in jar META-INF
try (InputStream is = getClass()
.getResourceAsStream("/META-INF/maven/" + MAVEN_PACKAGE + "/"
+ MAVEN_ARTIFACT + "/pom.properties")) {
if (is != null) {
Properties p = new Properties();
p.load(is);
String version = p.getProperty("version", "").trim();
if (!version.isEmpty()) {
return version;
}
}
} catch (Exception e) {
// Ignore
}
// Fallback to using Java API to get version from MANIFEST.MF
String version = null;
Package pkg = getClass().getPackage();
if (pkg != null) {
version = pkg.getImplementationVersion();
if (version == null) {
version = pkg.getSpecificationVersion();
}
}
version = version == null ? "" : version.trim();
return version.isEmpty() ? "unknown" : version;
}
Если ваша сборка Java ставит целевые классы где-то иначе, чем "target/classes", вам может потребоваться настроить значение segmentToRemove.
Ответ 7
В моем весеннем загрузочном приложении решение из принятого ответа работало до тех пор, пока я недавно не обновил свой jdk до версии 12. Также попробовал все остальные ответы и не смог заставить его работать.
В этот момент я добавил строку ниже в первый класс моего приложения с весенней загрузкой сразу после аннотации @SpringBootApplication
@PropertySources({
@PropertySource("/META-INF/maven/com.my.group/my-artefact/pom.properties")
})
Позже я использую приведенное ниже, чтобы получить значение из файла свойств в любом классе, в котором я хочу использовать его значение, и appVersion
возвращает мне версию проекта:
@Value("${version}")
private String appVersion;
Надеюсь, это кому-нибудь поможет.
Ответ 8
Вариант Java 8 для EJB в файле war с проектом maven. Проверено на EAP 7.0.
@Log4j // lombok annotation
@Startup
@Singleton
public class ApplicationLogic {
public static final String DEVELOPMENT_APPLICATION_NAME = "application";
public static final String DEVELOPMENT_GROUP_NAME = "com.group";
private static final String POM_PROPERTIES_LOCATION = "/META-INF/maven/" + DEVELOPMENT_GROUP_NAME + "/" + DEVELOPMENT_APPLICATION_NAME + "/pom.properties";
// In case no pom.properties file was generated or wrong location is configured, no pom.properties loading is done; otherwise VERSION will be assigned later
public static String VERSION = "No pom.properties file present in folder " + POM_PROPERTIES_LOCATION;
private static final String VERSION_ERROR = "Version could not be determinated";
{
Optional.ofNullable(getClass().getResourceAsStream(POM_PROPERTIES_LOCATION)).ifPresent(p -> {
Properties properties = new Properties();
try {
properties.load(p);
VERSION = properties.getProperty("version", VERSION_ERROR);
} catch (Exception e) {
VERSION = VERSION_ERROR;
log.fatal("Unexpected error occured during loading process of pom.properties file in META-INF folder!");
}
});
}
}