# Objekte zwischen zwei Application Contexts austauschen



## NerdIII (24. Jul 2008)

Moin moin,

ich bastele gerade an einer Erweiterung eines Web-Projekts, das Spring verwendet. Diese soll als eigene Web-App laufen, aber Beans und Klasen aus dem Hauptprojekt mitverwenden. Das wirft für mich ein paar Fragen auf. Am wichtigsten ist mir aber momentan: Wie bekomme ich die Erweiterung dazu, die Klassen zu finden und zu laden, die nur im Hauptprojekt existieren. Gibt es da schon ein Rezept?

- kein EAR Projekt, da alles auf einem Tomcat installiert wird und der damit nicht umgehen kann.
- mein Arbeitgeber möchte zwei Projekte daraus machen, so dass sie Erweiterung nicht zwingend auf dem Server installiert wird
- die gemeinsam benutzten Klassen sollen nicht nach jeder Änderung in ein JAR kompiliert und in ein globales lib-Verzeichnis koipiert werden. 
- Nach Möglichkeit soll in Eclipse einfach dem Server das Projekt hinzugefügt oder entfernt werden

Freundliche Grüße,
Marco


----------



## maki (24. Jul 2008)

Maven 2 hilft.


----------



## Niki (24. Jul 2008)

Das heißt die webapps haben zwar nichts mit einander zu tun. Du möchtest nur von einem Projekt die Klassen vom anderen Projekt nutzen? Das wird soweit ich weiß nicht funktionieren, da jede webapp einen eigenen ClassLoader hat. Da müsstest du die gemeinsamen jars ins lib vom tomcat kopieren. Dann hat sie jede webapp. Wenn du aber funktionalität von einer anderen webapp aufrufen willst soltlest du dir etwas anderes überlegen. WebServices z.B.


----------



## byte (24. Jul 2008)

Grundsätzlich kannst Du Deine Anwendung doch in so viele Java-Projekte aufteilen wie Du willst. Du musst dann halt nur mit einem Build-Script aus dem ganzen Kram ein War-File zusammenbauen, das dann auf dem Tomcat deployed wird.

Ich sehe da eigtl. keine Probleme mit Spring, aber ich bin mir nicht sicher, ob ich Dich richtig verstanden habe.


----------



## maki (24. Jul 2008)

Spring selbst ist zB mittlerweile auch zu M2 convertiert worden.

So kann man kann einfach beliebige Module mit dem Core benutzen


----------



## BjörnBu (24. Jul 2008)

meiner Meinung anch ist das nicht so einfach.
Zwei Projekte draus zu machen ist gar kein Problem.

Was auch geht ist über Maven oder sonstwie die Haupt-Applikation in der zweiten als jar einzubinden. Ist auch überhaupt kein Akt beim bauen der Erweiterunbg immer die neuste (oder eine festgelegte) Version der Hauptapplikation zu nutzen ohne diese neu bauen zu müssen.

Prinzipeill sind alle Anforderungen erfüllt, aber so würde die Hauptapplikation quasi zwei mal im Tomcat laufen.

Eine andere Möglichkeit wäre es die Erweiterung in der Hauptapplikation einzubinden. Auch wunderbar easy über Maven. Man kann die Erweiterung einzeln bauen und eigene targets in der Hauptapplikation machen um mit oder ohne Erweiterung zu bauen.

Schon besser... Aber so musst du auch noch bei Änderungen an der Erweiterung die ganze Hauptapplikation neu deployen.

In jedem Fall kommst du leider nicht drumrum dass beides im Endeffekt als eine Webapp läuft (siehe Nikis Post) und auch gemeinsam deployt wird.

ich kenne mich leider null damit aus, aber ich habe im SpringSource Blog bischen was über den Spring ApplicationServer gelesen. Der nutzt OSGI und das macht es möglich Module bzw Bundles einzeln zu re-deployen. So weit ich weiß ist das aber noch nicht wirklich Praxisreif. Für klassische Webapps gibt es meines Wissens nach aber gar keine Möglichkeit so zu modularisieren.

Was sourcen, eclipse projekte und co angeht, geht aber alles wunderbar mit Maven. Nur wenn dann letzendlich deployt werden soll muss man halt alles zusammen anpacken.


----------



## FArt (24. Jul 2008)

NerdIII hat gesagt.:
			
		

