Ant and manifests

20 April 2007

by fanedo

When you build an exploded J2EE package such as a .war or .ear, you may need to create a manifest file. This can be quite tricky, since the format of the manifest file is such that it is easy to get it wrong. Furthermore, some errors may cause your application to fail in mysterious ways.

If you look at the JAR File Specification, you will see that lines in a manifest can not be any longer than 72 bytes. That’s bytes, not characters.

It was the line length that tripped me up a while ago. I was getting unexpected ClassNotFoundExceptions in my web application. After much prodding and hitting my head against the wall, I found out that it simply didn’t understand my MANIFEST.MF and failed to set up the class loader with the correct settings from the Class-Path: attribute. Normally the jar task fixes your manifest for you, if you use the manifest attribute - otherwise it makes an empty one, even if you have a MANIFEST.MF in your jar’s fileset. This works only if you are actually using the jar task. Which I was not, since I was deploying exploded packages for testing.

The simplest way to avoid these kinds of problems, is to have your manifest generated or "fixed" by Ant. If you are making exploded packages, the manifest task can either create or update your manifest. If you use the "update" option, you could just maintain your manifest in your favourite editor and use the manifest task to make sure that it’s correctly formatted. Here is a snippet of a build.xml that does exactly that:

...
<target name="manifest">
    <manifest file="MANIFEST.MF" mode="update"/>
</target>
...

You can set attributes from ant by using the attribute element. Note that you do not have to set all the attributes in this way. You can keep some of them in the manifest file and the manifest task will not remove them. It will make sure that they are correctly formatted, however. The next example shows how to use this hybrid method.

The manifest before running ant:

Class-Path: profile-server-client-dev.jar commons-httpclient-3.0.jar commons-betwixt-0.8-dev.jar k2.jar

a snippet from the build file:

...
<target name="manifest">
    <manifest file="MANIFEST.MF" mode="update">
        <attribute name="Implementation-Version" value="1.0"/>
    </manifest>
</target>
...

and the resulting manifest:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Created-By: 1.5.0_06-b05 (Sun Microsystems Inc.)
Class-Path: profile-server-client-dev.jar commons-httpclient-3.0.jar c
 ommons-betwixt-0.8-dev.jar k2.jar
Implementation-Version: 1.0

Note that the manifest task does its work in place. You can also see the strangeness of the format here, where the word "commons-betwixt-0.8-dev.jar" has been broken over two lines. Do remember, though, that the 72 bytes per line is a maximum, so if you still want to do this by hand, you do not have to break up words over several lines, if you do not want to.

If you need to read or create manifest files in your Java code, have a look at the java.util.jar package.