create jar with custom manifest with multiple libraries in classpath

36,251

Solution 1

Finally I've copied all the libs into the /lib folder and add them into the .jar with an ant target since seems to be OK with the IT guys (because it is a small application).

Here is the ant(in case is useful for someone):

<?xml version="1.0" encoding="UTF-8"?>
<project name="BatchTester" default="compile" basedir=".">
    <property name="external" value="lib/external-libs.jar"/>
    <target name="compile">
        <javac srcdir="jav"
               source="1.6"
        />
        <echo>Creating jar File</echo>
        <!--create a new .jar with all the external jars in /lib-->
        <jar jarfile="${external}">
            <zipgroupfileset dir="lib/">
                <include name="**/*.jar"/>
            </zipgroupfileset>
        </jar>
        <!--<sleep seconds="1"/>-->
        <!--create .jar file-->
        <jar jarfile="BatchTester.jar" index="true" filesetmanifest="mergewithoutmain">
            <fileset dir=".">
                <include name="**/jav/**/*.class"/>
                <exclude name="**/jav/**/*.java"/>
            </fileset>
            <zipfileset src="${external}">
                <exclude name="META-INF/*.SF"/>
            </zipfileset>
            <manifest>
                <attribute name="Main-Class" value="jav.BatchTester"/>
            </manifest>
        </jar>
        <!--delete previously created extern .jar-->
        <delete file="${external}"/>
    </target>
</project>

Solution 2

Sorry If my questions sounds obvious for you.


*Launch Command *

In order to exclude any doubt, didn't you tried to launch your jar with this kind of command ?

java -jar myJar.jar -cp ./lib

If you use classpath option, you probably didn't ;). Option --classpath (or -cp) and -jar can't be uses together.

Prefer the use of relative path too, like ./lib instead of P:/Tools/... But, anyway, that won't solve your problem.


*Package Location *

As brimborium said, what is you real package ? src sounds very strange. We suspect an error around this.

In your BatchTester class, what have you written for package directive ? Nothing (i.e default package which isnot recommanded ?)?

Does you class begin with (get rid off comments)

public class BatchTester {

In that case, for sure, src should not be mentionned.

Here an example of manifest which work for me.

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: jrRevy
Build-Jdk: 1.6.0_31
Main-Class: com.sopragroup.training.dojo1.MainSwingApp
Class-Path: dojo1-0.5.0-SNAPSHOT-lib/spring-core-3.1.1.RELEASE.jar doj
 o1-0.5.0-SNAPSHOT-lib/spring-asm-3.1.1.RELEASE.jar [blablabla]

with the following execution structure

/
|
+ --dojo1-0.5.0-SNAPSHOT.jar
|
+ --dojo1-0.5.0-SNAPSHOT-lib/
    |
    + --spring-core-3.1.1.RELEASE.jar

Obviously, I'm using maven for build my app, but the main idea is in.

Solution 3

The manifest doesn't allow absolute paths in the Class-Path: tag. You have two alternatives:

  • Use relative paths as you already mention in your own answer

  • Use absolute paths via file protocol. This has been answered elsewhere too and it works absolute versus relative path names in jar manifest

    Class-Path: file:///P:/Tools/xstream/1.4.2/lib/kxml2-2.3.0.jar

In addition, you should not edit the manifest.mf manually without being aware of several limitations:

  • line maximum length must not exceed 72 characters, and after breaking one line you must insert an space in the first column.
  • There must be a carriage return after the last line otherwise, the file can't be parsed correctly
Share:
36,251
magodiez
Author by

magodiez

Developer, musician, artist...

Updated on October 28, 2021

Comments

  • magodiez
    magodiez over 2 years

    I'm trying to create a jar from my eclipse and in order to be able to use the external .jars, I'm using this manifest with multiple .jars in the classpath:

    Manifest-Version: 1.0
    Sealed: true
    Main-Class: src.BatchTester
    Class-Path: . P:/Tools/xstream/1.4.2/lib/kxml2-2.3.0.jar P:/Tools/xstream/1.4.2/lib/xstream-1.4.2.jar P:/Tools/StringTemplate/4.0.5/lib/antlr-3.3-complete.jar P:/Tools/StringTemplate/4.0.5/lib/ST-4.0.5.jar P:/Tools/Jdbc/lib/sqljdbc4.jar
    

    Obviously if I don't put the libraries in the classpath the following error appears:

    java.lang.NoClassDefFoundError: com/thoughtworks/xstream/XStream
    

    But when I put them in the classpath the error changes to:

    java.lang.NoClassDefFoundError: src/BatchTester
    

    So it seemps that it can't found my main class. I've tryed with several possibilities in the classpath, like adding or removing . to the classpath, but can't make it work.

    Any idea of how can I solve this???

    Thanks for your time and effort,


    PS: After creating the .jar the classpath in the manifest inside looks like:

    Class-Path: . P:/Tools/xstream/1.4.2/lib/kxml2-2.3.0.jar P:/Tools/xstr
     eam/1.4.2/lib/xstream-1.4.2.jar P:/Tools/StringTemplate/4.0.5/lib/ant
     lr-3.3-complete.jar P:/Tools/StringTemplate/4.0.5/lib/ST-4.0.5.jar P:
     /Tools/Jdbc/lib/sqljdbc4.jar 
    

    with new lines and spaces, but even after changing it to the "right" format, I got the same problems.

    PS2: I know that with some plugins like Fat-Jar you can make it work, but I don't want to insert more data than needed in my .jar

  • Jan
    Jan over 8 years
    Thank you so much! I've spent hours and hours on this problem trying to add multiple jars to the classpath in the manifest but this solution with the zipfileset works flawlessly and so fast!!!!!!!
  • Jan
    Jan over 8 years
    If I could +1 more than once I would definitely do it.