WSDL Schnittstellen automatisch vergleichen

Kaveh Keshavarzi

Von: Kaveh Keshavarzi
Datum: 30.03.2011

Nichts bleibt wie es war

Viele Organisationen sind ständigen Änderungen und Anpassungen unterworfen. Entsprechend werden die Schnittstellen von Systemen und Komponenten angepasst. Web Services und die Service-orientierte Architektur haben dazu beigetragen, dass Komponenten von immer mehr anderen Komponenten abhängig sind, die oft auch über die Grenzen der Organisationen miteinander kommunizieren.
Bereits eine kleine Änderung an der Schnittstelle einer Komponente kann dazu führen, dass abhängige Komponenten ausfallen. Dieser Artikel beschreibt, wie Änderungen an der Schnittstelle eines Services automatisch erkannt, dokumentiert und bewertet werden können.

Schnittstellen ändern sich

Ein Web Service kann im Laufe der Zeit verschiedene Änderungen erfahren. Aus Sicht der Benutzer betrachtet sind Änderungen an der Schnittstelle von großer Bedeutung, denn diese Änderungen können schwere Folgen haben. Diese sind beispielsweise Beeinträchtigung der Kommunikation zwischen Client und Server, kompletter Ausfall des Dienstes oder fehlerhafte Ergebnisse, die zum Teil spät erkannt werden und dadurch große Schäden verursachen können. Die Organisation W3C veröffentlichte 2007 einen Primer für WSDL 2.0, in dem der Abschnitt „Web Service Versioning“ das unten stehende Zitat beinhaltet. Dies zeigt neben der Wichtigkeit und Notwendigkeit der WSDL-Versionierung, dass der Stand der Forschung und Entwicklung in diesem Gebiet noch nicht weit fortgeschritten ist.
„A WSDL 2.0 document describes a set of messages that a Web service may send and receive. In essence, it describes a language for interacting with that service. However it is possible for a Web service to exchange other messages beyond those described in a particular WSDL 2.0 document. Often this circumstance occurs following an evolution of the client and/or service, and thus an evolution of the interaction language. How best to manage the evolution (versioning) of Web based systems is, at the time of writing, the subject of a wide-ranging debate.“ [1] Folgendes Beispiel verdeutlicht die Motivation zu diesem Thema und somit zu der vorliegenden Arbeit. Die Idee und der Aufbau des Beispiels basiert auf einem ähnlichen Beispiel aus der Arbeit von Brown und Ellis [2].
Angenommen eine Bank bietet einen Web Service zur Überweisung von Geldbeträgen in der Währung Euro. Laut WSDL-Dokument erwartet der Service eine Nachricht mit einem Feld vom Typ Float als Gelbbetrag, so dass die ersten zwei Nachkommastellen den Cent-Betrag darstellen. Der Service wird bereits von vielen Nutzern eingesetzt. Nach einer Weile wird in der IT-Abteilung klar, dass Float nicht der beste Datentyp zur Darstellung von Geldbeträgen ist. Denn es werden nie mehr als zwei Nachkommastellen gebraucht, um einen Geldbetrag darzustellen. Demnach wird der Service modifiziert und arbeitet nun mit Integer-Werten, so dass die Zahl den Betrag in Cent präsentiert. Der neue Service mit dem neuen WSDL-Dokument ersetzt irgendwann den alten Service. Nun wissen neue Clients, die dieses WSDL-Dokument zum ersten Mal lesen und parsen, wie sie richtig mit dem Service kommunizieren sollen. Die alten Nutzer hingegen schicken ihre Nachrichten noch im alten Format an den Service. Nun will ein Nutzer des alten Dienstes den Betrag von 100 Euro überweisen und gibt die Zahl 100 als Inhalt seiner Nachricht ein, während der neue Service lediglich 1 Euro als Betrag entgegen nimmt. Dieses Beispiel schildert einen der schlimmsten Fälle, da der Nutzer keine Fehlermeldung bekommt und davon ausgeht, dass der Service wunschgemäß funktioniert hat.
Es ist also für einen sicheren und zuverlässigen Einsatz von Web Services, aus der Sicht der Nutzer von großer Bedeutung, Änderungen an der Schnittstellenbeschreibung der eingesetzten Dienste, schnell zu erkennen und zu überprüfen. In diesem Dokument werden Kernpunkte der WSDL-Versionierung und WSDL-spezifische Änderungen angesprochen und verdeutlicht. Des Weiteren wird zusätzlich ein Algorithmus vorgestellt, der zwei WSDL-Dokumente rekursiv und mit Berücksichtigung deren Baumstruktur vergleicht. Auf diesen Algorithmus aufbauend, wird ein Software-System der Firma „predic8“ zur Versionierung von WSDL-Dokumenten beschrieben. Analog zur CVS-Versionsverwaltung, die das Unix-Tool „diff“ zum Erkennen von Änderungen an Dokumenten und Dateien einsetzt, setzt dieses Software-System einen speziell für WSDL entwickelten DiffGenerator für das Erkennen und Bestimmen von Unterschieden in WSDLDokumenten ein.

