# Ant - Einbindung von externen Jars



## Robsta10 (9. Mai 2005)

Hallo Leute!

Vorerst einmal möchte ich anbringen, dass ich bereits diese Foren durchforstet, auch schon auf ant.apache.com war, einen Kollegen befragt, der Ant regelmäßig benutzt und natürlich auch gegoogelt habe.

Folgende Situation:
Ich habe ein Java Programm geschrieben, welches mehrere externe JARs (von Oracle) verwendet, also einbindet. Mein Ziel ist es, aus meinem Programm ein ausführbares JAR zu generieren.

Was ich bereits versucht habe:
-    In Eclipse mit Export --> JAR file zu arbeiten, was nicht wirklich funktioniert. Ich kann das generierte JAR File in der CMD mit java -jar file.jar aufrufen. Sobald aber Code durchlaufen wird, der diese externen JARs von Oracle verwendet, gibt es eine tolle NoClassDefFound Exception.
-    Daher versuche ich das Ganze per ANT zu bewerkstelligen. Da gibts den ganz gleichen Effekt, also NoClassDefFound Exception, die auf eine Klasse aus einem solchen externen JAR wirft.

Ich meine, laut den Postings hier, dass ich es weiterhin mit ANT versuche, nur leider bin ich gerade an einen Punkt gelangt, an dem ich denke, dass ich einfach zu dumm bin, das richtige build.xml File zu schreiben.

Ich habe bereits geschafft, im build.xml das Manifest File so hinzubiegen, dass der gesamte CLASS-PATH der externen JARs vorhanden ist. Leider bleibt dies ohne Effekt, denn schon wieder NoClassDefFound Exception...

Weil ich momentan keinen eigenen Lösungsweg sehe, bitte ich euch, mir in diesem Fall Hilfe zu leisten, sofern ihr schon mal in so einer Situation gewesen seid, d.h. vielleicht gibts ein Beispiel-build.xml File, oder vielleicht ist eine andere Vorgehensweise zu wählen, tja keine Ahnung. Das Einzige was ich nicht will ist, die externen JARs zu entpacken und die Class Files als solche ins Projekt zu importieren, da ich da keinen Überblick mehr hätte.

Bin dankbar für jede Hilfe

Robert


----------



## 0xdeadbeef (9. Mai 2005)

FatJar versucht?


----------



## daLenz (10. Mai 2005)

Robsta10 hat gesagt.:
			
		

> Ich habe bereits geschafft, im build.xml das Manifest File so hinzubiegen, dass der gesamte CLASS-PATH der externen JARs vorhanden ist. Leider bleibt dies ohne Effekt, denn schon wieder NoClassDefFound Exception...



wie hast du die externen jar's dann angegeben? so?:


```
...

<property name="app.cp" value="lib/jar1.jar lib/jar2.jar"/>
...
    
<attribute name="Class-Path" value="${app.cp}"/>   
...
```

also so funktioniert es...(wenn das restliche ebenfalls richtig angegeben ist )


----------



## Robsta10 (10. Mai 2005)

@OxDeadBeaf: FatJar hab ich noch nie versucht, hab auch noch nie was davon gehört.

@daLenz:    - Die CLASS-PATH Variable hab ich gleich gesetzt, wie in deinem Beispiel angegeben.
                  - Den Parameter, der den Wert für CLASS-PATH beinhaltet hab ich mit dem task pathconvert befüllt:


```
<pathconvert targetos="windows" property="path.jar" refid="project.classpath">
    </pathconvert>
```

                   project.classpath wird erstellt, wenn man in Eclipse ein build.xml generieren lässt, schaut so aus:


```
<path id="project.classpath">
        <pathelement location="."/>
        <pathelement location="C:/oracle/oraMobile/jdbc/lib/classes12.zip"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/Server/bin/webtogo.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/xmlparserv2.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/classgen.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/consolidator.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/devmgr.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/javax-ssl-1_2.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/jssl-1_2.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/servlet.jar"/>
    </path>
```

Das Manifest File sollte meiner Meinung nach stimmen:

