Создайте файл Version.java в Maven
У меня есть проект Java, который я создаю с помощью Ant script. Я пытаюсь преобразовать проект в Maven.
Одна из задач создает исходный файл Java с именем Version.java, который содержит статическое представление временной метки компиляции:
package com.foo.bar;
public final class Version {
public static String VERSION="100301.1046";
}
Задача Ant очень проста:
<target name="version" depends="init" description="Create Version.java">
<echo file="src/${package.dir}/Version.java" message="package ${package.name};${line.separator}" />
<echo file="src/${package.dir}/Version.java" append="true" message="public final class Version {${line.separator}" />
<echo file="src/${package.dir}/Version.java"
append="true"
message=" public static String VERSION="${buildtime}";${line.separator}" />
<echo file="src/${package.dir}/Version.java" append="true" message="}${line.separator}" />
<echo message="BUILD ${buildtime}" />
</target>
Можно ли сделать что-то подобное в Maven, используя источники генерации или какой-либо другой простой метод?
Ответы
Ответ 1
После более Googling я придумал это (в pom.xml):
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<goals>
<goal>run</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<tasks>
<property name="src.dir" value="${project.build.sourceDirectory}" />
<property name="package.dir" value="com/foo/bar" />
<property name="package.name" value="com.foo.bar" />
<property name="buildtime" value="${maven.build.timestamp}" />
<echo file="${src.dir}/${package.dir}/Version.java" message="package ${package.name};${line.separator}" />
<echo file="${src.dir}/${package.dir}/Version.java" append="true" message="public final class Version {${line.separator}" />
<echo file="${src.dir}/${package.dir}/Version.java" append="true"
message=" public static String VERSION="${buildtime}";${line.separator}" />
<echo file="${src.dir}/${package.dir}/Version.java" append="true" message="}${line.separator}" />
<echo message="BUILD ${buildtime}" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
Кажется, что он работает хорошо и создает этот файл Java:
package com.foo.bar;
public final class Version {
public static String VERSION="100318.1211";
}
Ответ 2
Я не думаю, что это хороший способ решить эту проблему.
Лучше всего разместить информацию о версии в файле properties
, который будет читаться вашей программой Java:
Ваш файл свойств будет содержать следующую строку:
myapp.version=${project.version}
Затем в вашем pom.xml
укажите, что файл будет отфильтрован Maven:
<resources>
<resource>
<directory>the/directory/that/contains/your/properties/file</directory>
<filtering>true</filtering>
</resource>
</resources>
Когда Maven создаст ваше приложение, оно заменит все ${...}
на их значение. По умолчанию ${project.version}
определяет версию pom.xml
(т.е. Значение тега <version>
).
Затем в вашем Java-коде вам просто нужно загрузить файл properties
и получить значение свойства myApp.version
.
Обратите внимание, что вы можете использовать Build Number plugin, чтобы установить что-то более "сложное", чем только ваша текущая версия (например, если вы хотите поместите время сборки в свою собственность).
Ответ 3
Вы также можете использовать maven-replacer-plugin
, если вы чувствуете, что ant немного уродлив:
Возможно, pom enrty:
<project>
...
<properties>
<version.template.file>src/main/java/com/stackoverflowVersion.java.template</version.template.file>
<version.file>src/main/java/com/stackoverflow/Version.java</version.file>
</properties>
...
<build>
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>maven-replacer-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>${version.template.file}</file>
<outputFile>${version.file}</outputFile>
<replacements>
<replacement>
<token>@[email protected]</token>
<value>${svn.revision}</value>
</replacement>
<replacement>
<token>@[email protected]</token>
<value>${maven.build.timestamp}</value>
</replacement>
<replacement>
<token>@[email protected]</token>
<value>${project.version}</value>
</replacement>
</replacements>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
Файл Version.java.template может быть:
package com.stackoverflow;
public final class Version {
public static final String build_number="@[email protected]";
public static final String build_time="@[email protected]";
public static final String pomversion="@[email protected]";
}
Ответ 4
Вот еще одно решение, которое даст то же самое, что и Ральф,
используя фильтрацию свойств pom и файл шаблона:
Файл шаблона (VersionJava.template помещен в src/main/resources/version):
package ${ver.package.name};
public final class ${ver.class.name} {
public static String VERSION="${ver.buildtime}";
}
POM:
<properties>
...
<ver.package.dir>com/foo/bar${project.artifactId}</ver.package.dir>
<ver.package.name>com.foo.bar${project.artifactId}</ver.package.name>
<ver.class.name>Version</ver.class.name>
<ver.buildtime>${maven.build.timestamp}</ver.buildtime>
<ver.template.dir>src/main/resources/version</ver.template.dir>
<ver.template.file>VersionJava.template</ver.template.file>
</properties>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>version/*</exclude>
</excludes>
</resource>
<resource>
<directory>${ver.template.dir}</directory>
<includes>
<include>*.java</include>
</includes>
<filtering>true</filtering>
<targetPath>${basedir}/src/main/java/${ver.package.dir}</targetPath>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>
<copy file="${ver.template.dir}/${ver.template.file}" tofile="${ver.template.dir}/${ver.class.name}.java" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<phase>compile</phase>
<configuration>
<tasks>
<delete file="${ver.template.dir}/${ver.class.name}.java" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Теперь это может показаться чрезмерным, но оно чрезвычайно разносторонне, и что мне больше всего нравится
что у меня есть файл шаблона в читаемом формате (а не в отчетах эха в pom).
Это также позволяет мне изменить класс версии, не изменяя pom
Ответ 5
Это старый вопрос, но есть другое решение, которое отлично выполняет отличную работу (в смысле Maven): Шаблон плагина Maven.
Использование этого плагина приводит к тому, что обработанный файл Java помещается в папку target/generated-sources
, как и следовало ожидать. И он добавляет папку под generated-sources
в путь сборки. Вы больше не будете регистрировать обработанный файл по ошибке.
Как использовать
Сначала поставьте следующее в src/main/java-templates/com/foo/bar/Version.java
:
package com.foo.bar;
public final class Version {
public static final String VERSION = "${project.version}";
}
Затем добавьте следующее к вашему POM:
<build>
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>templating-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>filtering-java-templates</id>
<goals>
<goal>filter-sources</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
Папка target/generated-sources/java-templates
добавляется в путь сборки Maven.
Ответ 6
На основе ответа от @superole. Это упрощенная версия без необходимости устанавливать дополнительные свойства. Только версия проекта скопирована в Version.java.
Поместите Version.java
в src/main/templates
:
package thepackage;
public final class Version {
public static String VERSION="${project.version}";
}
Попросите maven заменить токены в Version.java
<resources>
<resource>
<directory>src/main/templates</directory>
<includes>
<include>*.java</include>
</includes>
<filtering>true</filtering>
<targetPath>${project.build.directory}/generated-sources/java/thepackage</targetPath>
</resource>
</resources>
Попросите maven узнать generated-sources/java
как путь сборки:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/java/</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Наконец, пусть Eclipse m2e
- знать новый путь сборки
- и не попасть в бесконечную сборку цикла.
Вторая точка достигается путем отключения с помощью maven-resources-plugin во время инкрементной сборки eclipse.
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<versionRange>[1.0,)</versionRange>
<goals>
<goal>parse-version</goal>
<goal>add-source</goal>
<goal>maven-version</goal>
<goal>add-resource</goal>
<goal>add-test-resource</goal>
<goal>add-test-source</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<runOnConfiguration>true</runOnConfiguration>
<runOnIncremental>true</runOnIncremental>
</execute>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<versionRange>[1.0.0,)</versionRange>
<goals>
<goal>resources</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<runOnConfiguration>true</runOnConfiguration>
<runOnIncremental>false</runOnIncremental>
</execute>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
thepackage
должен быть заменен вашим пакетом: также соответствующим образом отрегулируйте targetPath
. Мне было проще установить путь в targetPath
вместо того, чтобы иметь много подпапок в src/main/templates
.
Ответ 7
Как было предложено @Romain, вы можете прочитать версию из файла свойств (либо /META-INF/maven/groupId/artifactId/pom.properties
, если вы можете подождать, пока не упакуете или не переверните свой собственный отфильтрованный файл, если вы не можете, или если он не предоставляет все, что вы необходимо).
И вы хотите придерживаться своего фактического класса Version
, а затем посмотрите этот поток в списке пользователей maven, который точно предлагает решение для этого (на основе плагина antrun, который вы свяжете на фазе generated-sources
).
Ответ 8
См. http://www.gxdeveloperweb.com/Blogs/Bram-de-Kruijff/Maven-secrets-filtering-sources.htm
Ответ 9
Стандартный способ сделать это с очень немногими строками XML-кода теперь - использовать плагин templating-maven.
См. мой ответ в Фильтрация исходного кода в Maven
В общем, способ Maven - описать , что, которое вы хотите сделать. Затем изобразите как. Когда требуется десятки или сотни строк XML, либо найдите правильный плагин, который это делает, либо напишите. Это было обоснование, которое создало плагин templating-maven: -).
Ответ 10
Я делаю это, используя Maven WAR Plugin, добавляя информацию в MANIFEST.MF, а затем прочитав этот файл MANIFEST.MF в Java:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Build-Time>${maven.build.timestamp}</Build-Time>
</manifestEntries>
</archive>
</configuration>
</plugin>
Эта конфигурация генерирует следующий файл MANIFEST.MF:
Manifest-Version: 1.0
Implementation-Title: MyApp
Implementation-Version: 2.11.0-SNAPSHOT
Built-By: niestroj
Specification-Title: MyApp
Implementation-Vendor-Id: com.mycompany
Build-Time: 2017-01-09 15:30
Created-By: Apache Maven 3.0.5
Build-Jdk: 1.8.0_40
Specification-Version: 2.11
И позже я читаю это в Java следующим образом:
try {
Manifest manifest = new Manifest(getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF"));
Attributes attributes = manifest.getMainAttributes();
attributes.getValue("Implementation-Version");
attributes.getValue("Build-Time");
} catch (IOException ex) {
LOGGER.debug("Error reading manifest file information", ex);
}