Änderungen an WSDL-Dokumenten

In diesem Abschnitt werden mögliche Änderungen eines WSDL-Dokuments und deren Auswirkungen mit Hilfe von Beispielen betrachtet und klassifiziert.
Bei WSDL-Versionierung kann im Gegensatz zu CVS nicht nur zeilenweise entschieden werden, ob Veränderungen stattgefunden haben. WSDL-Dokumente basieren auf XML. Das heißt, eine sinnvolle Versionierung kann nur gewährleistet werden, wenn die Dokumente nicht nur zeilenweise, sondern auch semantisch miteinander verglichen werden.
Im folgenden Beispiel wird erläutert, warum dies nötig ist und warum ein Verfahren, das Dokumente nur zeilenweise miteinander vergleicht, nicht alle Anforderungen erfüllt und zum Teil nicht zu den richtigen Ergebnissen führt.
Folgender Codeausschnitt zeigt die Beschreibung des Service-Elements in WSDL1.

<wsdl:service name="BLZService">
  <!-- SOAP 1.1 Port -->
  <wsdl:port name="BLZServiceSOAP11port_http" binding="tns:BLZServiceSOAP11Binding">
    <soap:address location="http://www.thomasbayer.com:80/axis2/services/BLZService"/>
  </wsdl:port>
  <!-- SOAP 1.2 Port -->
  <wsdl:port name="BLZServiceSOAP12port_http" binding="tns:BLZServiceSOAP12Binding">
    <soap12:address location="http://www.thomasbayer.com:80/axis2/services/BLZService"/>
  </wsdl:port>
  <!-- HTTP Port -->
  <wsdl:port name="BLZServiceHttpport" binding="tns:BLZServiceHttpBinding">
    <http:address location="http://www.thomasbayer.com:80/axis2/services/BLZService"/>
  </wsdl:port>
</wsdl:service>
Listing 1: WSDL-Service-Beschreibung

Folgender Codeausschnitt zeigt eine in der Reihenfolge veränderte Beschreibung des Service-Elements in WSDL2. Die Information ist aus Sicht des Clients aber unverändert.

<wsdl:service name="BLZService">
  <!-- HTTP Port -->
  <wsdl:port name="BLZServiceHttpport" binding="tns:BLZServiceHttpBinding">
    <http:address location="http://www.thomasbayer.com:80/axis2/services/BLZService"/>
  </wsdl:port>
  <!-- SOAP 1.1 Port -->
  <wsdl:port name="BLZServiceSOAP11port_http" binding="tns:BLZServiceSOAP11Binding">
    <soap:address location="http://www.thomasbayer.com:80/axis2/services/BLZService"/>
  </wsdl:port>
  <!-- SOAP 1.2 Port -->
  <wsdl:port name="BLZServiceSOAP12port_http" binding="tns:BLZServiceSOAP12Binding">
    <soap12:address location="http://www.thomasbayer.com:80/axis2/services/BLZService"/>
  </wsdl:port>
</wsdl:service>
Listing 2: WSDL-Service-Beschreibung mit veränderter Reihenfolge der Ports

