Generieren Sie eine Version.java-Datei in Maven

Lesezeit: 13 Minuten

Benutzer-Avatar
Ralf

Ich habe ein Java-Projekt, das ich mit einem Ant-Skript baue. Ich versuche, das Projekt in Maven zu konvertieren.

Eine der Aufgaben generiert eine Java-Quelldatei namens Version.java, die eine statische String-Darstellung des Kompilierungszeitstempels enthält, wie folgt:

package com.foo.bar;
public final class Version {
 public static String VERSION="100301.1046";
}

Die Ant-Aufgabe ist sehr einfach:

<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>

Ist es möglich, etwas Ähnliches in Maven mit generate-sources oder einer anderen einfachen Methode zu tun?

Benutzer-Avatar
Romain Linsolas

Ich glaube nicht, dass dies der richtige Weg ist, um diese Art von Problem zu lösen.

Ein besserer Weg ist, die Versionsinformationen in a zu setzen properties Datei, die von Ihrem Java-Programm gelesen wird:

Ihre Eigenschaftendatei enthält die folgende Zeile:

myapp.version=${project.version}

Dann in Ihrem pom.xmlzeigen an, dass die Datei sein wird gefiltert von Maven:

<resources>
    <resource>
        <directory>the/directory/that/contains/your/properties/file</directory>
        <filtering>true</filtering>
    </resource>
</resources>

Wenn Maven Ihre Anwendung erstellt, wird es alle ersetzen ${...} nach ihrem Wert. Standardmäßig, ${project.version} definiert die Version der pom.xml (dh der Wert der <version> Schild).

Dann müssen Sie in Ihrem Java-Code nur noch die laden properties Datei und rufen Sie die ab myApp.version Eigentumswert.

Beachten Sie, dass Sie die verwenden können Build-Nummer-Plugin um etwas “Komplexeres” als nur Ihre aktuelle Version festzulegen (z. B. wenn Sie die Build-Zeit in Ihre Eigenschaft einfügen möchten).

  • Ich denke, dieser Ansatz ist großartig, aber nicht anwendbar, wenn Sie eine Anmerkung wie @PersistentUnit(value=”myPU”) haben. Was denken Sie über diesen Fall?

    – Guido

    31. Mai 2011 um 16:03 Uhr

  • Wenn Sie Maven 3.x verwenden, ersetzen Sie ${pom.version} (jetzt veraltet) mit ${project.version}. docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide

    – Lukasstevo

    24. November 2013 um 22:26 Uhr

  • Warum ist es nicht der gute Weg, es zu lösen? Ich habe mehrere Module mit disjunkten Sätzen von Eigenschaftendateien. Ich glaube, dass das Speichern in mehreren Eigenschaftendateien der falsche Weg ist.

    – mirelon

    6. Mai 2014 um 7:38 Uhr

  • @mirelon Aus vielen Gründen ist Wartbarkeit einer davon. Das Erstellen einer Java-Datei mit der Verkettung von String aus einer Ant-Aufgabe ist etwas seltsam, und Sie können nicht sicher sein, dass Sie keinen ungültigen Code schreiben. Der Maven-Filter hat genau diesen Zweck, warum also nicht ihn verwenden?

    – Romain Linsolas

    6. Mai 2014 um 8:03 Uhr

  • Eigenschaftendateien können geändert werden oder verloren gehen. Es scheint am besten, wenn dies in die Binärdatei eingebettet ist.

    – Kerbin

    22. Januar 2015 um 0:12 Uhr

Benutzer-Avatar
spupek

Sie können auch verwenden maven-replacer-plugin wenn du das Gefühl hast, dass Ameise ein bisschen hässlich ist: Der Pom-Eintrag könnte sein:

<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>@buildnumber@</token>
                        <value>${svn.revision}</value>
                    </replacement>
                    <replacement>
                        <token>@buildtime@</token>
                        <value>${maven.build.timestamp}</value>
                    </replacement>
                    <replacement>
                        <token>@pomversion@</token>
                        <value>${project.version}</value>
                    </replacement>
                </replacements>                        
            </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Die Version.java.template könnte sein:

package com.stackoverflow;

public final class Version {

    public static final String build_number="@buildnumber@";

    public static final String build_time="@buildtime@";

    public static final String pomversion="@pomversion@";

}

  • Verwenden Sie stattdessen besser die Phase “Generate-Sources”.

    – ChRoNoN

    2. Oktober 2015 um 13:59 Uhr

Benutzer-Avatar
vegemite4me

Dies ist eine alte Frage, aber es gibt eine andere Lösung, die dies tut eine großartige Arbeit dies perfekt (im Sinne von Maven): Templating-Maven-Plugin.

Die Verwendung dieses Plugins führt dazu, dass die verarbeitete Java-Datei in die abgelegt wird target/generated-sources Ordner, wie Sie es erwarten würden. Und es fügt den Ordner darunter hinzu generated-sources zum Baupfad. Sie werden die verarbeitete Datei nicht mehr versehentlich einchecken.

Wie benutzt man

Tragen Sie zunächst Folgendes ein src/main/java-templates/com/foo/bar/Version.java:

package com.foo.bar;
public final class Version {
    public static final String VERSION = "${project.version}";
}

Fügen Sie dann Folgendes zu Ihrem POM hinzu:

<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>