> - kein EAR Projekt, da alles auf einem Tomcat installiert wird und der damit nicht umgehen kann.


Ein EAR wäre ja auch EINE Enterpriseapplikation.


			
				NerdIII hat gesagt.:
			
		

> - mein Arbeitgeber möchte zwei Projekte daraus machen, so dass sie Erweiterung nicht zwingend auf dem Server installiert wird


Der erste Trugschluss... man kann auch mit einem Projekt zwei verschiedene Deployment-Units realisieren. Das Projekt (Entwicklung) hat noch nichts mit der Laufzeitapplikation zu tun.


			
				NerdIII hat gesagt.:
			
		

> - die gemeinsam benutzten Klassen sollen nicht nach jeder Änderung in ein JAR kompiliert und in ein globales lib-Verzeichnis koipiert werden.


Lib-Verzeichnis ist immer uncool... für ein sauberes Deployment gehören die Ressourcen in die Applikation (Web-App, oder Enterprise-APP), und nicht mit den Ressourcen des Containers vermengt.

Könnte sein, dass das Tomcat unterstützt... verschiedene Application-Server unterstützen diese Verhalten, indem sie heirarchische Classloader-Repositories einsetzen (z.B. JBoss). Dort könne man die einzelnen Teile einfach in das selbe Repository schmeißen, also z.B. die geteilten Ressourcen, die Applikation und die Erweiterung oder nur die geteilten Ressourcen und die Applikation, je nach Bedarf.


			
				NerdIII hat gesagt.:
			
		

> - Nach Möglichkeit soll in Eclipse einfach dem Server das Projekt hinzugefügt oder entfernt werden


Meinst du, dass das Deployment soll mit Eclipse realisiert werden? Wer drauf steht...

Noch zu deinem Vorhaben: über einen lustigen Mechanismus (JNDI, static, ...) wirst du schon an die auf die Klassen des andren Bereiches zugreifen können. Hier sieht das aber nicht nach einer sauberen Schnittstelle aus. Vielleicht solltet ihr lieber über eine EE Applikation nachdenken? Da gibt es Wege das Verhalten zu realisieren... EJBs wäre dann das Zauberwort für die Schnittstellen...

Annahme: du redest nicht davon, dass zur Laufzeit Ressourcen ausgetauscht werden sollen bzw. die Applikation mit der Erweiterung beglückt bzw. dieser Erweiterung beraubt werden soll...


----------



## Niki (24. Jul 2008)

> lustigen Mechanismus (JNDI, static, ...)



wie soll das mit static gehen? Dachte immer static ist nicht WebApp übergreifend, oder ist es das doch?


----------



## FArt (24. Jul 2008)

Niki hat gesagt.:
			
		

> wie soll das mit static gehen? Dachte immer static ist nicht WebApp übergreifend, oder ist es das doch?



Kommt drauf an, welcher Classloader für das laden der Klassen zuständig ist. Gleicher Classloader, gemeinsame statics...

Ansonsten muss man eh aufpassen... beliebte Probleme: die gleiche Klasse wurde von zwei Classloadern geladen und jetzt will man eine Instanz des einen zum anderen casten, zuweisen, ...  bumm...


----------



## byte (24. Jul 2008)

Genau deswegen ist OSGi ziemlich genial. Hier ein interessanter Artikel zu OSGi auf Serverseite:

http://www.javaworld.com/javaworld/jw-06-2008/jw-06-osgi3.html


----------



## Niki (24. Jul 2008)

Verstehe, das heißt lege ich eine Klasse ins lib Verzeichnis vom Tomcat, und ich habe zwei webapps die diese Klasse verwendet, greifen beide auf die selben static-Members zu - richtig?
Befindet sich aber die Klasse in jeder webapp, hat jede webapp ihre eigenen static Members.

Ist das so korrekt?


----------



## byte (24. Jul 2008)

Nein. Jars im lib Ordner des Tomcats sind zwar für alle Webapps verfügbar, trotzdem lädt jede Webapp diese Klassen mit dem eigenen Classloader.



> WebappX - A class loader is created for each web application that is deployed in a single Tomcat 6 instance. All unpacked classes and resources in the /WEB-INF/classes directory of your web application archive, plus classes and resources in JAR files under the /WEB-INF/lib directory of your web application archive, are made visible to the containing web application, but to no others.


http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html


----------



## Niki (24. Jul 2008)

Hmmm, und wie kann es dann zu Problemen kommen?
Mir ist zum Beispiel mal aufgefallen dass zwei webapps die selben System-Properties haben (in der einen webapp habe ich welche hinzugefügt, diese wurde vor der anderen geladen, die andere webapp hatten dann sie selben System-Properties.)

Die classloader haben ja einen Parent, oder? Wenn der Parent bereits die Klasse geladen hat, müssten ja die anderen beiden Class-Loader die selben static Members haben, oder?

//EDIT: Haben die ClassLoaders für die WebApps den selben Parent?


----------



## Niki (24. Jul 2008)

So, um diese Frage aus der Welt zu schaffen, hier kommt die Antwort:

Befindet sich die Klasse im lib vom Tomcat, haben die WebApps *gemeinsamen* Zugriff auf die statischen Members. Ich habe eine Klasse erstellt die nur eine statische Variable besitzt. Diese Klasse hab ich in ein jar gepackt und dieses ins lib gestellt.
Dann habe ich eine kleine webapp gebastelt, die zwei Servlets hat. Eines zum setzen der statischen Variable und eines zum holen. Diese Webapp habe ich zwei mal mit unterschiedlichen Namen deployt. Setze ich über die WebApp1 die Variable, so hat auch WebApp2 den gleichen Wert.

Manchmal ist einem alles klarer wenn man es selber ausprobiert.


----------



## FArt (24. Jul 2008)

Niki hat gesagt.:
			
		

> Die classloader haben ja einen Parent, oder? Wenn der Parent bereits die Klasse geladen hat, müssten ja die anderen beiden Class-Loader die selben static Members haben, oder?
> 
> //EDIT: Haben die ClassLoaders für die WebApps den selben Parent?



Die wenigsten Appserver nutzen das Standardclassloading-Verhalten. Das Problem wäre ja sonst, dass der Container eine API (z.B. Xerces) in der Version x einsetzt und somit die Applikation auf diese Version festgenagelt wäre.

Wieder Beispiel JBoss:
hier kann ich beliebige Deploymentunits aus dem selben oder aus unterschiedlichen Repositories bedienen, vergleichbar mit einem Classloader (wenn da auch mehrere beteiligt sind). Außerdem kann ich das Verhalten beeinflussen, wie die Ressourcen gesucht werden: erst im eigenen Repositroy und dann im gemeinsamen Repository oder umgekehrt. So kann ich blieblig Applikationen kombinieren oder gegeneinander (oder gegen den Container) isolieren.


----------



## FArt (24. Jul 2008)

Niki hat gesagt.:
			
		

> Manchmal ist einem alles klarer wenn man es selber ausprobiert.



Das ganze gilt nur für die von dir verwenete Tomcat Version in der von dir hier benutzten (Default)Konfiguration.


----------



## Niki (24. Jul 2008)

Ist schon richtig. Man muss sich halt die ClassLoader Funktionalität vom jeweiligen Server durchlesen. Ich habe das ganze mit Tomcat 6 getestet.


----------



## NerdIII (25. Jul 2008)

Danke für die Antworten. Ich würde gerne Maven 2 ausprobieren, aber muss ich dazu nicht einen Fortbildungskurs machen? Wie viel bringt Maven mir? Ich sehe, dass beim BUILD einige Dateien heruntergeladen werden. Kann ich so zum Beispiel auf einem frisch eingerichteten Rechner die libs von Hibernate, Spring, Log4J, ... automatisch nachinstallieren lassen? Wie funktioniert das 'ChangeLog anhand der SVN/CVS-Logs'? Und was gibt es sonst noch, was Maven 2 unerlässlich macht?  :###


----------



## byte (25. Jul 2008)

NerdIII hat gesagt.:
			
		

> Ich würde gerne Maven 2 ausprobieren, aber muss ich dazu nicht einen Fortbildungskurs machen?


Das hängt wohl ganz von Dir ab.


----------



## FArt (25. Jul 2008)

NerdIII hat gesagt.:
			
		

> Ich würde gerne Maven 2 ausprobieren



Das kannst du gerne machen, ist ein feines Tool. Aber das Problem, mit dem du den Thread gestartet hast, wird es nicht lösen. Im Gegenteil, das Problem ist nur verlagert und du hast den erhöhten Aufwand der Einarbeitung in maven.
 ???:L


----------

