2008-11-06 9 views
14

Derzeit haben wir eine Webanwendung, die einen Spring-Anwendungskontext lädt, der einen Stapel von Geschäftsobjekten, DAO-Objekten und Hibernate instanziiert. Wir möchten diesen Stapel mit einer anderen Webanwendung teilen, um zu vermeiden, dass mehrere Instanzen derselben Objekte vorhanden sind.Was ist der beste Weg, Geschäftsobjektinstanzen zwischen Java Web Apps mit JBoss und Spring zu teilen?

Wir haben verschiedene Ansätze untersucht; Aussetzen der Objekte mithilfe von JMX oder JNDI oder mithilfe von EJB3.

Die verschiedenen Ansätze haben alle ihre Probleme, und wir suchen nach einer leichten Methode.

Irgendwelche Vorschläge, wie man das löst?

Edit: Ich habe Kommentare erhalten anfordernden mich ein bisschen zu erarbeiten, geht so hier:

Das Hauptproblem wir lösen wollen, ist, dass wir nur eine Instanz von Hibernate haben wollen. Dies liegt an Problemen mit der Ungültigmachung des Secondlevel-Caches von Hibernate, wenn mehrere Client-Anwendungen ausgeführt werden, die mit derselben Datenquelle arbeiten. Auch der Business-/DAO/Hibernate-Stack wird ziemlich groß, so dass es nicht sinnvoll ist, ihn zu duplizieren.

Zuerst haben wir versucht zu sehen, wie die Business-Schicht allein anderen Web-Anwendungen ausgesetzt sein könnte, und Spring bietet JMX-Wrapping zum Preis einer winzigen Menge an XML. Es war uns jedoch nicht möglich, die JMX-Entitäten an die JNDI-Struktur zu binden, sodass wir die Objekte nicht über die Webanwendungen suchen konnten.

Dann versuchten wir, die Business-Schicht direkt an JNDI zu binden. Obwohl Spring keine Methode dafür bot, war die Verwendung von JNDITemplate, um sie zu binden, auch trivial. Dies führte jedoch zu mehreren neuen Problemen: 1) Der Sicherheitsmanager verweigert den Zugriff auf den RMI-Klassenlader, so dass der Client fehlschlug, nachdem wir versucht hatten, Methoden auf der JNDI-Ressource aufzurufen. 2) Sobald die Sicherheitsprobleme gelöst wurden, hat JBoss IllegalArgumentException ausgelöst: Objekt ist keine Instanz der deklarierenden Klasse. Ein bisschen Lesen zeigt, dass wir Stub-Implementierungen für die JNDI-Ressourcen benötigen, aber das scheint eine Menge Ärger (vielleicht hilft uns der Frühling?)

Wir haben noch nicht zu viel in EJB geschaut, aber nach dem ersten Bei zwei Versuchen frage ich mich, ob das, was wir erreichen wollen, überhaupt möglich ist.

Zusammenfassend, was wir erreichen wollen: Eine JBoss-Instanz, mehrere Web-Apps, die einen Stapel von Geschäftsobjekten über DAO-Ebene und Hibernate verwenden.

Mit freundlichen Grüßen,

Nils

+0

Können Sie etwas zu 1. Was Sie versuchen zu lösen versuchen; 2. Die Probleme, die Sie bei den von Ihnen genannten Ansätzen gefunden haben. Dies würde eine zielgerichtetere Antwort ermöglichen ... – johnstok

+0

Es war schwierig, alles in 300 Zeichen zu sagen, also habe ich die Frage bearbeitet, um weitere Details hinzuzufügen :-) –

Antwort

5

Sind die Webanwendungen auf demselben Server implementiert?

Ich kann nicht für Spring sprechen, aber es ist einfach, Ihre Geschäftslogik mithilfe von Session Beans in die EJB-Ebene zu verschieben.

