# Deployment und Konfiguration mit Tomcat



## meisteryoda (24. Okt 2009)

Hallo, ich habe folgende Problemstellung:

Eine Anwendung, nennen wir sie Warfile1, wird in einen 
Tomcat deployed. 

Je nachdem, welchen Zweck diese Anwendungsinstanz 
erfüllen soll, muss sie unterschiedlich konfiguriert werden
können. Beispiel: Auf der Testmaschine arbeitet die Anwendung
gegen eine Testdatenbank, auf der Produktion gegen die
Produktionsdatenbank. Ich möchte aber für beide 
Deployments dasselbe Warfile1 verwenden.

Um das zu erreichen, müsste ich der Anwendung mitteilen können, 
welche Konfiguration sie einlesen soll. Wenn es sich um eine reine
Webanwendung handeln würde, wäre das kein Problem, die
Information käme dann im Request an, dort kann ich dann
auslesen, "welcher Kontext ich bin". Aber die Anwendung 
hat zusätzlich einen Batch-Modus, der mit dem Hochfahren
von Tomcat startet. Spring-Beans sorgen hier dafür, dass
die Anwendung zyklisch gewisse Prozesse ausführt.

Aber woher soll die Anwendung wissen, welche Konfiguration
zu ihr gehört? Da ich dasselbe Warfile1 für unterschiedliche 
"Instanzen" verwenden will, kann die Information nicht allein
im Warfile stecken. Ich müsste zusätzlich die Information 
injizieren können:

Anwendung 1: Du bist A1 und sollst die Datenbank1 konnektieren.
Anwendung 2: Du bist A2 und sollst die Datenbank2 konnektieren.

Habt ihr eine Idee, wie man das bewerkstelligen könnte?

- M.


----------



## vinculum (25. Okt 2009)

Hi,

ich würde versuchen die Hostadresse zu erkennen, handelt es sich um die Testmaschine wird die Test-DB verwendet ansonsten die Produktions-DB.

Hier wird diskutiert wie man an die entsprechende Information kommt: Java Servlet - Re: How can applet determine server's IP address

Viel Erfolg!


----------



## mvitz (25. Okt 2009)

Wenn es nur um die DB geht und diese vom selben Hersteller ist, was spricht dann dagegen, die DB über JNDI zu beziehen? Dann ist der jeweilige Tomcat dafür verantwortlich und du brauchst am War nichts zu verändern.


----------



## vinculum (25. Okt 2009)

Stimmt, das wäre noch besser als mein Vorschlag!


----------



## meisteryoda (26. Okt 2009)

Problem dabei: Ich muss erstmal an den Kontextnamen kommen.
Habe aber kein Servlet in der Hand - getServletContext() geht somit
IMHO nicht. Wie kann ich denn den Wurzelnamen meiner deployten
Anwendung herausfinden, wenn ich nicht an das Kontext-Objekt komme?

- M.


----------



## byte (26. Okt 2009)

Warum willst du umbedingt das gleiche War-File benutzen? Ich halte das für den falschen Weg.

Das Standard-Vorgehen sieht eigentlich so aus, dass man sich verschiedene Build-Scripts schreibt. Je nachdem, welche Build-Script Du ausführst, fliegt unten ein fertiges War-File raus. Da sind dann die entsprechenden Properties schon gesetzt.

Ich benutze dafür Maven2, aber es funktioniert genauso gut auch mit Ant. Ich kann mit einem Klick ein War-File für lokale Tests, ein Remote Testsystem oder das Produktivsystem erzeugen.

Wenn Du Spring verwendest, ist das Austauschen der Properties übrigens recht einfach. Du kannst z.B. einen PropertyPlaceholderConfigurer verwenden, um unterschiedliche Properties aus einer Property-Datei zu laden. Du musst dann nur noch dafür sorgen, dass in den verschiedenen Build-Scripts die richtigen Property-Dateien angezogen werden.

Maven2 kann auch recht easy Properties aus einer Datei in den Konfig-Dateien ersetzen. Das funktioniert genauso wie bei Spring, also auch mittels ${...} Syntax.


----------



## meisteryoda (27. Okt 2009)

byte hat gesagt.:


> Warum willst du umbedingt das gleiche War-File benutzen? Ich halte das für den falschen Weg.



