# Property File soll neben war-file liegen



## LILA (6. Sep 2011)

Hallo Forum,

ich habe folgendes Problem, in meinem dynamischen WebProjekt will ich Datenbank-Parameter aus einem Property-File laden. Das funktioniert auch soweit mit folgender Struktur und folgendem Aufruf:
Ich nutze EclipseIndigo und Tomcat7.

Struktur:

>Projektname
>|>build
>|>|>classes
>|>|>|>de (neben "de" liegen Properties)
>|>|>|>|>firma
>|>|>|>|>|>projekt
>|>|>|>|>|>|>Hier liegen meine Klassen/Servlets

So rufe ich das Property-File auf:

```
...
BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(".."+File.separator+".."+File.separator+".."+File.separator+"file.properties")));
...
```

Aber eigentlich will ich meine Properties neben dem Ordner "Projektname" ablegen, also so:
>Projektname (neben "Projektname" liegen Properties)
>|>build
>|>|>classes
>|>|>|>de 
>|>|>|>|>firma
>|>|>|>|>|>projekt
>|>|>|>|>|>|>Hier liegen meine Klassen/Servlets

Das Property-File würde ich dann so aufrufen wollen: 

```
...
BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(".."+File.separator+".."+File.separator+".."+File.separator+".."+File.separator+".."+File.separator+".."+File.separator+"file.properties")));
...
```

Allerdings bekomme ich dann immer eine NullPointerException:

```
SCHWERWIEGEND: Servlet.service() for servlet [de.bfs.odlinfo.Stations] in context with path [/StationsServlet] threw exception
java.lang.NullPointerException
	at java.io.Reader.<init>(Unknown Source)
	at java.io.InputStreamReader.<init>(Unknown Source)
	at de.bfs.odlinfo.DbReader.load(DbReader.java:46)
	at de.bfs.odlinfo.DbReader.<init>(DbReader.java:82)
	at de.bfs.odlinfo.Stations.processRequest(Stations.java:53)
	at de.bfs.odlinfo.Stations.doGet(Stations.java:100)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:851)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:278)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
```

Kann es sein, dass ich mit Eclipse nicht auf Quellen ausserhalb meines Webprojektes zugreifen kann.
Ich will ja, dass meine Properties neben dem Projektordner liegen.

Vielleicht noch kurz zu meinen Hintergründen. Ich würde die Properties deshalb gerne neben dem Projektordner haben, weil ich *nicht* will, dass die Properties mit in das WAR-File eingepackt werden.
Denn wir lagern die Properties extra aus, um sie auch auf dem Server einfach kurz ändern zu können.
Wenn Sie aber ins WAR-File integriert sind, kann es ja sein, dass mein Servlet-Container beim erneuten entpacken des WAR-Files die veränderten Properties wieder mit den ursprünglichen überschreibt. Das stimmt doch so, oder?
Und um das Projekt aber auch lokal testen zu können, muss ich genau 6 Ordner-Stufen nach oben schreiten.
In Catalina-Home wollen wir die Properties nicht packen. Das würde ja über eine Umgebungsvariable möglich sein.

Vielen Dank für eure Hilfe.
Schöne Grüße


----------



## mvitz (6. Sep 2011)

Wenn du die Properties nicht mit ins WAR packst, kannst du auf diese nicht per getResourceAsStream zugreifen (abgesehen davon, dass ich mir File.separator sparen würde und hier immer den / nehmen würde [macht es leserlicher und der / ist in Java Plattform-Kompatibel]).

In dem Falle, macht man es afaik so, dass man den Ort zu dem Property per JVM, oder web.xml-Parameter übergibt und dann doch direkt mit der java File API arbeitet. Dadurch geht dir zwar unter Umständen Dinge wie Clustering verloren (außer dann ist das File auch immer am selben Ort) aber getResourceAsStream ist nunmal grundsätzlich nur für Dinge da, die 1. deployed werden (und das würde das property file nicht) und 2. im classpath vorhanden sind.


----------



## LILA (6. Sep 2011)

Hallo mvitz,