Die Anwendung Organisation ist geradlinig. Die Logik geht in Session Beans über, und diese Session Beans werden in einem einzigen Jar als Java EE-Artefakt mit einer ejb-jar.xml-Datei gebündelt (in EJB3 ist diese Datei wahrscheinlich praktisch leer).

Dann bündeln Sie Entity-Klassen in eine separate JAR-Datei.

Als Nächstes werden Sie jede Webanwendung in ihre eigene WAR-Datei einbauen.

Schließlich werden alle JARS und WARS in einem Java EE EAR mit der zugehörigen Datei application.xml gebündelt (wiederum wird dies wahrscheinlich ziemlich minimal sein, indem einfach die JARs in der EAR aufgelistet werden).

Diese EAR wird im Großhandel zum App-Server bereitgestellt.

Jede WAR ist effektiv unabhängig - ihre eigenen Sitzungen, ihre eigenen Kontextpfade usw. Aber sie teilen sich das gemeinsame EJB Backend, so dass Sie nur einen einzigen 2nd Level Cache haben.

Sie verwenden auch lokale Referenzen und semantische Aufrufe, um mit den EJBs zu kommunizieren, da sie sich auf demselben Server befinden. Keine Notwendigkeit für Remote-Anrufe hier.

Ich denke, das ganz gut, das Problem löst die Sie haben, und sein ist ganz einfach in Java EE 5 mit EJB 3.

Sie können aber auch noch Frühling verwenden für viel von Ihrer Arbeit, wie ich sie verstehe , aber ich bin kein Frühling, also kann ich nicht mit den Details sprechen.

+0

Ja, alles wird auf demselben Server bereitgestellt. Das sieht ziemlich interessant aus, ich gebe EJB heute eine Chance. Mein Punkt über Frühling ist, dass es anbietet, Bohnen für z.B. JMX ohne Code, aber anscheinend nicht für EJB. Jedenfalls schaue ich heute auf den EJB-Ansatz. –

-1

Werfen Sie einen Blick auf JBossCache. Es ermöglicht Ihnen das einfache Teilen/Replizieren von Karten von Daten zwischen mehreren JVM-Instanzen (gleich oder verschieden). Es ist einfach zu bedienen und verfügt über viele Protokolloptionen auf Wire-Level (TCP, UDP Multicast, etc.).

3

Terracotta könnte hier eine gute Passform sein (Offenlegung: Ich bin ein Entwickler für Terrakotta). Terracotta gruppiert Java-Objekte auf JVM-Ebene transparent und integriert sich in Spring und Hibernate. Es ist kostenlos und Open Source.

Wie Sie sagten, das Problem von mehr als einer Client-Webanwendung, die einen L2-Cache verwendet, hält diese Caches synchron. Mit Terracotta können Sie einen einzelnen Hibernate L2-Cache clustern. Jeder Client-Knoten arbeitet mit seiner Kopie dieses gruppierten Cache, und Terracotta hält ihn synchron. This link erklärt mehr.

Wie für Ihre Business-Objekte können Sie Terrakotta verwenden Spring integration Ihre Bohnen Cluster - jeder Web-App kann geclustert Bean-Instanzen teilen und Terracotta hält den gruppierten Zustand synchron transparent.

0

Ich bin nicht wirklich sicher, was Sie versuchen zu lösen; Am Ende des Tages wird jeder jvm entweder Instanzen der Objekte repliziert haben oder Stubs, die Objekte repräsentieren, die auf einem anderen (logischen) Server existieren.

Sie könnten einen dritten Business-Logik-Server einrichten, der über eine Remote-API verfügt, die Ihre beiden Web-Apps aufrufen können. Die typische Lösung ist die Verwendung von EJB, aber ich denke, dass spring Remoting-Optionen in seinen Stack integriert hat.

Die andere Option besteht darin, eine Form der gemeinsamen Cache-Architektur zu verwenden ... die Objektänderungen zwischen den Servern synchronisiert, aber Sie haben immer noch zwei Instanzen.

+0

Nicht so, wenn Sie Terracotta –

2

Eigentlich, wenn Sie eine leichte Lösung wollen und keine Transaktionen oder Clustering benötigen, verwenden Sie einfach die Spring-Unterstützung für RMI. Es ermöglicht Spring Beans aus der Ferne mit einfachen Anmerkungen in den neuesten Versionen zu entlarven. Siehe http://static.springframework.org/spring/docs/2.0.x/reference/remoting.html.

+0

verwenden Ich habe diesen Ansatz verwendet, um freigegebene Spring-Beans von einer Webanwendung zugreifen. Es funktioniert, obwohl ich immer noch denke, dass es wahrscheinlich eine bessere/sauberere Lösung gibt. – Mark

+0

Wenn Sie RMI nicht mögen, bietet Spring einige andere Remoting-Optionen an - Hessian, Burlap und HttpInvoker (Spring's eigene Remoting-Lösung - Java-Serialisierung über HTTP). Natürlich gibt es auch immer Webdienste. –

1

Vielen Dank für Ihre Antworten bisher. Wir sind immer noch nicht ganz da, aber wir haben jetzt ein paar Dinge ausprobiert und sehen die Dinge klarer. Hier ein kurzes Update:

Die Lösung, die am lebensfähigsten erscheint, ist EJB. Dies wird jedoch einige Änderungen in unserem Code erfordern. Daher werden wir diese Lösung derzeit nicht vollständig implementieren. Ich bin fast überrascht, dass wir nicht in der Lage waren, eine Spring-Funktion zu finden, die uns hier helfen könnte.

Wir haben auch versucht, die JNDI-Route, die mit der Notwendigkeit für Stubs für alle freigegebenen Schnittstellen endet. Das ist sehr mühsam, wenn man bedenkt, dass sich sowieso alles auf demselben Server befindet.

Gestern hatten wir einen kleinen Durchbruch mit JMX. Obwohl JMX definitiv nicht für diese Art von Verwendung gedacht ist, haben wir bewiesen, dass es möglich ist - ohne Code-Änderungen und eine minimale Menge an XML (ein großes Dankeschön an Spring für MBeanExporter und MBeanProxyFactoryBean). Die Hauptnachteile dieser Methode sind die Leistung und die Tatsache, dass unsere Domain-Klassen über den JBoss-Server/lib-Ordner freigegeben werden müssen. Das heißt, wir müssen einige Abhängigkeiten von unseren WARs entfernen und sie auf server/lib verschieben, andernfalls erhalten wir ClassCastException, wenn die Business-Schicht Objekte aus unserem eigenen Domänenmodell zurückgibt. Ich verstehe völlig, warum das passiert, aber es ist nicht ideal für das, was wir erreichen wollen.

Ich dachte, es wäre Zeit für ein kleines Update, denn was die beste Lösung zu sein scheint, wird einige Zeit in Anspruch nehmen. Ich werde unsere Ergebnisse hier veröffentlichen, sobald wir diesen Job erledigt haben.

+0

Es wurde mehrmals auf diesem Thread von mir und anderen vorgeschlagen, aber haben Sie sich Terracotta angesehen? Im Gegensatz zu allen anderen Lösungen, die bisher vorgestellt wurden, ist es explizit für die gemeinsame Nutzung von Zuständen konzipiert. –

2

Sie sollten sich die Terracotta Reference Web Application - Examinator ansehen. Es hat die meisten Komponenten, die Sie suchen - es hat Hibernate, JPA und Spring mit einem MySQL-Backend.

Es wurde auf bis zu 16 Knoten skaliert, 20k gleichzeitige Benutzer.

bestellen hier aus: http://reference.terracotta.org/examinator

1

Frühling einen Integrationspunkt hat, die für Sie von Interesse sein könnte: EJB 3 injection nterceptor. Dadurch können Sie auf Frühlingsbohnen von EJBs zugreifen.