Tworząc aplikację Java (zarówno SE, jak i EE) można spotkać się z potrzebą zaprezentowania wersji. Jeśli korzystamy z narzędzia Maven do budowania, plik pom.xml wymusza zdefiniowanie elementu “version”. Raczej rzadko przydaje się utrzymywanie informacji o wersji w wielu miejscach w projekcie - naraża to twórców na powstanie niespójności. Na szczęście istnieją sposoby na odczytanie z poziomu aplikacji Java wersji określonej w pliku pom.xml.

Tworząc projekt, warto zacząć od zdefiniowania niezbędnych danych, które będziemy próbowali następnie odczytać:

<project xmlns="http://maven.apache.org/POM/4.0.0"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	(...)
	<groupId>pl.wercia.example</groupId>
	<artifactId>example-maven-manifest</artifactId>
	<version>1.0.0</version>
	<name>Example Maven manifest</name>
	<organization>
		<name>Wercia</name>
	</organization>
	(...)
</project>

Aby mieć dostęp do tych danych, należy pakować aplikację (do pliku jar, war itp.) wraz z odpowiednim plikiem META-INF/MANIFEST.MF. Istotne jest dodanie do niego odpowiednich informacji. Dla plików jar, pozwala na to wtyczka maven-jar-plugin (dla plików war jej odpowiednikiem jest maven-war-plugin):

<project xmlns="http://maven.apache.org/POM/4.0.0"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	(...)
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<version>3.0.2</version>
				<configuration>
					<archive>
						<manifest>
							<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
							<mainClass>pl.wercia.example.maven.manifest.MavenManifest</mainClass>
						</manifest>
					</archive>
				</configuration>
			</plugin>
		</plugins>
	</build>
	(...)
</project>

Element addDefaultImplementationEntries odpowiedzialny jest za wygenerowanie następujących wpisów:

Implementation-Title: ${project.name}
Implementation-Version: ${project.version}
Implementation-Vendor-Id: ${project.groupId}
Implementation-Vendor: ${project.organization.name}
Implementation-URL: ${project.url}

Z kolei wartość mainClass jest niewymagana i określa klasę główną, która będzie uruchamiana domyślnie dla spakowanego pliku jar.

Nie pozostaje nic innego jak odczytać interesujące informacje:

package pl.wercia.example.maven.manifest;

public class MavenManifest {

	public static void main(String[] args) {
		MavenManifest mavenManifest = new MavenManifest();
		System.out.println("Name: " + mavenManifest.getName());
		System.out.println("Version: " + mavenManifest.getVersion());
		System.out.println("Organization name: " + mavenManifest.getOrganizationName());
	}

	public String getName() {
		return this.getClass().getPackage().getImplementationTitle();
	}

	public String getVersion() {
		return this.getClass().getPackage().getImplementationVersion();
	}

	public String getOrganizationName() {
		return this.getClass().getPackage().getImplementationVendor();
	}

}

Aby przetestować działanie, wystarczy skompilować i spakować archiwum:

mvn package

Co pozwala na uruchomienie wynikowego programu:

cd target
java -jar example-maven-manifest-1.0.0.jar

W efekcie na konsoli zostanie wyświetlona nazwa projektu, wersja i organizacja.

Przykładowy projekt: