回答:
特定のライブラリ/クラスのバージョン情報を取得するためにMaven固有のファイルにアクセスする必要はありません。
を使用getClass().getPackage().getImplementationVersion()
して、.jar-filesに格納されているバージョン情報を取得できますMANIFEST.MF
。幸い、Mavenは十分にスマートです。残念ながら、Mavenはデフォルトで正しい情報をマニフェストにも書き込みません。
代わりに、次のようにset とtoの<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
または別のベースポンに配置する必要があります。
<archive>
要素の詳細なドキュメントは、Maven Archiveドキュメントにあります。
上記の回答をフォローアップするために、.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
)
null
、warファイルのMANIFEST.MFには正しい情報が含まれていますが、結果は常にです。
<archiveClasses>true</archiveClasses>
-そしてそれはそれ以来確実に機能します。
これは、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;
}
ここで2つの主要なアプローチに少し時間を費やしましたが、それらは私にとってうまくいきませんでした。私はビルドにNetbeansを使用しています。Maven 3からいくつかのエラーと警告がありましたが、それらは簡単に修正できたと思います。大したことはありません。
DZoneに関するこの記事で、保守が容易で実装が簡単に見える回答を見つけました。
私はすでにresources / configサブフォルダーを持っており、私たちが自分のファイルにapp.propertiesという名前を付けて、そこに保持する可能性のあるもの(サポートURLなど)をより適切に反映しています。
唯一の注意点は、NetbeansがIDEにフィルターをかける必要があるという警告を出すことです。どこで/どうやってわからない。この時点では効果はありません。おそらく、その橋を渡る必要がある場合は、回避策があるかもしれません。幸運を祈ります。
私はmaven-assembly-plugin
私のmavenパッケージに使用しています。使用のApache Mavenのアーカイバでヨアヒム・ザウアーの答えはまた仕事ができます:
<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>
archieverはMaven共有コンポーネントの 1つであるため、複数のMavenビルドプラグインによって使用される可能性があり、archive
内部の構成を含め、2つ以上のプラグインが導入された場合にも競合する可能性があります。
これをEclipseとMavenビルドで実行するには、他の返信で説明されているようにaddDefaultImplementationEntries
とaddDefaultSpecificationEntries
pomエントリを追加してから、次のコードを使用します。
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's 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ビルドが「ターゲット/クラス」以外の場所にターゲットクラスを配置する場合、segmentsToRemoveの値を調整する必要がある場合があります。
System.getProperty("user.dir")/pom.xml
。WTP以外の場合を除いて、他の事柄にも同様に対応できると確信しています。
.getResource()
またはを使用する必要があります.getResourceAsStream()
。
私のスプリングブートアプリケーションでは、jdkを最近バージョン12に更新するまで、受け入れられた回答からの解決策が機能しました。他のすべての回答も試したところ、機能しませんでした。
その時点で、次の行を注釈の直後のスプリングブートアプリケーションの最初のクラスに追加しました @SpringBootApplication
@PropertySources({
@PropertySource("/META-INF/maven/com.my.group/my-artefact/pom.properties")
})
後で、以下を使用して、値を使用するクラスのプロパティファイルから値をappVersion
取得し、プロジェクトバージョンを取得します。
@Value("${version}")
private String appVersion;
それが誰かを助けることを願っています。
Maven互換で、あらゆる(したがってサードパーティの)クラスでも機能するシンプルなソリューション:
private static Optional<String> getVersionFromManifest(Class<?> clazz) {
try {
File file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI());
if (file.isFile()) {
JarFile jarFile = new JarFile(file);
Manifest manifest = jarFile.getManifest();
Attributes attributes = manifest.getMainAttributes();
final String version = attributes.getValue("Bundle-Version");
return Optional.of(version);
}
} catch (Exception e) {
// ignore
}
return Optional.empty();
}
mavenプロジェクトのwarファイルにあるEJBのJava 8バリアント。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!");
}
});
}
}