```
Manifest-Version: 1.0
Sealed: true
Main-Class: publication.Initiator
Main-Class: publication.Initiator
Class-Path: D:\DA\Prog\Snapshot;C:\Programme\Java\j2re1.4.2_05\lib\rt.
 jar;C:\Programme\Java\j2re1.4.2_05\lib\sunrsasign.jar;C:\Programme\Ja
 va\j2re1.4.2_05\lib\jsse.jar;C:\Programme\Java\j2re1.4.2_05\lib\jce.j
 ar;C:\Programme\Java\j2re1.4.2_05\lib\ext\dnsns.jar;C:\Programme\Java
 \j2re1.4.2_05\lib\ext\ldapsec.jar;C:\Programme\Java\j2re1.4.2_05\lib\
 ext\sunjce_provider.jar;C:\oracle\oraMobile\jdbc\lib\classes12.zip;C:
 \oracle\oraMobile\Mobile\Server\bin\webtogo.jar;C:\oracle\oraMobile\M
 obile\classes\xmlparserv2.jar;C:\oracle\oraMobile\Mobile\classes\clas
 sgen.jar;C:\oracle\oraMobile\Mobile\classes\consolidator.jar;C:\oracl
 e\oraMobile\Mobile\classes\devmgr.jar;C:\oracle\oraMobile\Mobile\clas
 ses\javax-ssl-1_2.jar;C:\oracle\oraMobile\Mobile\classes\jssl-1_2.jar
 ;C:\oracle\oraMobile\Mobile\classes\servlet.jar
```


----------



## Robsta10 (10. Mai 2005)

Hallo Leute!

Ich glaube es ist hilftreich, die ganze build.xml zum Anschauen bereitzustellen. Guckt sie euch mal an und dann werde ich meine Probleme damit schildern. (Diese build.xml ist im Übrigen nach dem Vorbild aus dem Beitrag www.java-forum.org/de/viewtopic.php?t=9021 entstanden)


```
<project name="Test" default="createJar"> 
   <target name="createJar"> 
    <path id="project.classpath">
        <pathelement location="."/>
        <pathelement location="C:/Programme/Java/j2re1.4.2_05/lib/rt.jar"/>
        <pathelement location="C:/Programme/Java/j2re1.4.2_05/lib/sunrsasign.jar"/>
        <pathelement location="C:/Programme/Java/j2re1.4.2_05/lib/jsse.jar"/>
        <pathelement location="C:/Programme/Java/j2re1.4.2_05/lib/jce.jar"/>
        <pathelement location="C:/Programme/Java/j2re1.4.2_05/lib/ext/dnsns.jar"/>
        <pathelement location="C:/Programme/Java/j2re1.4.2_05/lib/ext/ldapsec.jar"/>
        <pathelement location="C:/Programme/Java/j2re1.4.2_05/lib/ext/sunjce_provider.jar"/>
        <pathelement location="C:/oracle/oraMobile/jdbc/lib/classes12.zip"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/Server/bin/webtogo.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/xmlparserv2.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/classgen.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/consolidator.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/devmgr.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/javax-ssl-1_2.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/jssl-1_2.jar"/>
        <pathelement location="C:/oracle/oraMobile/Mobile/classes/servlet.jar"/>
    </path>
    <pathconvert targetos="windows" property="path.jar" refid="project.classpath"/>
    <jar destfile="start.jar" basedir="publication" update="yes"> 
       <manifest> 
        <attribute name="Main-Class" value="publication.Initiator"/> 
         <attribute name="Class-Path" value="${path.jar}"/>    
       </manifest> 
    </jar> 
   </target> 
</project>
```

Also, das start.jar File wird erfolgreich erstellt. Dann natürlich versuche ich es via Command Line zu starten. Da spuckt er aber die Meldung "NoClassDefFoundError publication.Initiator" aus, dass heißt er findet meine Main-Class nicht an. Dann hab ich das start.jar File entpackt und feststellen müssen, dass Initiator.class (bei meinen anderen Klassen daselbe) nicht in einem Unterverzeichnis publication, sondern im Root Verzeichnis anglegt sind. Ich glaub, das ist der Grund, warum beim Ausführen die Main-Class nicht gefunden wird.

Wie kann der Jar task so umgeschrieben werden, damit Dateien aus publication auch in ein Verzeichnis publication gejart werden?

Danke im Voraus

Robert


----------



## Bleiglanz (10. Mai 2005)

such mal hier im forum

der class-path eintrag im manifest bezieht sich IMMER auf Dateien AUSSERHALB des betroffenen jars

es gibt IMHO einfach keine Möglichkeit, die für die Ausführung eines Programms benötigten externen Bibliothekten gleich mit in das jar aufzunehmen