Listing 1 enthält Informationen über die Ports zum Zugriff auf den Service. Listing 2 enthält die gleiche Information für den selben Service. Der einzige Unterschied ist, dass in der zweiten Beschreibung die Ports in einer anderen Reihenfolge beschrieben worden sind. Dieser Unterschied ist für die Benutzung des Dienstes grundsätzlich bedeutungslos.
Der Einsatz eines Diff Tools zum Erkennen der Änderungen in WSDL würde dazu führen, dass die obigen Dokumente als unterschiedlich eingestuft werden. Es würde fälschlicherweise eine neue Version des Dienstes ins Leben gerufen werden, die keine wesentlichen Unterschiede zu der letzten Version aufweisen würde. Genauer betrachtet würde ein Diff Tool jede Änderung des Dokuments erkennen. Jedoch folgt nicht jeder Änderung im Dokument eine Änderung der Schnittstelle. Dies zeigt den Bedarf eines speziellen Tools zum Erkennen von wesentlichen Änderungen einer Service- Beschreibung.
In den weiteren Abschnitten wird beschrieben, welche Eigenschaften diese Änderungen besitzen und wie sie zu verstehen und zu unterscheiden sind. Änderungen, die keine Auswirkung auf die Schnittstelle des Dienstes haben, werden von nun an nicht mehr beachtet.

Art der Änderungen

Um die Änderungen eines WSDL-Dokuments genauer betrachten zu können, werden sie in folgende Gruppen eingeteilt:

  • Erweiterung
  • Es wird eine neue Komponente zu der Beschreibung des Dienstes hinzugefügt, zum Beispiel eine neue Operation.

  • Reduktion
  • Bestehende Komponenten werden aus der neuen Beschreibung gestrichen, zum Beispiel eine bestimmte Binding-Methode wird nicht mehr unterstützt und deswegen gelöscht.

  • Änderung bestehender Elemente
  • Hierunter versteht man Änderungen an den Komponenten, die sowohl in der alten als auch in der neuen Beschreibung vorhanden sind. Diese Änderungen sind im Grunde kleine Modifikationen, zum Beispiel wenn sich die Schema-Definition eines Nachrichtenelements ändert.

  • Strukturänderung
  • In diese Kategorie fallen die Änderungen, die einen Großteil der bisherigen Beschreibung verändern, so dass die neue Beschreibung als ein neues Dokument gesehen werden kann.

In der Praxis wird schnell klar, dass nicht jede Änderung maschinell in die oben genannten Kategorien eingestuft werden kann, wie es in dem folgenden Beispiel zu sehen ist. Es sind zwei WSDL-Dokumente eines Services vorhanden, die miteinander verglichen werden sollen (Siehe Listing 3 und Listing 4). Die Operation heißt in dem neuen Dokument anders. Die Entscheidung, ob es sich hier um eine Umbenennung der Operation (Änderung bestehender Elemente) handelt oder ob die alte Operation entfernt wurde (Reduktion) und eine neue Operation hinzugefügt worden ist (Erweiterung), ist nicht trivial. Hierzu wären mehr Statistiken oder Information aus der Umwelt des Systems notwendig.

...
  <wsdl:portType name="BLZServicePortType">
    <wsdl:operation name="getBank">
      <wsdl:input message="tns:getBank"/>
      <wsdl:output message="tns:getBankResponse" wsaw:Action=
      "http://thomas-bayer.com/blz/BLZService/getBankResponse"/>
    </wsdl:operation>
  </wsdl:portType>
...
        
Listing 3: Beschreibung der Operation im alten WSDL-Dokument


...
  <wsdl:portType name="BLZServicePortType">
    <wsdl:operation name="getFinancialInstitute">
      <wsdl:input message="tns:getBank"/>
      <wsdl:output message="tns:getBankResponse" wsaw:Action=
      "http://thomas-bayer.com/blz/BLZService/getBankResponse"/>
    </wsdl:operation>
  </wsdl:portType>
...
        
Listing 4: Beschreibung der Operation im neuen WSDL-Dokument


Änderungen in XML

