2009-11-10 4 views
15

Ich habe eine JAR-Datei, die eine Anwendung sowie Konfigurationsdateien für diese Anwendung enthält. Die Anwendung lädt Konfigurationsdateien aus dem Klassenpfad (unter Verwendung von ClassLoader.getResource()), und ihre Abhängigkeiten werden vollständig mit den in die JAR-Datei integrierten Konfigurationsdateien erfüllt.Kann ich den Klassenpfad zum Überschreiben einer Datei in einem ausgeführten jar verwenden?

Gelegentlich möchte ich, dass die Anwendung mit einer etwas anderen Konfiguration ausgeführt wird (speziell möchte ich die JDBC-URL überschreiben, um auf eine andere Datenbank zu verweisen), also erstelle ich eine neue Konfigurationsdatei, speichere sie in der richtigen Verzeichnisstruktur (was bedeutet, in einem Verzeichnis /config einen classpath-Eintrags), und ich möchte etwas tun:

java -cp new-config:. -jar application.jar 

Aber ich kann den classpath den new-config Pfadeintrag vor der Anwendung JAR Inhalt zu haben, nicht bekommen. Ist es hart codiert, dass der Inhalt der JAR immer der erste Teil des Klassenpfads ist?

+0

Haben Sie versucht, die Config außerhalb de Glas setzen, in einem eigenen JAR-Datei in einem Pfad relativ zum application.jar (../conf/config.jar)? Wenn Sie dies tun, können Sie den Klassenpfad auf das Konfigurations-JAR im App-Manifest setzen, und Sie können die neue Konfiguration festlegen, indem Sie die Datei config.jar ändern. Ich wünschte, ich hätte mehr Zeit, um eine Demo zu machen, um meine Antwort zu bestätigen, aber ich kann nicht ... also schrieb ich es als Kommentar – JuanZe

+0

Sie meinen, statt in der JAR? – Guss

+0

ja, anstatt in das gleiche Glas wie die Anwendung, setzen die Konfig in einem zweiten Glas ... – JuanZe

Antwort

20

Warum ausdrücklich nicht nur die Anwendung aufrufen -jar ohne Angabe und stattdessen die Anwendung Hauptklasse nennen? Dadurch können Sie sowohl Ihre new-config als auch die application.jar in der erforderlichen Reihenfolge in den Klassenpfad einfügen:

z. („New-config“ unter der Annahme ist ein Verzeichnis der überschriebenen Eigenschaften-Datei enthält)

java -cp new-config:application.jar Application.Main.Class 

Ich glaube, der Name der Hauptklasse kann in dem Topf in der MANIFEST.MF Datei gefunden ....

+2

Das Hauptproblem besteht darin, dass ich nicht das Argument -cp verwende, sondern den Klassenpfad in der Manifestdatei, da die Anwendung viele andere externe JARs benötigt, um alles zu extrahieren, was eher fehleranfällig ist. Aber ich wette, dass ich ein Skript schreiben kann, das den Klassenpfad aus dem Manifest extrahiert und automatisch eine relevante Befehlszeile erstellt, also ist dies wahrscheinlich die Antwort, die ich verwenden werde. – Guss

1

Es ist möglicherweise nicht möglich, nur den CLASSPATH zu verwenden. Es gibt Möglichkeiten, den Aufruf an ClassLoader.getResource() einen statischen Pfad verwenden, um die Ressource zu finden. Wenn es das tut, wird der CLASSPATH umgangen.

3

Das mit der Option -jar angegebene JAR-Archiv überschreibt alle anderen Werte.

Sie müssten es in der Regel mit einer externen Konfigurationsdatei oder erstellen Sie Ihre eigene Lösung mit ClassLoader.getResource().

Wir verwenden eine individuelle Lösung dieses Problem zu lösen - wir die inneren Eigenschaften wie so laden:

final Properties p = new Properties(); 
p.load(DefaultConfiguration.class.getResourceAsStream("config.properties")); 

Wir haben dann die externe Datei auf die gleiche Weise laden und die internen Werte mit den externen überschreiben.

Für Informationen darüber, wie das Laden von Klassen Werke sehen:

http://java.sun.com/javase/6/docs/technotes/tools/findingclasses.html

+0

Dies ist in der Tat die Problem. Ich verstehe, dass es keinen anderen Weg gibt, als die Anwendung anders zu starten - wie von alasdairg vorgeschlagen, oder einen benutzerdefinierten Ladecode zu schreiben. Vielen Dank. – Guss

13

wenn Sie die Option -jar verwenden, um Ihre Anwendung zu starten:

... ist die JAR-Datei ist die Quelle aller Benutzerklassen und andere Benutzerklasse Pfadeinstellungen werden ignoriert.

wie beschrieben here. Eine Problemumgehung wäre, den Klassenpfad im Manifest der JAR-Datei anzugeben, um den zusätzlichen Pfad (beschrieben here) einzuschließen.

Da Sie jedoch nur über die Änderung der Konfiguration sprechen, möchten Sie vielleicht einen anderen Ansatz wählen, der nicht vom Klassenpfad abhängig ist. Zum Beispiel konfiguriere ich meine Anwendungen normalerweise über Spring mithilfe von Eigenschaftendateien, um den Speicherort von Datenbanken usw. zu bestimmen. Meine Spring-Konfiguration ist in Test-, QA- und Live-Umgebungen konsistent, übergebe jedoch beim Starten der App eine andere Eigenschaftendatei als Befehlszeilenargument .

Federkonfiguration Snippet

<bean id="MyDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource"> 
    <property name="url" value="jdbc:microsoft:sqlserver://${dbServer}:${dbPort};DatabaseName=${dbName}"/> 
    <property name="username" value="${dbUserName}"/> 
    <property name="password" value="${dbPassword}"/> 
    <property name="suppressClose" value="false"/> 
</bean> 

Property-Datei Snippet

dbServer=MyServer 
dbPort=1433 
dbName=MyDb 
dbUserName=Me 
dbPassword=foobar 
+0

Das Übergeben der Konfigurationsdatei als optionalen Parameter ist eine gute Idee, aber meine Anwendung akzeptiert derzeit eine ganze Reihe von Parametern, und das Hinzufügen eines weiteren wird für die Benutzer problematisch sein. Danke für die Antwort. – Guss

+0

Wie starten Sie Ihre Anwendung? Ich hätte gedacht, dass die übergebenen Parameter dem Benutzer durch den Start der Anwendung über Webstart, .bat oder .sh-Skript etc. verborgen bleiben würden. – Adamski

+0

Nein - die Benutzer starten die Anwendung selbst von der Kommandozeile aus und übergeben die erforderlichen Parameter - Daten , zu verarbeitende Dateien usw. – Guss