Kombinieren Sie das Sitzungsfassadenmuster mit XML

Das Entwurfsmuster für Sitzungsfassaden ist beliebt für die Entwicklung von Unternehmensanwendungen auf der Basis von J2EE (Java 2 Platform, Enterprise Edition). Es erzwingt nicht nur das Design wiederverwendbarer Anwendungsarchitekturen, sondern bietet auch viele Vorteile, darunter reduzierten Netzwerk-Overhead, zentrales Sicherheitsmanagement und Transaktionskontrolle, grobkörnige Abstraktion von Geschäftsdaten und Serviceobjekten sowie reduzierte Kopplung zwischen Clients und Geschäftsobjekten.

Das Entwurfsmuster für Sitzungsfassaden ist ein Muss, um Software mit J2EE erfolgreich zu entwickeln. Es ist schwierig zu entscheiden, wie die Sitzungsfassade in einem bestimmten Projekt am effektivsten eingesetzt werden kann. Es sind viele Faktoren zu berücksichtigen: Projektgeschäftsanforderungen, Projektumfang und Komplexität, um nur einige zu nennen. In den meisten Situationen verwenden Entwickler das Sitzungsfassadenmuster mit Value Object und anderen verwandten Entwurfsmustern. Ich habe jedoch in mehreren Projekten einige Einschränkungen für diesen Ansatz festgestellt, insbesondere beim Erstellen großer und komplexer Systeme.

In diesem Artikel werde ich zunächst eine Einführung in das Entwurfsmuster der Sitzungsfassade, die damit verbundenen Vorteile sowie die Vor- und Nachteile bei der Verwendung der Sitzungsfassade mit dem Wertobjektmuster geben. Dann werde ich die alternative Lösung vorstellen: Sitzungsfassade mit XML.

Sitzungsfassadenübersicht

Das Entwurfsmuster für Sitzungsfassaden verwendet eine Enterprise Session Bean als Fassade, die die zugrunde liegenden Geschäftsobjektinteraktionen abstrahiert und Clients eine einheitliche, grobkörnige Servicezugriffsschicht bietet.

In einer verteilten J2EE-Anwendung interagiert die Client-Tier-Anwendung mit dem Server, indem sie Daten zwischen sich und der EJB-Schicht (Enterprise JavaBeans) austauscht. Aufgrund des Overheads mehrerer Netzwerkanrufe und der schlechten Parallelität kann es ein Leistungskiller sein, wenn die Anwendung auf Clientebene direkt mehrere fein abgestimmte Methoden für EJB-Komponenten von Sitzungen / Entitäten (die ich Geschäftsobjekte nenne) in der EJB-Ebene der J2EE-Anwendung aufruft .

Stellen Sie sich eine J2EE-Bankanwendung vor, bei der ein Bankkunde einen Bankangestellten auffordert, Geld von seinem Sparkonto auf sein Girokonto zu überweisen. In diesem Szenario muss die eigenständige Bankkundenanwendung zuerst den Kunden validieren, bevor Geld vom Sparkonto abgebucht und auf das Girokonto eingezahlt wird. Das Sequenzdiagramm in Abbildung 1 zeigt die Interaktion zwischen der Client-Schicht und der EJB-Schicht.

Dieser Ansatz weist zwei Hauptnachteile auf. Erstens skaliert es nicht. Die Clientanwendung muss Remote-Aufrufe an jede Enterprise-Bean senden. Insgesamt gibt es sechs Netzwerkanrufe, wie im Sequenzdiagramm von Abbildung 1 dargestellt.

Der zweite Nachteil: Dieser Ansatz weist eine schlechte Parallelität auf. Die Clientanwendung muss die Anrufe zu SavingAccountund CheckingAccountinnerhalb einer Transaktion umschließen, um das Kundenkonto in einem konsistenten Zustand zu halten. Die Transaktion wird aufgrund des Netzwerk-Overheads länger dauern. Infolgedessen erhöht dieser Ansatz zwangsläufig die Wahrscheinlichkeit eines Deadlocks und verringert die Parallelität.

Die Lösung für unser Design-Dilemma besteht darin, eine übergeordnete Abstraktionsschicht zwischen der Client-Schicht-Anwendung und der EJB-Schicht mithilfe des Sitzungsfassaden-Entwurfsmusters hinzuzufügen, das als Sitzungs-Bean implementiert ist. Das Sequenzdiagramm in Abbildung 2 zeigt die Interaktionen zwischen dem Client und den EJB-Ebenen, nachdem eine Sitzungs-Bean für die Bankensitzungsfassade hinzugefügt wurde.

In unserem Beispiel reduziert die Sitzungsfassade die Anzahl der Netzwerke von sechs auf eins. Der Zugriff auf jede Entity-Bean erfolgt jetzt über die lokale Schnittstelle und nicht mehr über die Remote-Schnittstelle. Dies minimiert den Netzwerk-Overhead. Die Session Bean von Session Façade kapselt die gesamte Logik für die Geschäftsdomäne und zentralisiert die Transaktionen auf dem Server. Dies führt zu einer hohen Parallelität.

