Alex Rivera | Logout

How do you create a MANIFEST.MF that's available when you're testing and running from a jar in production?

Asked 2008-09-17T15:28:05.210
21

I've spent far too much time trying to figure this out. This should be the simplest thing and everyone who distributes Java applications in jars must have to deal with it.

I just want to know the proper way to add versioning to my Java app so that I can access the version information when I'm testing, e.g. debugging in Eclipse and running from a jar.

Here's what I have in my build.xml:

<target name="jar" depends = "compile">
    <property name="version.num" value="1.0.0"/>
    <buildnumber file="build.num"/>
    <tstamp>
        <format property="TODAY" pattern="yyyy-MM-dd HH:mm:ss" />
    </tstamp>

    <manifest file="${build}/META-INF/MANIFEST.MF">
        <attribute name="Built-By" value="${user.name}" />
        <attribute name="Built-Date" value="${TODAY}" />                   
        <attribute name="Implementation-Title" value="MyApp" />
        <attribute name="Implementation-Vendor" value="MyCompany" />                
        <attribute name="Implementation-Version" value="${version.num}-b${build.number}"/>                              
    </manifest>

    <jar destfile="${build}/myapp.jar" basedir="${build}" excludes="*.jar" />                   
</target>

This creates /META-INF/MANIFEST.MF and I can read the values when I'm debugging in Eclipse thusly:

public MyClass()
{
    try
    {                        
        InputStream stream = getClass().getResourceAsStream("/META-INF/MANIFEST.MF");
        Manifest manifest = new Manifest(stream);            

        Attributes attributes = manifest.getMainAttributes();

        String implementationTitle = attributes.getValue("Implementation-Title");
        String implementationVersion = attributes.getValue("Implementation-Version");
        String builtDate = attributes.getValue("Built-Date");
        String builtBy = attributes.
Edit
Report

3 Answers

2

You want to use this:

Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF");

You can parse the URL to figure out WHICH jar the manifest if from and then read the URL via getInputStream() to parse the manifest.

answered 2008-09-18T16:44:23.460
1

I've found the comment by McDowell to be true - which MANIFEST.MF file gets picked up depends on the classpath and might not be the one wanted. I use this

String cp = PCAS.class.getResource(PCAS.class.getSimpleName() + ".class").toString();
cp = cp.substring(0, cp.indexOf(PCAS.class.getPackage().getName())) 
              +  "META-INF/MANIFEST.MF";
Manifest mf = new Manifest((new URL(cp)).openStream());

which I adapted from link text

answered 2010-06-18T11:30:49.177
0

You can use a utility class Manifests from jcabi-manifests that automates finding and parsing of all MANIFEST.MF files available in classpath. Then, you read any attribute with a one liner:

final String name = Manifests.read("Build-By");
final String date = Manifests.read("Build-Date");

Also, check this out: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

answered 2012-12-30T09:02:05.250

Your Answer