In einem WSDL-Dokument werden Nachrichtentypen mithilfe von XML-Schema definiert. Diese Typ-Definitionen befinden sich zum Teil in den Schemas, die im WSDL-Dokument selbst definiert sind, und zum Teil in externen Schemas die vom WSDL-Dokument importiert werden. Dies bedeutet, dass die Änderungen an den verwendeten Schemas auch eine Veränderung der Schnittstelle mit sich bringen können und daher bei einem Vergleich berücksichtigt werden müssen. Ähnlich wie bei einem WSDL-Dokument, gibt es auch bei einem Schema-Dokument Änderungen, die aus Sicht der Nutzer keinen wesentlichen Unterschied zwischen dem alten und dem modifizierten Dokument verursachen. Zum Beispiel ist es bei der Verwendung von „choice“ im Schema die Reihenfolge der Elemente, die zur Auswahl stehen, gleichwertig. Somit dürften zwei Dokumente, die nur einen Unterschied in der Reihenfolge der in „choice“ vorgekommenen Elemente vorweisen, nicht als unterschiedlich bewertet werden.
Zu beachten ist, dass Auswirkungen der Schema-Änderungen auf die Schnittstelle stark von der Service-Beschreibung und Serviceimplementierung abhängig sind. Als Beispiel kann ein Element betrachtet werden, dessen Nutzung von optional auf notwendig geändert wird. Ein Client, der dieses Element bis dahin nicht verwendet hat, erhält eine Fehlermeldung, während ein anderer Client, der das optionale Element verwendet, den neuen Service weiter nutzen kann.
Das obige Beispiel macht anschaulich, dass die Entscheidung, ob ein neues Schema die Schnittstelle brechen würde, auch nicht immer trivial ist.
Der nächste Abschnitt beschäftigt sich näher mit den Auswirkungen verschiedener Änderungen auf die Schnittstelle eines WSDL-Dokuments.

Kompatibilität

Auswirkungen, die eine Änderung des Dokuments auf die Schnittstelle des jeweiligen Dienstes haben kann, lassen sich in zwei Hauptgruppen teilen. Die erste Gruppe sind Änderungen, die die bisherige Schnittstelle brechen und die zweite Gruppe sind Änderungen, die es nicht tun.

Schwerwiegende Änderungen

In diese Gruppe fallen Änderungen, die eine relativ schwerwiegende Veränderung zu der alten Version mit sich bringen. Schwerwiegend bedeutet in diesem Kontext, dass dadurch eine Inkompatibilität mit der neuen Schnittstelle für die Benutzer der bisherigen Schnittstelle verursacht wird. Beispiele dieser Art sind laut Brown und Ellis [2]:

  • Entfernen einer Operation
  • Umbenennen einer Operation
  • Ändern der Struktur eines Datentyps im Schema

Geringfügige Änderungen

In dieser Kategorie werden Änderungen zusammengefasst, die eine bestehende Schnittstelle nicht brechen. Das heißt, dass die bisherigen Clients den Service weiter verwenden können, ohne eine Änderung zu bemerken, während in der neuen Beschreibung neue Features und Verbesserungen zur Verfügung stehen. Diese Art von Änderungen werden auch rückwärtskompatibel (backward compatible) genannt.
Beispiele für diese Art sind laut Brown und Ellis [2]:

  • Hinzufügen einer zusätzlichen Operation zum bestehenden WSDL-Dokument
  • Definieren eines neuen Schema-Datentyps, der in den bisherigen Datentypen nicht verwendet wird.

