Ich habe meine Applikation in ein Jar File (x.jar) verpackt, inklusive einer Manifest.mf, in der im Classpath die Libs aufgelistet sind, die benötigt werden. Alle Jars liegen im gleichen Verzeichnis (auch meine x.jar).
Nun starte ich meine Applikation wiefolgt:
java -cp x.jar Startklasse
Die Libraries die ich über die Manifest.mf eingebunden habe, die brauchen ja teilweise auch wiederrum Libraries um zu funktionieren. Nun die Frage: Können diese Libraries dann ihre benötigten Jars selber finden (liegen ja alle im gleichen Ordner) ODER muss ich alle Jars die ingesamt benötigt werden (also auch die nicht direkt von meiner Applikation benötigt werden) auch in den Classpath in meine Manifest.mf aufnehmen.
Kurzes Beispiel:
x.jar, liby.jar, libz.jar alle im gleichen Ordner.
x.jar (von mir erzeugt): benötigt liby.jar. Deshalb in der manifest.mf im Classpath aufgeführt.
liby.jar benötigt libz.jar. Muss libz.jar jetzt auch im Classpath in der manifest.mf aufgeführt werden, oder findet Java die von selbst?
Wenn die Klassenpfade in der Manifestdatei gepflegt werden, dann musst du mit dem -jar Parameter starten (ohne Startklasse). Sonst musst du den Klassenpfad mit -cp angeben und die Startklasse. Jegliche Kombinationen davon führen nicht zum Ziel.
Wenn die Klassenpfade in der Manifestdatei gepflegt werden, dann musst du mit dem -jar Parameter starten (ohne Startklasse). Sonst musst du den Klassenpfad mit -cp angeben und die Startklasse. Jegliche Kombinationen davon führen nicht zum Ziel.
Erstmal danke für deine Antwort. Das mache ich doch soweit, oder?
Im Moment wird die Applikation (vereinfacht) wiefolgt gestartet:
java -cp /path/to/x.jar:/path/to/etc:/path/to/properties "Startklasse_y für x.jar"
D.h. die Pfade zu den ganzen Konfigurationsdateien werden im Classpath direkt angegeben. Auf die Libs wird in der Manifest.mf verwiesen.
Ich startete nicht mit java -jar x.jar (und nehme die Konfigurationspfade in die Manifest.mf auf), da es 2 verschiedene Eingangspunkte gibt (einmal für Server, einmal für Client). Ansonsten bräuchte ich zwei Jars, was ich ungern will.
Die Frage die sich mehr stellt, ist ob Java die transitiven Abhängigkeiten von x.jar->Libs->"von den Libs benötigte Libs" automatisch auflöst oder ob ich das selber machen muss.
Ich wiederhole: entweder... oder. Keine Kombination.
Pflege den kompletten Klassenpfad über -cp und starte über Skripten mit der passenden Main-Klasse.
Auch zwei JARs wären nicht unbending verkehrt. Vermutlich hättest du dann mehr Aufwand beim Assembly der JARs, aber du hättest auch keine unnötigen Ressourcen in den JARs.
Je länger ich mich mit dem Problem auseinandersetze, desto weniger funktioniert es
Hier nochmal das aktuelle Setup, etwas detailierter. Vielleicht kann mir jemand noch einen Tipp geben.
Die Dateistruktur ist vereinfacht die folgende (ausgehend vom Hauptordner der Applikation):
Code:
bin
|- start.sh
etc
|- my.config
properties
|- server
|- logback.xml
webapp
|- server
|- WEBINF
|- lib
|- lib1.jar
|- lib1.jar
|- myapp.jar
Die bin/start.sh ruft folgendes auf:
java -jar /opt/company/myapp/webapp/server/WEBINF/lib/myapp.jar
Ich glaub die Pfade stimmen einfach nicht, aber ich kriegs einfach nicht richtig hin. Die Applikation starte ich im Moment direkt aus dem Hauptordner, also mit bin/start.sh. Hat jemand eine Idee wo das Problem liegen könnte?
Bin für jede Hilfe dankbar!
NEIN ... java kann abhängigkeiten nicht selbst auflösen ...
wenn dein jar ein weiteres jar braucht das wiederum ebenfalls eins braucht musst du das von der lib genutzte jar ebenfalls in DEINEN class-path aufnehmen da alles relativ zum SystemClassLoader ist
heißt also das ALLE jars die deine gesamte app nutzt ... also auch die jars die von den libs gebraucht werden müssen in deinen Class-Path ... und zwar alle RELATIV zum root-jar *also dem jar was über java -jar *.jar gestartet wird*
alternativ mit java -cp alle jars eintragen und dann die main-klasse starten ...
die antwort von wegen entweder mit -cp oder garnicht von FArt ist hier fehl am platz ...
NEIN ... java kann abhängigkeiten nicht selbst auflösen ...
wenn dein jar ein weiteres jar braucht das wiederum ebenfalls eins braucht musst du das von der lib genutzte jar ebenfalls in DEINEN class-path aufnehmen da alles relativ zum SystemClassLoader ist
heißt also das ALLE jars die deine gesamte app nutzt ... also auch die jars die von den libs gebraucht werden müssen in deinen Class-Path ... und zwar alle RELATIV zum root-jar *also dem jar was über java -jar *.jar gestartet wird*
alternativ mit java -cp alle jars eintragen und dann die main-klasse starten ...
die antwort von wegen entweder mit -cp oder garnicht von FArt ist hier fehl am platz ...
Alles klar, damit kann ich was anfangen kann - vielen Dank.
Sollte dann nicht auch "java -cp myapp.jar STARTKLASSE" funktionieren, vorausgesetzt in der Manifest.mf in der myapp.jar sind alle Klassen eingetragen?
ganz erlich : das weis ich nicht ... ich würde aber rein vom bauchgefühl her sagen : funktioniert nicht ...
warum : weil du mit der parameter-angabe genau diesen eintrag im manifest überschreibst ...
und ich denke das FArt genau diese kombination meinte mit : GEHT NICH ... und da würde ich mich dann auch anschließen
Sollte dann nicht auch "java -cp myapp.jar STARTKLASSE" funktionieren, vorausgesetzt in der Manifest.mf in der myapp.jar sind alle Klassen eingetragen?
Nein. Das sagte ich schon zwei mal. Und auch die "transitiven" Abhängigkeiten waren eigentlich schon beantwortet, als ich vom "kompletten Klassepfad" sprach.
Nein. Das sagte ich schon zwei mal. Und auch die "transitiven" Abhängigkeiten waren eigentlich schon beantwortet, als ich vom "kompletten Klassepfad" sprach.
wobei alle benötigten Libs in der Manifest.mf in der myapp.jar eingetragen sind. Applikation startet, funktioniert und er findet auch die logback.xml für die Logging Konfiguration. Rein logisch macht es für mich keinen Sinn und ich denke es ist eher ein "günstiger" Zufall, dass es überhaupt klappt. Folglich, keine akzeptable Lösung.
Das Einzige was nicht funktioniert, wenn ich alle Jars in die Manifest einfüge, ist dass er die logback.xml nicht mehr finden kann (s. Post #6). Irgendwelche Ideen?
Meinst du? Trotzt "ich habs verstanden" und "damit kann ich was anfangen" stehen wir noch am Anfang...
Ich hatte vergessen auf die Internet- und Forensuche hinzuweisen (auch über die FAQs ist da glaube ich was hilfreiches dabei).... denn genau dieses Thema ist einfach nicht neu und es kommen auch keine neuen Facetten hinzu (außer dass man hier auf einem Standalone-Client eine unnötige WAR-Struktur vorfindet).
Ich hatte vergessen auf die Internet- und Forensuche hinzuweisen (auch über die FAQs ist da glaube ich was hilfreiches dabei).... denn genau dieses Thema ist einfach nicht neu und es kommen auch keine neuen Facetten hinzu (außer dass man hier auf einem Standalone-Client eine unnötige WAR-Struktur vorfindet).
Ich stimme dir zu, es gibt unzählige Threads zum Thema Jar, Manifest & Classpath. Mir ist noch keines untergekommen, in dem etwas anderes als Jar Dateien inkludiert worden sind (was hier eh nicht das Problem war). Wenn aber in dem Großteil der Threads mit Halbwissen und "Starte doch mit java -cp myapp.jar Startklasse" hantiert wird, dann ist es ja wenig verwunderlich, dass jemand auch mal ein Problem bekommt, wenn es dann nicht mehr klappt.
Das "-jar" den "-cp" Parameter überschreibt ist ja aus der Doku bekannt. Dass jedoch der Classpath in der Manifest den "-cp" Parameter überschreibt, davon ist in der Doku (leider) nichts zu lesen und genausowenig in 99% der eigentlich betroffenen Threads. Jedenfalls, Danke für deine Hilfe, jetzt gehts ja.
Gut, dass es jetzt geht.
Dieser Link ist ein prominenter Treffer der Google Suche "java classpath": Classpath (Java) - Wikipedia, the free encyclopedia.
Da steht alles drin. Man muss ein wenig genau lesen...
@TO
du hast es scheinbar nicht verstanden was ich geschrieben habe oder du hast es falsch gelesen
durch setzen von -cp im aufruf wird der Class-Path im manifest überschrieben ...
nicht der -cp vom manifest ...
was aber EINDEUTIG aus der doc hervorgeht
nur dateinamen die auf ein "/" enden werden als verzeichnisse interpretiert ... alles andere als file ...
und wenn du das mal GENAU gelesen hättest wäre dir dieser fehler sehr viel früher aufgefallen