In unserer Bankanwendung verwenden wir einen Methodenaufruf transfer()mit Parametern, um Daten von der Client-Ebene über die Sitzungsfassade zur EJB-Ebene zu übertragen. Dieser Ansatz wird für anspruchsvolle Geschäftsdomänenanwendungen, die höchstwahrscheinlich große Mengen an Parametern verarbeiten, bald außer Kontrolle geraten. Darüber hinaus sollten wir mit der Sitzungsfassade nicht mehrere fein abgestimmte Anrufe verwenden, um Massendaten aufgrund des Netzwerk-Overheads zu übertragen. Dies ist einer der Gründe, warum wir das Sitzungsfassadenmuster überhaupt in unser Beispiel aufgenommen haben. Stattdessen transfer()können Sie das Wertobjekt-Entwurfsmuster für den Datenaustausch zwischen dem Client und den EJB-Ebenen über die Session-Beans der Sitzungsfassade verwenden. Ein Wertobjektist eine serialisierbare Java-Klasse, die Geschäftsdaten kapselt. Dieses Codefragment zeigt das Wertobjekt AccountTransferValueObject, das transfer()in unserem Beispiel für eine Bankanwendung ersetzt werden kann :

öffentliche Klasse AccountTransferValueObject implementiert java.io.Serializable {private String customerPK; private String fromAccountPK; private String toAccountPK; privater Floatbetrag; ... public String getCustomerPK () {return customerPK; } public String getFromAccountPK () {return fromAccountPK; } public String getToAccountPK () {return toAccountPK; } public float getTransferAmount () {Rückgabebetrag; } public void setCustomerPK (String customerPK) {this.customerPK = customerPK; } public void setFromAccountPK (String fromAccountPK) {this.fromAccountPK = fromAccountPK; } public void setToAccountPK (String toAccountPK) {this.toAccountPK = toAccountPK; } public void setTransferAmount (Float-Betrag) {this.amount = Betrag; }}

Wenn die Client-Schicht Daten zur Verarbeitung an die EJB-Schicht sendet, erstellt die Client-Schicht ein Wertobjekt, um alle erforderlichen Informationen zu verpacken, und sendet das Objekt über eine Sitzungsfassadenschnittstelle an die EJB-Schicht. Wenn die Client-Schicht Daten von der EJB-Schicht empfängt, erstellt die EJB-Schicht Wertobjekte, um alle von den Entity-Beans gesammelten Informationen zu verpacken, und sendet die Objekte über eine Sitzungsfassadenschnittstelle an die Client-Schicht.

Die Herausforderungen bei der Verwendung der Sitzungsfassade mit Value Object

Für gut verstandene und einfache Geschäftsbereiche können Sie leicht Wertobjekte definieren. Für anspruchsvolle Geschäftsdomänen wird diese Aufgabe aufgrund ihrer potenziell großen Anzahl von Wertobjekten und Anpassungsanforderungen kompliziert, selbst wenn die Analyse- und Designteams die Geschäftsdomäne gründlich analysiert haben.

Die Verwendung des Sitzungsfassadenmusters mit Value Object bietet außerdem die folgenden Herausforderungen:

  • Wenn die Client-Schicht Massendaten von der EJB-Schicht empfängt, empfängt der Client entweder Wertobjekte oder eine Ausnahme, jedoch nicht beide. In realen Anwendungen möchten Sie manchmal sowohl Wertobjekte als auch Geschäftsausnahmen von der EJB-Ebene abrufen. Unter Leistungsgesichtspunkten ist es teuer, jedes Mal, wenn eine Geschäftsregelüberprüfung auf der EJB-Ebene fehlschlägt, eine Geschäftsausnahme für Anwendungen auszulösen. Immer wenn eine Ausnahme ausgelöst wird, muss die JVM aufgrund des neu erstellten Geschäftsausnahmeobjekts den Aufrufstapel reparieren. Ausnahmen sollten nur für Fehlerbedingungen verwendet werden.
  • Die Kopplung und Abhängigkeit zwischen den Client- und EJB-Ebenen wird nur reduziert, nicht beseitigt, sodass eine parallele Entwicklung der verschiedenen Anwendungsschichten nicht vollständig erreicht werden kann. Ohne die Ebene "Sitzungsfassade" müssen Clients die detaillierten Methoden für EJB-Komponenten (Geschäftsobjekte) von Sitzungen / Entitäten direkt aufrufen. Wenn sich Geschäftsobjekte in Zukunft ändern müssen, müssen Sie auch die Clients ändern. Durch die Einführung der Sitzungsfassadenebene können Sie möglicherweise vermeiden, die Clients zu ändern, wenn sich Geschäftsobjekte ändern. Infolgedessen wird die Kopplung und Abhängigkeit zwischen den Client- und EJB-Ebenen verringert. Die Client-Schicht ist jedoch weiterhin über Wertobjekte mit der EJB-Schicht gekoppelt. Wenn sich die Wertobjekte ändern, müssen Sie normalerweise die Client-Tier-Klassen neu kompilieren. Da sich Wertobjekte häufig ändern,Sie können einen schrecklichen Engpass zwischen dem Client und den EJB-Ebenen verursachen, insbesondere bei großen Projekten mit einer großen Anzahl von Wertobjekten.
  • Die Verwendung des Sitzungsfassadenmusters mit Value Object bietet keine implizite Audit-Trail-Funktion. Da Unternehmensanwendungen immer komplizierter werden, müssen verschiedene Anwendungen miteinander interagieren. Mit der integrierten Audit-Trail-Funktion können Systemaktivitäten ordnungsgemäß verfolgt und überwacht werden, während Anforderungen für die Anwendungsverarbeitung verschiedene Anwendungsebenen oder sogar verschiedene Unternehmensanwendungen durchlaufen.