Im Hinblick auf die oben genannten Gruppen sollte ein Werkzeug zum Vergleichen von WSDLDokumenten in der Lage sein, diese Fälle (soweit es möglich ist) zu unterscheiden und den Benutzer entsprechend zu informieren. Allerdings ist es wie oben beschrieben nicht immer möglich, diese zwei Fälle eindeutig voneinander zu trennen.
Eindeutig ist dagegen, dass das Diff-Tool nach Änderungen in einer XML-Struktur suchen muss. Wie in XML-Dokumenten nach Änderungen gesucht wird ist kein neues Themen-Gebiet. Es sind verschiedene Algorithmen und Ansätze dafür entwickelt worden, wie X-Diff oder BULD. Diese sind allerdings entwickelt worden, um in zwei verschiedenen Dokumenten allgemeine Unterschiede und Ähnlichkeiten fest zu stellen. Die gängigen XML-Vergleichs-Algorithmen verarbeiten ein XMLDokument als eine Beschreibung für Daten und setzen den Fokus beim Vergleichen auf diese Daten. WSDL- und Schema-Dokumente sind aber eher eine Beschreibung von Datenbeschreibungen und Datenstrukturen. Aus diesem Grund sollte in ein WSDL-Diff-Tool ein Algorithmus eingesetzt werden, der diese Beschreibung und Struktur einer Schnittstelle berücksichtigt und darauf basierend nach Änderungen sucht. Im folgenden Abschnitt wird so ein Algorithmus vorgestellt und beschrieben.

Vergleichsalgorithmus

Im Folgenden wird ein Algorithmus vorgestellt, der von Thomas Bayer und Kaveh Keshavarzi bei predic8 GmbH entwickelt wurde. Dieser Algorithmus ist für die Suche nach Änderungen zwischen zwei WSDL-Dokumenten optimiert worden und berücksichtigt die in der Spezifikation vorgegebene Struktur und Vererbungshierarchie des WSDL-Dokuments.

Baumstruktur

Ein WSDL-Dokument beschreibt eine Baumstruktur. Da das Root-Element standardmäßig bei jedem WSDL-Dokument gleich ist, sollten die Wurzeln der beiden Dokumente gleichgesetzt werden und demnach die Struktur des ersten Dokuments Knoten für Knoten mit der des zweiten vergleichen werden. Dabei werden Knoten (Elemente) auf dem gleichen Pfad auf beiden Seiten auf Ähnlichkeiten und Unterschiede überprüft.

Ablauf

Das Verfahren geht folgendermaßen vor:

  1. Sei a das Wurzel-Element des alten Dokuments und b das Wurzel-Element des neuen Dokuments
  2. Vergleich a mit b. Haben beide denselben Namen?
    1. Wenn nein: vermerken: a ist entfernt worden, b ist hinzugefügt worden
    2. Wenn ja: Vergleiche a und b auf weitere Element-spezifische Eigenschaften, wenn Kind-Elemente vorhanden, gehe zu Schritt 4
      • Wenn sich eine Eigenschaft geändert hat, die Änderung vermerken
      • Vermerkte Änderungen an das Vater-Element weitergeben
  3. Alle Änderungen sind vermerkt, Ende
  4. Vergleiche die Kind-Elemente von a und b: Sein A die Menge der Kind-Elemente von a und B die Menge der Kind-Elemente von b
    1. Vermerken: Alle Elemente der Menge A-B sind im neuen Dokument entfernt worden.
    2. Vermerken: Alle Elemente der Menge B-A sind zu dem neuen Dokument hinzugefügt worden
    3. Vermerken: Alle Elemente in A∩B sind in beiden Dokumenten vorhanden
      • Für alle Elemente aus A∩B wähle a aus A und entsprechend b aus B
      • Führe Schritt 2 mit neuen a und b aus

Zu den Vorteilen dieses Algorithmus zählen, neben seiner Einfachheit die rekursive Vorgehensweise und Tiefensuche der Baum-Struktur nach Änderungen. Es werden mathematische Mengenfunktionen zur Differenzierung der Elemente benutzt. Zusätzlich besitzt der Algorithmus eine einheitliche Vorgehensweise bei Änderungen, deren Art nicht eindeutig klassifiziert werden kann. Somit wird es in den Fällen, wie in dem Beispiel von Listing 3 und Listing 4, davon ausgegangen, dass ein Element entfernt und ein Element hinzugefügt worden ist. Im folgenden wird ein Software-System vorgestellt, das anhand des obigen Algorithmus WSDL- und Schema-Dokumente miteinander vergleicht.

WSDL-Diff-Tool