danke für die Antwort.
Wenn ich das Richtig verstehe, würde ich aber im web.xml einen festen Parameter angeben.
Ich würde aber gerne das Property-File 6 Stufen über den class-Files ablegen.
Also immer neben dem Projektordner, wie kann ich das machen? Mit relativem Pfad von Class aus!

Kennst du ein gutes Tutorial zu web.xml-Parametern?

Und dann hätte ich noch eine Verständnisfrage:
Wenn ich ein War-File in einem Servlet-Container entpacken lasse, erhalte ich einen neuen Ordner, mit Class-Files, Libraries und ggf. Property-Files. Wann und wie oft wird dieses War-File wieder entpackt.
Uns geht es nämlich darum, dass wir im Property-File Datenbank-Verbindungs-Parameter speichern wollen. Diese sollen aber nicht überschrieben werden!

Wäre super, wenn du nochmal was schreiben könntest. Bin recht unerfahren in Programmierung und habe wenig Hilfe!
Danke für den Tip mit dem File.Seperator.


----------



## mvitz (6. Sep 2011)

Also soweit ich mich erinnere, steht in keiner Spec überhaupt drin, dass ein ServletContainer das WAR entpacken muss (auch wenn es afaik die meisten machen). Und genau da setzt ja schon das Problem an, sollte einer das mal nicht machen, dann sind 6 Ordner weiter oben schon wieder völlig falsch.

Da ich persönlich bisher noch nie ein File woanders abgelegt habe, kann ich dir jetzt auch leider nicht 100% helfen.

Bezüglich web.xml init parameter: Set the context parameters in web.xml : ContextServletsJava


----------



## freez (8. Sep 2011)

Ich schliesse mich mvitz an:

Es macht einfach mehr Sinn, dass du dir einen Ordner deiner Wahl nimmst und dort dein File ablegst. Diesen Ordner musst du jetzt deiner Anwendung bekannt machen. Dies kannst du entweder über die web.xml machen (wäre mein bevorzugter Weg) oder du legst dir ein Property-File in dein Projekt, der den Ordner enthält, so wie du es mit deinem Property-File vor hattest und lädst dieses wiederrum mit [c]getClass().getResourceAsStream[/c].

Wenn du deine Anwendung auf viele verschiedene Server deployen möchtest, muss der Ordner entweder immer gleich sein (sonst müsstest du für jeden Server ein WAR File generieren) oder du kannst mit Betriebssystemmitteln (z.B. Umgebungsvariablen oder sowas) diesen Ordner festlegen.

Du könntest natürlich auch mit [c]new File(".")[/c] versuchen herauszufinden, welcher Ordner gerade der aktuelle ist und von da aus immer zu dem selben Ordner (relativ gesehen) navigieren.


----------



## LILA (8. Sep 2011)

Hallo ihr Beiden,

ich danke euch für eure Hilfe!
Das hat mir sehr bei meiner Entscheidungshilfe geholfen.
Ich werde es jetzt so machen, dass sich mein Programm auf eine Umgebungsvariable --> Tomcat/webapps bezieht.
Sobald diese gesetzt ist, ist die Ordnerstruktur der unterschiedlichen Systeme egal.
Vielen Dank!


----------



## freez (9. Sep 2011)

Hallo Lila,

es wäre schön, wenn du deine Lösung mit Codebeispielen präsentieren würdest, da dies schon ein interessanter Fall ist, der mit Sicherheit öfter auftritt.


----------



## LILA (15. Sep 2011)

Hallo,

besser spät als nie:

Mein Properties-File rufe ich in meiner Anwendung so auf:

```
private String configFile = System.getenv("TOMCAT_WEBAPPS")+File.separator+"conf"+File.separator+"config.properties"
```

Lokal auf meinen Windows-Rechner habe ich eine Umgebungsvariable "TOMCAT_WEBAPPS" gesetzt.
(Windows XP)

Auf dem Produktivserver habe ich in tomcat.conf ebenfalls wine Umgebungsvariable "TOMCAT_WEBAPPS" gesetzt.
(Linux OEL)

Schöne Grüße


----------