XML zur Rettung

Als Alternative zu Wertobjekten verwenden wir XML-Datenströme, um beliebige Datensätze zwischen Ebenen über die Session Beans der Session Façade auszutauschen. Dieses in Abbildung 3 dargestellte vereinfachte XML-Schema definiert die Struktur, den Inhalt und die Semantik der XML-Dokumente, die zum Austausch von Datensätzen zwischen dem Client und den EJB-Ebenen verwendet werden.

Die Client-Schicht verwendet den inputKnoten, um Anforderungsdaten, die zur Verarbeitung an die EJB-Schicht gesendet werden, flexibel zu verpacken. Der inputKnoten kann null oder mehr fieldsetKnoten enthalten. Ein fieldsetKnoten kann einen oder mehrere fieldKnoten und null oder mehrere datasetKnoten enthalten. Ein fieldKnoten kann ein oder mehrere valueElemente haben, die jeweils den tatsächlichen Wert enthalten field. Der fieldKnoten kann ein Datenarray enthalten. Die Knoten fieldset, fieldund datasetalle haben ein erforderliches nameAttribut.

Die EJB-Schicht verwendet den outputKnoten, um eine Antwort an die Client-Schicht zurückzusenden. Der outputKnoten ist auch flexibel. Es kann sowohl flache tabellarische Daten als auch hierarchische Daten zurücksenden. Die Hauptdatenstruktur innerhalb des outputKnotens ist der datasetKnoten. outputkann null oder mehr datasetKnoten enthalten, die wiederum null oder mehr rowKnoten und null oder mehr verschachtelte datasetKnoten haben können.

The client and EJB tiers exchange information about application business domain-related errors and possible system errors in the errors node. The errors node can contain zero or more error nodes; each error node has a source element, an errorcode element, and a description element. In addition, the error node has a category attribute, which can be one of two possible values: system and business.

The audits node logs the system activities on different tiers or different applications. The audits node can have zero or more audit nodes; and each audit node has both a timestamp and description element.

For the text view of the XML data stream schema, please download the source code. The following code shows a simple XML example using this schema:

   buy Jason Cai JAVA 10000      0 buy 0.00      TradeBean 10001 Stock symbol Java does not exist     

Using XML data stream has the following benefits:

  • The client tier will be able to retrieve both multiple data sets and business validation exceptions from the EJB tier with just one remote call.
  • The XML data stream eliminates the coupling and dependency between the client and EJB tiers, and achieves parallel development. Additionally, using XML results in less custom development. A validating XML parser can use a supplied schema to automatically check an XML data stream's syntax and enforce business rules.

  • The audit-trail capability is built-in.
  • XML data streams are self documenting. XML tags' textual nature and the inclusion of a well-defined schema greatly reduce guesswork during application development.
  • Mit XML können Unternehmen offene und standardisierte Schnittstellen für vorhandene Systeme erstellen.

Die Umsetzung

Unsere in Abbildung 4 gezeigte Sitzungsfassade mit XML-Implementierung definiert drei Java-Schnittstellen und abstrakte Klassen als Kernklassen.

ISessionFacadeDie Schnittstelle definiert, wie im folgenden Codeausschnitt gezeigt, zwei process()Methoden mit unterschiedlichen Signaturen. Eine Methode verwendet eine Zeichenfolgendarstellung eines XML-Eingabedatenstroms als Eingabeparameter und gibt eine Zeichenfolgendarstellung eines XML-Ausgabedatenstroms zurück. Der andere verwendet ein XML-DOM-Dokument (Document Object Model) als Eingabeparameter und gibt ein XML-DOM-Dokument zurück. Sowohl die Remote-Schnittstelle einer Session Façade Session Bean als auch ihre Bean-Klasse müssen die ISessionFacadeSchnittstelle implementieren :