I'm working on a Spring Boot MVC application. The requirement is to read the MANIFEST.MF file to get build number and application version number etc of this spring boot app.
For this, I have written the following bean definition for Manifest Class so that I can autowire it in the Controller class.
@Configuration
public class AppConfig{
@Bean("manifest")
public java.util.jar.Manifest getManifest()
{
// get the full name of the application manifest file
String appManifestFileName = this.getClass().getProtectionDomain().getCodeSource().getLocation().toString() + JarFile.MANIFEST_NAME;
Enumeration resEnum;
try
{
// get a list of all manifest files found in the jars loaded by the app
resEnum = Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME);
while (resEnum.hasMoreElements())
{
try
{
URL url = (URL) resEnum.nextElement();
System.out.println("Resource url=" + url.toString());
// is the app manifest file?
if (url.toString().equals(appManifestFileName))
{
// open the manifest
InputStream is = url.openStream();
if (is != null)
{
// read the manifest and return it to the application
Manifest manifest = new Manifest(is);
return manifest;
}
}
}
catch (Exception e)
{
// Silently ignore wrong manifests on classpath?
}
}
}
catch (IOException e1)
{
// Silently ignore wrong manifests on classpath?
}
return null;
}
}
The above code is taken from here. But it didn't help. It is always giving me null object.
AppController.java
@RestController
public class AppController
{
@Autowired
private Environment env;
@Autowired
@Qualifier("manifest")
private Manifest manifest;
@GetMapping("/get-app-details")
public String getAppDetails()
{
Attributes mainAttributes = manifest.getMainAttributes();
String buildNum = mainAttributes.getValue("Build-Number");
buildNum = buildNum.substring(buildNum.lastIndexOf('_') + 1);
String AppVersion = env.getProperty("App.Version") + "." + buildNum;
return "Build Number - " + buildNum + ", AppVersion - " + AppVersion;
}
}
Additional info - I'm using gradle to build this application as a war file and deploying it into external tomcat version 9.
Manifest
class? That will show you what constructors are available. However I would suggest to ditch this approach and use the Spring Boot actuator with the info endpoint to expose this information. See docs.spring.io/spring-boot/docs/current/reference/html/… – NumismatologyInputStream inputFile = new FileInputStream("/META-INF/MANIFEST.MF"); Manifest manifestObj = new Manifest(inputFile);
but I'm gettingjava.io.FileNotFoundException: \META-INF\MANIFEST.MF (The system cannot find the path specified)
– Heterogeneticsrc/main/webapp/META-INF/MANIFEST.MF
. I even tried withFileInputStream("/webapp/META-INF/MANIFEST.MF")
. But no luck – Heterogeneticjava.io.File
(which is what is used underneath) needs to be a physical file somewhere on the file system. If you package a file inside a jar/war/ear/zip it isn't a physical file anymore and as such cannot be loaded withjava.io.File
anymore. You need to load it as a stream/resource. Something likegetClassLoader().getResourceAsStream(/META-INF/MANIFEST.MF)
. Or just use theResourceLoader
abstraction from Spring `new ClassPathResource("/META-INF/MANIFEST.MF).getInputStream()). – Numismatologynew ClassPathResouce
instead of you loading it yourself. However I probably would say you should stop this and use the info endpoint solution available in Spring Boot, which can append/read the values from a file. – NumismatologyManifest
as it is part of the classpath. I would strongly suggest to ask a new question and describe what you want and then how you tried to do it and why it doesn't work. YOu have not described a how and not a what with unclear comments referring to your original question. – Numismatology