13

I used the instructions found at Maven - how can I add an arbitrary classpath entry to a jar to add an arbitrary entry to the Class-Path attribute. Here is my MANIFEST.MF file:

Manifest-Version: 1.0
Class-Path: jace-runtime.jar
Main-Class: org.jace.examples.Test

I defined org.jace.examples.Test as follows:

public class Test
{
    public static void main(String[] args)
    {
        System.out.println("classpath: " + System.getProperty("java.class.path"));
        System.out.println("PeerExample: " + Class.forName("org.jace.util.ShutdownHook"));
    }
}

where org.jace.util.ShutdownHook is defined in jace-runtime.jar. When I invoke java -jar peer_example1.jar I get the following output:

classpath: peer_example1.jar Exception in thread "main" java.lang.ClassNotFoundException: org.jace.util.ShutdownHook

In other words, Java is adding the executable JAR file to the classpath but ignoring Class-Path. If I invoke java -cp jace-runtime.jar;peer_example1.jar org.jace.examples.Test I get the expected output:

classpath: jace-runtime.jar;peer_example1.jar

Any ideas?

Gray
  • 115,027
  • 24
  • 293
  • 354
Gili
  • 86,244
  • 97
  • 390
  • 689

3 Answers3

20

Answering my own question:

  1. Adding arbitrary entries to Class-Path is fine on its own. The problem arises when you enable JAR indexing using:

    <configuration>
      <archive>
        <index>true</index>
      </archive>
    </configuration>
    

    Maven will omit your entries from META-INF/INDEX.LIST.

  2. When you use the JAR at runtime, Java will look at INDEX.LIST for finding classes, not MANIFEST.MF.

  3. Because your entries are missing from INDEX.LIST, they will not be found by the classloader, no matter what the manifest says.

A simple workaround is to disable JAR indexing. I'm not sure how to inject an arbitrary Class-Path with indexing enabled.

Gili
  • 86,244
  • 97
  • 390
  • 689
  • I wish I could upvote this more than once. I have had the same issue for about a year. Couldn't find the cause until I saw this. In my case, I don't have this code in my .pom file but an INDEX.LIST is still being generated. At least, now I know where the problem is. – Wige Apr 03 '18 at 15:20
0

For those that may otherwise be unaware, the executable archive mechanism takes the manifest classpath and uses it to load classes external to the archive.

So if you are expecting a WAR with a manifest classpath of WEB-INF/classes to find classes in the WEB-INF/classes entry inside the archive then you will be disappointed.

William
  • 20,150
  • 8
  • 49
  • 91
-4

Per the tooldocs page for the jar option - Link to docs

When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.

karakuricoder
  • 1,065
  • 8
  • 8
  • 2
    -1: The documentation refers to the fact that the `-cp/-classpath` command-line option gets ignored in favor of the `Class-Path` which I am using, so this isn't the problem. – Gili May 03 '12 at 18:05