Wie im Abschnitt "Änderungen an WSDL-Dokumenten" beschrieben, ist das Suchen nach Änderungen in XML-Dokumenten kein neues Themengebiet. Es existieren bereits verschiedene Tools, wie „Microsoft XML Diff and Patch Tools 1.0“, „Altova DiffDog“ oder „XyDiff“. Allerdings herrscht bei den Implementierungen die gleiche Situation, wie bei den Algorithmen. Viele Tools setzen die zuvor angesprochenen Algorithmen ein und sind eher für allgemeine Suche nach Änderungen in XML-Dokumente geeignet. Zum Beispiel sind in „Microsoft XML Diff“ implementierte Algorithmen ein Greedy-Algorithmus und der Algorithmus von Zhang-Sasha. SOA-Modell dagegen implementiert zur Erkennung von Schnittstelenänderungen den obigen Algorithmus, der speziell für WSDL-Dokumente mit Berücksichtigung derer Eigenschaften entwickelt worden ist. Das Einsatzgebiet des hier vorgestellten Systems ist der Vergleich der Dokumente nach deren Aufstellung (Deployment) und von außerhalb ihrer Implementierungsumgebung. Dies ist besonders aus Sicht der Benutzer interessant und gibt einen Überblick über jede beliebige Service- Beschreibung, unabhängig davon ob der Entwickler die Schnittstelle mit Versionsberücksichtigung geändert hat oder nicht. Dies verdeutlicht den Unterschied zu anderen Ansätzen, die sich mit WSDL-Versionierung beschäftigen. Zum Beispiel wird in dem Artikel „WSDL Versioning Best Practise“ [6] beschrieben wie der Entwickler die Versionierung in seine WSDL-Struktur einbinden und Änderungen nach deren Auswirkung voneinander unterscheiden kann. „WSDL and UDDI extensions for version support in web services“ [7] schlägt wiederrum Ansätze zu Erweiterungen für WSDL und UDDI vor, die eine Versionierung unterstützen. Eine Idee ist, das WSDL-Dokument mittels einer Erweiterung so zu definieren, dass es verschiedenen Service-Beschreibungen für je eine Version beinhaltet. Diese Ansätze sind vielmehr für die Entwickler eines Web Services nützlich und geben Richtlinien an, wie eine sinnvolle Versionierung aus Sicht der Anbieter durchgeführt werden kann, während er Änderungen an dem Service vornimmt.

SOA-Model

SOA-Modell ist ein leistungsstarker SOA-Parser und ist die Kern-Software für weitere SOAorientierte Produkte, wie Membrane SOA Registry undMembrane Client. Die Software unterstützt unter anderem Features, die beim Vergleichen von Dokumenten zum Einsatz kommen:

  • Importieren und Parsen von WSDL- oder Schema-Dokumente vom Speicher oder von URLs
  • Erzeugen eines Objekt-Modells des geparsten Dokuments in JAVA
  • Vergleichen von WSDL-Dokumenten auf Änderungen
  • Vergleichen von Schema-Dokumenten auf Änderungen

SOA-Modell ist in der Programmiersprache Groovy entwickelt worden.

Parser und Objekt-Modell

Zu den Komponenten jedes XML-Diff-Tools gehört ein Parser. Der Parser liest das Dokument und verwandelt es von reinem Text in ein zum Vergleich geeignetes Format, wie ein JAVA-Objekt- Modell. SOA-Modell verfügt über einen WSDL- und einen Schema-Parser. Diese Tools nehmen ein entsprechendes Dokument als Datei entgegen und parsen es zu einem Objekt-Modell. Der WSDLParser ruft für externe Schema-Dokumente, die im WSDL-Dokument referenziert worden sind, automatisch den Schema-Parser auf und übergibt ihm den Dateipfad.
Somit wird für jedes geparste Dokument ein Objekt-Modell im Hauptspeicher erzeugt. Die erzeugten Objekte sind abgeleitete JAVA-Objekte und bilden eine Baum-Struktur. Dieser Baum ist analog zu dem XML-Baum des geparsten Dokuments. Die Implementierung hält die von W3C vorgegebene Struktur strikt ein und bietet Zugriff auf den Inhalt, die Referenzen oder die Vererbungsstruktur eines Elements.

DiffGeneratoren