Die Mappe target/generated-sources/java-templates wird von Maven zum Erstellungspfad hinzugefügt.

  • Dies funktioniert für meine, aber ich muss das Templating noch manuell starten: filter-sources. Ich bin neu bei Maven. Wie führe ich dieses Plugin aus, bevor ich Profile ändere oder jeden Build starte?

    – Roll

    4. Juli 2016 um 12:23 Uhr

  • Ja, Sie müssen Maven aufrufen, um die Quelle zu generieren, wenn Sie eine Vorlage ändern. Aber du könntest einfach anrufen mvn install und müssen sich nicht die Mühe machen, sich an das spezifische Ziel zu erinnern, das Sie verwendet haben.

    – vegemite4me

    4. Juli 2016 um 15:51 Uhr

  • @Roel dieses Plugin wird binden sich automatisch zu einer der ersten Phasen des Maven-Lebenszyklus: generate-sources. Sie müssen es also nicht manuell aufrufen, wie auch vegemite4me sagte

    – Baptist Mathus

    21. November 2016 um 9:11 Uhr


Nach weiterem Googeln kam ich auf Folgendes (in der 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>

Es scheint gut zu funktionieren und erzeugt diese Java-Datei:

package com.foo.bar;
public final class Version {
 public static String VERSION="100318.1211";
}

Benutzer-Avatar
Superole

Hier ist eine andere Lösung, die dasselbe wie Ralphs eigene Antwort erzeugt, indem sie die Filterung von Pom-Eigenschaften und eine Vorlagendatei verwendet:

Die Vorlagendatei (VersionJava.template abgelegt in src/main/resources/version):

package ${ver.package.name};
public final class ${ver.class.name} {
    public static String VERSION="${ver.buildtime}";
}

Der 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>

Das mag jetzt übertrieben erscheinen, aber es ist extrem vielseitig, und was mir am besten gefällt, ist, dass ich die Vorlagendatei in einem lesbaren Format habe (anstelle von Echo-Anweisungen im Pom). Dadurch kann ich auch die Versionsklasse ändern, ohne den pom ändern zu müssen

  • Das ist großartig! Ich würde die Zieldatei in /target/source/${ver.package.dir} ablegen und dann (unter der Annahme von Eclipse) /target/source/${ver.package.dir} als Quellordner hinzufügen. Auf diese Weise schließen Sie es aus der Quellcodeverwaltung aus

    – John Oxley

    25. Februar 2012 um 6:42 Uhr

  • @john-oxley Ich stimme zu. Die generierte Datei sollte sich im Zielordner und nicht in src befinden. Außerdem denke ich, wenn es in ‘target/generated-sources/pom/${ver.package.dir}’ abgelegt würde, würde es (unter der Annahme von NetBeans) automatisch als Quelle enthalten sein. Ich habe das noch nicht ausprobiert, aber ich werde es tun, und wenn es wie erwartet funktioniert, sollte ich meine Antwort bearbeiten 🙂

    – Superole

    27. Februar 2012 um 12:50 Uhr


  • Diese Lösung verursacht eine Endlosschleife in Eclipse 4.2 mit dem m2e-Plugin. Ich habe jedoch die Lösung ohne die Ameisenaufgabe verwendet. Den Grund für letzteres sehe ich derzeit nicht: Die Filterlösung generiert lediglich die Version.java mit den korrekten Feldern.

    – koppor

    26. November 2013 um 13:50 Uhr

Benutzer-Avatar
Gemeinschaft

Basierend auf der Antwort von @superole. Dies ist eine vereinfachte Version, ohne dass zusätzliche Eigenschaften festgelegt werden müssen. Nur die Version des Projekts wird in Version.java kopiert.

Stellen Version.java hinein src/main/templates:

package thepackage;

public final class Version {

 public static String VERSION="${project.version}";

}

Weisen Sie maven an, die Tokens in Version.java zu ersetzen

<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>

Weisen Sie Maven an, es zu wissen generated-sources/java als Baupfad:

<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>

Lassen Sie abschließend Eclipse m2e

  • Beachten Sie den neuen Erstellungspfad
  • und nicht in eine Endlosschleife zu geraten.

Der zweite Punkt wird durch das Deaktivieren mit erreicht maven-resources-plugin während des inkrementellen Builds von Eclipse.

   org.eclipse.m2e lifecycle-mapping 1.0.0      org.codehaus.mojo build-helper-maven-plugin [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 needs to be replaced by your package: Also adjust the targetPath accordingly. I found it easier to set the path in targetpath instead of having many subfolders in src/main/templates.

  • This is aweseome! I would put the target file in /target/source/${ver.package.dir} and then (assuming Eclipse) add /target/source/${ver.package.dir} as a source folder. That way you exclude it from source control

    – John Oxley

    Feb 25, 2012 at 6:42

  • @john-oxley I agree. The generated file should have been in the target folder rather than src. More over, I think if it was put in ‘target/generated-sources/pom/${ver.package.dir}’ then (assuming NetBeans) it would be included as a source automagically. I haven’t tried this yet but I will, and if it works as expected I should edit my answer 🙂

    – Superole

    Feb 27, 2012 at 12:50


  • This solution causes an endless loop in Eclipse 4.2 with the m2e plugin. I used, however, the solution without the ant task. I currently don’t see the reason for the latter: The filtering solution just generates the Version.java with the correct fields.

    – koppor

    Nov 26, 2013 at 13:50

I’m doing it using the Maven WAR Plugin adding information to the MANIFEST.MF file and later reading this MANIFEST.MF file in 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>

This configuration generates the following MANIFEST.MF file:

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

And later i’m reading this in Java like this:

  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);
  }

1035070cookie-checkGenerieren Sie eine Version.java-Datei in Maven

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy