0

First of all I want to say that I do not want to use Maven, Ant, Gradle, any IDE or similar for this task.

I want to make a runnable jar using a bash script. The jar should includes all jar-content from my "libs" folder.

I have started this script and it "almost" works(until the jar creattion):

#!/bin/bash

#Setup
libs=$(find libs -name "*.jar" -print0 | xargs -0 | sed -e 's/ /:/g')
tmp2=$(sed -e 's/:/\n ..\//g' <<< $libs)
tmp2=../$tmp2
libs=$libs:src
mkdir tmp

#Compile
javac -d tmp -classpath "$libs" src/main/PublishData.java


#Create manifest
cd tmp
echo "Main-Class: main.PublishData" >> m.mf
echo "Class-Path: $tmp2" >> m.mf

#Build jar
jar cvfm thejar.jar m.mf *

An m.mf example file would look like this:

Main-Class: MyMain
Class-Path: ../libs/1.jar
 ../libs/2.jar

The file structure looks like this:

├── src
├── tmp (created by the script, jar cvfm thejar.jar m.mf * is run here)
├── libs
│   ├── jar1
│   ├── jar2

The jar file is created and can be executed but the referenced jars are not found. (E.g: Exception in thread "main" java.lang.NoClassDefFoundError: com/mongodb/MongoClient )

It seams to me like the jar program could not find the jars.

How can I successfully "include" my jars from the libs dir?


UPDATE:

Every line in the "Class-Path:" section of a manifest file needs to start and end with a white space this caused the class-path to break.

user264230
  • 630
  • 3
  • 7
  • 19
  • Maybe this post can answer your question: [http://stackoverflow.com/a/8312977/2522681](http://stackoverflow.com/a/8312977/2522681) – Michael Lang Nov 18 '14 at 14:00

1 Answers1

0

Your approach looks good in general.

Relative paths work in the manifest but you need to make sure that the paths are available at runtime. So if you say "load ../libs/foo.jar", then for the classloading to work, you need to be in the src/, tmp/ or libs/ when you start the application.

The main problem is that Java silently ignores JARs which it can't find. I hesitate to call this a feature, especially since so many people run into problems starting a Java application. So you will have to painstakingly find out what works and what doesn't.

To make things more simple, I suggest that you JAR all the classes of your project as well and then create a pure "classpath" JAR (i.e. no classes, just a manifest file with the classpath + the main class). That way, all your dependencies work the same.

Another thing you should try is to write a small project (just the hello world kind) where you can test your "create manifest JAR" script.

That said, my approach is to create a main class which accepts a path as arguments (the absolute path to the libs folder). It then lists all the JAR files in the folder (plus some debug output so I can see what it finds) and creates a new URLClassLoader with those URLs. That way, I can debug classpath issues easily plus my "start" script work like this:

BASE=$(cd $( dirname "$0" ) > /dev/null ; pwd )

java -jar $BASE/starter.jar $BASE/libs
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820