Подтвердить что ты не робот

Создайте файл 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=&quot;${buildtime}&quot;;${line.separator}" />
    <echo file="src/${package.dir}/Version.java" append="true" message="}${line.separator}" />
    <echo message="BUILD ${buildtime}" />
</target>

Можно ли сделать что-то подобное в Maven, используя источники генерации или какой-либо другой простой метод?

4b9b3361

Ответ 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=&quot;${buildtime}&quot;;${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).

Ответ 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);
  }