Die DiffGeneratoren bilden das Diff-Tool des Systems. Als WSDL- oder Schema-DiffGenerator nimmt das Tool die Objekt-Modelle der zu vergleichenden Dokumente entgegen und überprüft sie mittels des obigen Algorithmus. Die Vorgehensweise ist folgendermaßen:
Nachdem zwei Instanzen von einem Dokumenttyp (WSDL oder Schema) erzeugt wurden, wird die entsprechende DiffGenerator-Klasse mit diesen Instanzen als a und b initialisiert. Das Ergebnis des Vergleichs wird nach der Auswertung der compare-Methode als eine Liste von Unterschieden (diffs) zurückgegeben. Die compare-Methode überprüft a und b auf deren Namespace. Wenn sich der TargetNamespace geändert hat, macht ein weiterer Vergleich keinen Sinn mehr. Es wird eine neue Diff-Instanz erzeugt und in der Diff-Liste aufgenommen. Die Methode endet und gibt die Liste der Unterschiede zurück. Wenn der TargetNamespace bei beiden Dokumenten gleich ist, wird das Service-Element der beiden verglichen. Bei einer Veränderung im Service-Element endet der Vergleich und die Liste der Änderungen wird zurückgegeben. Wenn es sich aber bei den zu vergleichenden Dokumenten (a und b) um denselben Service handelt, werden weitere Elemente in den Vergleich einbezogen. Dies geschieht als Aufruf drei weiterer Methoden, die die Unterelemente gegenübersetzen.