[ausser du entpackst sie und packst sie dann flach wieder hinein]


----------



## Robsta10 (10. Mai 2005)

Also, dass es nicht gehen sollte, dass das ausführbare JAR File seine benötigten externen JAR Files nicht findet, das kanns ja wohl nicht sein. Für was gibt es dann überhaupt externe Bibliotheken??? Ich hab keine Lust diese externen JARS zu entpacken, das würde zu unübersichtlich werden.

Es MUSS ja eine kompfortable Lösung geben. Was machen sonst JAVA Programmierer, die externe Bibliotheken verwenden und ihr Programm dann auch ohne Eclipse standalone laufen lassen wollen?


----------



## Bleiglanz (10. Mai 2005)

was hat das alles mit eclipse zu tun? gar nichts!

pack halt alles in einen gezippten ordner

MeineApp.jar (mit dem main, die class-path: eintrag gehen auf lib/..)
lib/externe1.jar
lib/externe2.jar 
...
dann kannst du deine Anwendung ganz normal mit java starten?!


----------



## Robsta10 (10. Mai 2005)

Hallo  Leute!

Ich habs jetzt geschafft, dass mein Programm standalone läuft. Mein Fehler dabei war, wie ich den Wert der CLASS-PATH Variable befüllt habe, denn dieser muss einer bestimmten Konvention entsprechen. Kann man in der JAR File Specification auf ant.apache.org/manual/ nachlesen.

Auf jeden Fall möchte ich für andere kurz skizzieren, wie das Ganze bei mir nun aussieht:

Wie bereits erwähnt benötigt mein Programm eine Reihe von externen JARs, in meinem Fall von Oracle. Mit diesen externen JARs kann ich den sogenannten Mobile Server ansteuern, die externen JARs dienen also als API. All jene JARs, die ich auch in meinem Eclipse Projekt importieren musste, habe ich in einen Unterordner des Projektordners 'oracle' kopiert. Bei Erstellen des JAR Files meines eigenen Programmes habe ich im build.xml Ant File sichergestellt, dass auch dieser Ordner 'mit von der Partie' ist, also im JAR File enthalten. Der springende Punkt nun ist die richtige Zusammenstellung des build.xml Files, wobei dabei die Variablen MAIN-CLASS und CLASS-PATH besonders wichtig sind. Mein build.xml sieht wie folgt aus:


```
<project name="Test" default="createJar"> 
   <property name="basedir" value="D:\DA\Prog\Snapshot"/>
   <property name="app.cp" value="
   oracle/webtogo.jar
    oracle/consolidator.jar 
    oracle/xmlparserv2.jar 
    oracle/classes12.zip
    oracle/classgen.jar
    oracle/devmgr.jar
    oracle/javax-ssl-1_2.jar
    oracle/jssl-1_2.jar
    oracle/servlet.jar
    "/>
   <target name="deleteJar"> 
  	<delete file="start.jar"/>  
	</target> 

   <target name="createJar" depends="deleteJar"> 
    <jar destfile="start.jar" basedir="./" update="yes"> 
      <fileset dir="publication">
			  <include name="publication/*.class"/>
			  
			</fileset>       
       <manifest> 
        <attribute name="Main-Class" value="publication.Initiator"/> 
        <attribute name="Class-Path" value="${app.cp}"/>
       </manifest> 
    </jar> 
   </target> 
</project>
```

Im Property namens app.cp stelle ich meinen CLASS-PATH zusammen. Wenn ihr nicht so viele externe JARs benötigt kann das auch in einer Zeile passieren, dann aber mit einem Leerzeichen getrennt. Für mich ist es so viel übersichtlicher.

Was ich vorher mit CLASS-PATH falsch gemacht habe:
Ich habe mir dafür den path, der von Eclipse automatisch erstellt wurde, mit pathconvert in einen Parameter umwandeln lassen. Die Zeichenfolge hatte aber das Format, wie wir es von den Systemvariablen in Windows gewohnt sind. Dieses Format stimmt aber nicht mit der Spezifikation überein.

Tja, das wars eigentlich schon. Ich hoffe, dieser Thread kann anderen helfen, bei diesem Problem etwas schneller zum Ziel zu finden als ich.

Danke nochmal an alle, die mir hilfreiche Tipps gegeben haben.

LG Robert


----------

