I would like to read MANIFEST.MF
of my WAR
application. How can I find its file name?
I did some researches to find the right solution for me. Mainly thanks to BalusC but also others I cannot remember now because I went deeply in many sources. I have a web application running on Weblogic 12c (12.2.1.4) version. First I had to say maven to add information in MANIFEST.MF, adding the following in plugins section of POM file
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
You can find the version of maven plugin looking at the console in the package goal.
Then I've mainly followed the BalusC direction in the post Using special auto start servlet to initialize on startup and share application data
Before registering the class in the servlet context in the contextInitialized method
@Override public void contextInitialized(ServletContextEvent servletContextEvent)
I've put my business logic to retrieve information from the manifest, like the following
@Override public void contextInitialized(ServletContextEvent servletContextEvent) {
logger.info("context initialized - reading MANIFEST.MF infos");
StringBuilder welcomeStrBuild;
welcomeStrBuild = new StringBuilder("version");
try (InputStream inputStream = servletContextEvent.getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF")) {
Properties prop = new Properties();
prop.load(inputStream);
welcomeStrBuild.append(prop.getProperty("Implementation-Version", "n/a"));
} catch (Exception e) {
logger.info("Unable to extract info from MANIFEST.MF");
welcomeStrBuild.append("Unable to extract info from MANIFEST.MF");
}
infoProject = welcomeStrBuild.toString();
servletContextEvent.getServletContext().setAttribute("config", this);
}
You can of course read the content of the manifest using the Java Manifest class, instead of using Properties class.
The main points of the solution are the two:
I had the same problem in every application and decided to create a component with a utility class in it: jcabi-manifests. Now it's easy to load any attribute from one of available MANIFEST.MF
in classpath:
import com.jcabi.manifests.Manifests;
String value = Manifests.read("My-Version");
Also, check this out: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html
How can I find its file name?
You already have it. Maybe you meant to find the absolute file location? You can use ServletContext#getRealPath() for this.
String relativeWARPath = "/META-INF/MANIFEST.MF";
String absoluteDiskPath = getServletContext().getRealPath(relativeWARPath);
File file = new File(absoluteDiskPath);
// ...
Or if you want to get it as InputStream
directly, use ServletContext#getResourceAsStream().
InputStream input = getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF");
// ...
There are a few ways to do it, and the chosen answer is only works when you want to read Manifiest files on Servlet/SpringMVC layer or whatever layer you can access to ServletContext.
However, if you want to read a value like "version" even before Servlet starts up, like during logback configuration or something else, you might need to do some old-way classloading or Manifest file manipulation.
I found this github repository(not mine) and it includes 4 different way to read information from Manifest file. If your situation is not accessible to ServletContext, check these out.
https://github.com/khmarbaise/version-examples