def compare() {
  def diffs=[]
  if ( a.targetNamespace != b.targetNamespace )
    diffs << new Difference(description:"targetNamespace changed from
      ${a.targetNamespace} to ${b.targetNamespace}", breaks:true)
  if ( a.services[0] && b.services[0] && a.services[0].name != b.services[0].name )
    diffs << new Difference(description:"servicename changed from
      ${a.services[0].name} to ${b.services[0].name}", breaks:true)
  else {
    if ( a.services[0] && b.services[0] ) {
      diffs.addAll(comparePorts())
    }
    diffs.addAll(comparePortTypes())
    diffs.addAll(compareSchemas())
  }
  diffs
}
      
Listing 5: compare Methode in WSDL-DiffGenerator

Im nächsten Schritt werden Listen von Objekten miteinander verglichen. Dazu wird von dem entsprechenden Objekt-Typ die doCompare Methode (6) aufgerufen, die zwei Objekt-Listen entgegen nimmt und vergleicht. Zusätzlich werden Funktionen als Parameter übergeben, die zur Laufzeit ausgeführt werden und das Ergebnis des Vergleichs generisch darstellen.

def doCompare(aObjs, bObjs, rm, add, getID){
  def aNames = aObjs.collect{getID(it)}
  def bNames = bObjs.collect{getID(it)}
  def diffs = []
  if(aNames[0]){
    def removed = aNames - bNames
    removed.each{ name ->
      diffs <<  rm(aObjs.find{getID(it) == name})
    }
  }
  if(bNames[0]){
    def added = bNames - aNames
    added.each{ name ->
      diffs <<  add(bObjs.find{getID(it) == name})
    }
  }
  diffs
}
            
Listing 6: Die doCompare Methode

Im Folgenden wird die Funktionsweise des WSDL-DiffGenerators anhand des Beispiels von Listing 1 und2beschrieben. Betrachtet werden die WSDL-Ausschnitte von Listing 1 und Listing2. Jeder Service hat eine Liste von Ports. Die definierten Port-Elemente sind in beiden Fällen gleich. Die Reihenfolge ist allerdings unterschiedlich (siehe Abbildung 1 und Abbildung2).

Alter Service

Abbildung 1: Alter Service

Neuer Service

Abbildung 2: Neuer Service

In der comparePorts-Methode werden die Ports gegenübergestellt (siehe Listing7). Es wird eine Schnittmenge über die Ports der beiden Dokumente gebildet. In diesem Schritt wird die Reihenfolge nicht beachtet. Nun wird für jedes Objekt der ersten Menge, das entsprechende Objekt aus der zweiten Menge ausgewählt. Somit werden die Objekte einzeln miteinander verglichen, unabhängig davon wo sie sich in der Liste befinden.

private def comparePorts(){
  def aPorts = a.services[0].ports
  def bPorts = b.services[0].ports
  def diffs = []
  diffs.addAll(compare(aPorts, bPorts,
  { new Difference(description:"Port ${it.name} removed.", breaks:true) },
  { new Difference(description:"Port ${it.name} added.", safe:true) }))
  def ports = aPorts.name.intersect(bPorts.name)
  ports.each{ port ->
    def aLocation = aPorts.find{ it.name == port}.location
    def bLocation = bPorts.find{ it.name == port}.location
    if(aLocation != bLocation)
    diffs << new Difference(description:"The location of the port: $port
    changed form $aLocation to $bLocation.")
  }
  diffs
}
      
Listing 7: comparePorts-Methode im WSDL-DiffGenerator

Alle anderen Ports, die nicht in diese Schnittmenge beinhaltet sind, sind entweder in dem ersten Dokument nicht vorhanden, oder in dem zweiten. Diese werden dann an die compare-Methode übergeben und werden dort als „added“ oder „removed“ eingestuft. Wenn der Vergleich von zwei Objekt-Listen abgeschlossen ist, werden die Diffs weiter nach oben übergeben und der Vergleich geht in dem nächsten Pfad der Baum-Struktur weiter ausgeführt. Am Ende sind die Dokumente verglichen und die Unterschiede in der Diff-Liste hierarchisch gespeichert. Abbildung 3 schildert das Ergebnis eines Vergleiches und die hierarchische Weitergabe der Differenz bis zum obersten Knoten.

Das Ergebnis eines Schema-Vergleiches

Abbildung 3: Das Ergebnis eines Schema-Vergleiches

Zusammenfassung

Web Services spielen eine immer größer werdende Rolle in der Welt der verteilten Systeme und lose gekoppelten Software. Da die Komponenten dieser Welt sich ständig verändern und weiterentwickeln, ändern sich auch Web Services samt deren Schnittstelle. Ein zuverlässiger Einsatz von Web Services setzt voraus, dass die Änderungen an der Schnittstelle eines Services so schnell wie möglich für die Nutzer des Dienstes sichtbar werden. Im Rahmen dieser Arbeit wurden Ideen und Systeme zur Erfüllung dieser Anforderung vorgestellt.
Nach einer kurzen Recherche im Internet wird klar, dass trotz der offensichtlichen Notwendigkeit von Überwachungssystemen, in diesem Gebiet nicht viele Ansätze zu finden sind. Es wird zwar bei den großen Organisationen wie W3C darüber debattiert, wie man das Thema „WSDL Versioning“ in den nächsten Standard-Versionen integrieren kann, einsetzbare Softwaresysteme sind aber noch nicht weit verbreitet. Einer der Gründe ist das fehlende Wissen über Vorteile und Einsatzmöglichkeiten der Versionierung bei der breiten Masse der Anwender in der Praxis. Es ist aber wahrscheinlich eine Frage der Zeit, bis immer mehr Tools mehr Nutzer davon überzeugen und das in dieser Arbeit vorgestellte Thema ein fester Bestandteil von vielen Systemen wird, die auf Web Services basieren.

Literaturliste

[1] WEB SERVICES DESCRIPTION LANGUAGE (WSDL) VERSION 2.0 PART 0: PRIMER
W3C Recommendation 26 June 2007

[2] BEST PRACTICES FOR WEB SERVICES VERSIONING
Autor: Kyle Brown, Michael Ellis

Share

WSDL Online vergleichen
Vergleichen Sie verschiedene Versionen eines WSDL Dokumentes online. Der WSDL Analyzer basiert auf der im Artikel beschriebenen Technologie. Der Vergleich berücksichtigt nicht nur Änderungen in der WSDL sondern auch Unterschiede in referenzierten XML Schema Dokumenten.
WSDL Comperator
Mit dem Membrane SOA Model können Sie selbst unterschiedlicheVersionen eines WSDL Dokuments vergleichen.
REST API Versionierung

Informationen zur Versionierung von REST APIs und zur Kompatibilität von Versionen findest du im Artikel zur REST Versionierung.