Die Anwendung wird in einer bisher SAP-lastigen Umgebung im
Bankenumfeld deployed. Dort besteht eine relativ statische
Vorstellung vom Deployment aus Entwicklung nach Test und
Produktion.

Überträgt man diese Vorstellung in die Java-Welt, so stellt sich
die Frage, *was* man eigentlich deployed - was *ist *eine Version,
die von Entwicklung nach Test, dann von Test nach Produktion geschoben
wird. Baue ich für diese drei Rechner drei unterschiedliche WAR-Files, 
wie kann ich dann sicher sein, dass die auf Test abgenommene Version
tatsächlich genau die ist, die auf Produktion freigegeben werden soll.
Immerhin könnte der Build etwas "anders" machen.

Multipliziert man jetzt dieses Szenario noch mit diversen Instanzen
der Anwendung, die nämlich tatsächlich gewissermaßen "mehrfach",
nämlich für unterschiedliche Stakeholder in unterschiedlichen Konfigurationen
produktiv geht, so hat man eine Matrix vor Augen, die alles in allen
3 x n Umgebungen umfasst. Ich möchte einfach nicht 3 x n Warfiles
bauen. Sondern das eine Warfile, das die neue Version / Release darstellt,
soll auf alle betroffenen Rechner deployed werden. Die Unterschiede
sollen lediglich noch in textuell editierbaren Properties-Dateien liegen.

Vielleicht macht es das etwas verständlicher. 

- M.


----------



## maki (27. Okt 2009)

> was man eigentlich deployed - was ist eine Version,


Nun, zu den meisten Anwendungen gehört doch auch eine Db bzw. ein ganz bestimmter DB Stand(Struktur & Daten), diese wird doch auch nicht mitausgeliefert beim Deployment der WebApp 



> Multipliziert man jetzt dieses Szenario noch mit diversen Instanzen
> der Anwendung, die nämlich tatsächlich gewissermaßen "mehrfach",
> nämlich für unterschiedliche Stakeholder in unterschiedlichen Konfigurationen
> produktiv geht, so hat man eine Matrix vor Augen, die alles in allen
> ...


Wenn man bedenkt das eine best. Konfiguration auch eine eigene Version darstellt (deswegen heisst es doch Konfigurationsmanagement), dann hättest du ja dann eine Version in Prod die nicht im Repo liegt, oder? 

Ich finde bytos Vorschlag da die bessere Variante, mit einem vernünftigen Buildsystem (zB. Maven2) und Versionierungssystem (zB. SVN) ist das auch gar kein Problem, dann passiert so etwas auch nicht:


> "Immerhin könnte der Build etwas "anders" machen."


----------



## byte (27. Okt 2009)

meisteryoda hat gesagt.:


> Überträgt man diese Vorstellung in die Java-Welt, so stellt sich
> die Frage, *was* man eigentlich deployed - was *ist *eine Version,
> die von Entwicklung nach Test, dann von Test nach Produktion geschoben
> wird. Baue ich für diese drei Rechner drei unterschiedliche WAR-Files,
> ...



In der SAP Welt läuft das natürlich etwas anders. Da deployest Du als Entwickler idR nur ins Testsystem und irgendein Verantwortlicher kann das dann automatisch ins QS / Prod übernehmen. Aber da läuft das Ganze ja eh etwas anders ab. Da ist der DB Zugriff fest in der SAP Software verdrahtet, so dass Du gar nicht in die Verlegenheit kommst, Dich um die Konfiguration der DB Daten zu kümmern.

Der von mir oben beschriebene Prozess ist natürlich nicht idiotensicher. Du kannst natürlich Sourcen ändern und eine andere Version für Prod generieren, als Du vorher getestet hast. Ich bin einfach mal stillschweigend davon ausgegangen, dass der Prozess richtig gelebt wird und nicht irgendein Entwickler ungetesteten Code ins Prod deployed.

Man könnte halt sonst noch den Weg gehen, die Datasource per JNDI zur Verfügung zu stellen. Damit wäre die Konfiguration der Datasource nicht im War File enthalten. Du hättest dann also auf jedem Server die entsprechende Datasource per JNDI zur Verfügung und könntest diese im Warfile abgreifen. Somit könntest Du mit dem gleichen War File je nach Umgebung entweder auf die Test-, QS- oder Prod-Datenbank zugreifen.

Man könnte dann direkt fürs QS/Prod das Warfile aus dem Test übernehmen, wenn das fehlerfrei getestet wurde.


----------

