Leistungsfähige Web Services

Java bietet mit Axis 2 und xFire leistungsfähige Frameworks zur Konsumation und Erstellung von Web Services für Web und Intranet.

Artikel erschienen in Swiss IT Magazine 2007/02

     

Applikationen miteinander über System- oder gar Netzwerk-Grenzen hinweg zu verbinden, ist heutzutage eine alltägliche Aufgabe. Web Services auf Basis von SOAP (Simple Object Access Protocol) haben sich dabei als Mittel der Wahl durchgesetzt, setzen sie doch auf omnipräsente Protokolle und offene Standards auf. Mit Hilfe leistungsfähiger Frameworks wie Axis 2 oder xFire lässt sich ihre Entwicklung beschleunigen.


Verzahnte Standards

Um Web Services mit SOAP zu realisieren, werden neben SOAP zwei weitere W3C-Standards verwendet: WSDL (Web Service Description Language) und W3C Schema.
SOAP ist der «Briefumschlag», in den eine Nachricht (oder die Details eines Methodenaufrufes) von Rechner A zu B verpackt werden. WSDL beschreibt den konkreten Service, der verwendet werden soll, und tut dies üblicherweise mit Unterstützung von Schemata. Diese sind notwendig, weil die zwischen den Partnern ausgetauschten Daten wie beispielsweise Übergabe-Parameter so spezifiziert werden müssen, dass sie von verschiedenen Plattformen gleich interpretiert werden. Dies ermög­licht, mittels XML den sauberen Austausch von Objekten zwischen unterschiedlichen Plattformen wie Java, Python und .Net zu realisieren.
Wie schon angedeutet, werden alle Standards sowie die übergebenen Daten in XML ausgedrückt. Als Entwickler kommt man aber kaum auf die Idee, anhand einer WSDL-Beschreibung ein Programm zu schreiben, das direkt SOAP-Nachrichten in XML erzeugt und diese dann mit dem gewählten Netzwerk-Protokoll zum Partner sendet. Diese eher mühsame Tätigkeit überlässt man besser spezialisierten Bibliotheken.
In noch stärkerem Masse gilt dies natürlich für den Anbieter von Web Services, die ja eine Serverumgebung erfordern.


Viele Erwartungen

Das Web-Service-Framework sollte nebst der Unterstützung mehrerer Transportprotokolle in der Lage sein, als Server zu fungieren und Klassen als Webservice anzubieten sowie einen Client-Teil zur Verfügung stellen, um auf Services zugreifen zu können.
Hierbei unterstützen Frameworks meist durch Tools die Code-Generierung: Aus WSDL-Spezifikationen können Client-Zugriffsklassen generiert und aus den Schema-Spezifikationen Data Bindings erstellt werden, die die in XML übermittelten Daten direkt auf Java-Objekte abbilden beziehungsweise im Falle des Service die Daten, die in Objekten gespeichert sind, in XML verwandeln.



Da Data Binding keine triviale Aufgabe ist – müssen doch Objekt-Hierarchien auf XML abgebildet werden –, existieren etliche Java-Projekte, die sich ausschliesslich mit diesem Thema beschäftigen und deren Software sich in den Fähigkeiten unterscheidet. Deshalb bieten die meisten Web-Service-Frameworks für Java die Auswahl zwischen mehreren verschiedenen Data-Binding-Werkzeugen. In der Regel wird aber ein Standard-Werkzeug mitgeliefert, das mindestens für erste Experimente immer geeignet ist.
Aber auch der umgekehrte Weg, aus Java-Klassen Web Services zu erstellen, ist möglich. Seit Java 1.5 sind die sogenannten Java Annotations vorhanden. Dabei handelt es sich um einen Metadaten-Standard, der es erlaubt, Java-Klassen mit zusätzlichen Daten anzureichern. Diese Daten können von einem geeigneten Compiler ausgewertet und weiter verarbeitet werden.




Hier bietet es sich an, die Klasse mit den notwendigen Informationen zu «annotieren» und damit die Publikation der Klasse als Service zu vereinfachen. Möglich wird dies durch den JSR-181 Web Services Metadata for the Java Platform, ein Standard mit acht unterschiedlichen Annotationen, um Klassen als Web Service zur Verfügung zu stellen.
Eine Problematik bei einer derartigen Erstellung von Web Services zur Laufzeit ist, dass die Nachvollziehbarkeit der Änderungen nicht immer gegeben ist. Eine Änderung des Interface muss natürlich bei allen Clients nachvollzogen werden. Daher geht man bei Services, die oft verwendet werden sollen, besser von einer sauberen Interface-Definition (WSDL) und nicht vom Quellcode aus.
Ebenfalls wünschenswert ist eine möglichst breite Unterstützung ergänzender Web-Service-Protokolle. Dazu gehören beispielsweise WS-Addressing, das vielfältigere Möglichkeiten zur Lokalisierung und Adressierung von Web Services bietet, oder WS-Reliable Messaging, das zuverlässigen Nachrichtenaustausch sicherstellen soll. Es existieren darüber hinaus aber auch etliche Erweiterungen, die beispielsweise bei der Koordination verteilter Applikationen und beim Umgang mit Ressourcen helfen.





Beispiel Web-Service-Stack


Der lange Weg zu Axis2

Alleine im Apache-Umfeld findet man deutlich über 20 Subprojekte, die sich verschiedenen Problemstellungen im Web-Service-Umfeld annehmen. Von diesen implementieren deren drei SOAP Web Services: Apache SOAP, Apache Axis 1 und Axis 2.




Apache SOAP ist das älteste Produkt und wird schon seit einiger Zeit nicht mehr weiterentwickelt. Es wurde von Axis 1 ersetzt, das eine Re-Implementierung von Apache SOAP ist und mittlerweile ebenfalls durch einen Nachfolger abgelöst wurde: Axis 2. Axis 2 verkörpert etwa 6 Jahre Erfahrung und Designverbesserungen seit der Veröffentlichung von Apache SOAP und arbeitet heute mit einem modernen StAX-Parser, ist modular aufgebaut, verfügt über ein gereiftes Objektmodell zur Abbildung des SOAP-Protokolls und unterstützt bereits die neuen Standards SOAP 1.2 und WSDL 2. Im Rahmen von WSDL 2 werden auch die erweiterten Message Exchange Patterns (MEP) unterstützt, die das Request-Response-Modell um Methoden wie «Notification» erweitern.





Sehr wichtig ist auch, dass Axis 2 nun auch asynchrone Web Services und REST-Architekturen, die immer asynchron arbeiten, vollständig unterstützt. Gross ist ebenfalls die Anzahl der unterstützten Transportprotokolle und Binding-Frameworks. Durch den modularen Aufbau gestattet Axis aber prinzipiell auch die Einbettung neuer Protokolle, sofern die entsprechenden Schnittstellen geschrieben werden.




Ein Problem bei der Verwendung von Web Services tritt häufig dann auf, wenn komplexere binäre Daten zu übertragen sind wie Bilder oder Office-Dokumente. Natürlich könnten diese Daten in ASCII übertragen und als XML verschickt werden. Dies ist jedoch umständlich und bläht das Dokument unnötig auf; auch die Verarbeitungsgeschwindigkeit leidet unter dieser Vorgehensweise. Axis umgeht dieses Problem dank Unterstützung für SOAP with Attachments. Binäre Daten können damit ähnlich wie bei E-Mails als Attachment an die SOAP-Nachricht gehängt werden.
Schliesslich bietet Axis eine recht breite Auswahl an Tools an: Code-Generatoren um Java-Code aus WSDL-Definitionen zu erzeugen und umgekehrt, Plug-ins für Eclipse, IntelliJ sowie Maven 2 und einen sehr nützlichen SOAP-Monitor, der es für Debugging-Zwecke erlaubt, den Nachrichtenaustausch zwischen Client und Server zu beobachten. Dieses Tool kann aber auch unabhängig von Axis verwendet werden.



Web-Service-Verarbeitung in xFire


Auf Achse mit REST

Parallel zu SOAP unterstützt Axis 2 auch den REST-Architekturstil. Dabei werden der Nachrichtenaustausch immer asynchron und die Services zustandslos gehalten, der Server hält also keine Sessions. Es werden ausserdem keine SOAP Envelopes oder dergleichen verwendet, sondern beliebige XML-Dokumente. Ein WSDL-artiger Methodenaufruf findet ebenfalls nicht statt. Statt dessen wird alles als Resource und damit als URL abgebildet, auf die mit HTTP zugegriffen wird. http://meinfilmserver/filme/2006 würde so beispielsweise alle Filme des Jahres 2006 zurückgeben, während http://meinfilmserver/film/f445356/ Informationen zum Film mit der ID zurückliefert.
Um Daten zu speichern, wird die PUT-Methode von HTTP verwendet.
Beispiele für Anwendungen mit REST APIs findet man beispielsweise bei del.icio.us oder Flickr.


Die nächste Generation

Das zweite prominente Web-Service-Framework für Java neben Axis ist xFire vom Codehaus-Projekt. Im Gegensatz zu Axis ist es noch recht jung und ist in der Java-Community als das «Next Generation» SOAP-Framework bekannt. xFire ist eine Servlet-basierte Applikation und muss daher wie Axis in einem entsprechenden Servlet-Container wie Tomcat eingesetzt werden. Für die XML-Verarbeitung greift auch xFire bereits auf das neue Parser-Konzept StAX zurück und verdankt unter anderem diesem die gute Performance.




xFire bietet drei Möglichkeiten, um Java-Komponenten als Web Service bereitzustellen: Die xFire-API, XML-Konfiguration sowie Web Service Annotation. Auch wenn xFire eine sehr einfach zu verwendende und umfangreiche API bietet, geht der derzeitige Trend in der Softwareentwicklung in Richtung XML-Konfiguration. Die WSDL-Generierung kann entweder zur Laufzeit mit Annotationen erfolgen oder mittels XML-Konfiguration, Ant Tasks, Maven Goals oder über ein Kommandozeilen-Werkzeug, wobei auch hier XML-Konfiguration und Annotationen die bevorzugte Möglichkeit sind. Der umgekehrte Weg kann mit Ant Tasks, Maven Goals, Kommandozeilen-Werkzeugen oder einem Eclipse-Plug-in beschritten werden.





Das Team von xFire ist sich der Bedeutung von Containern bewusst und bietet daher auch entsprechende Integrationen an: Spring, Plexus, Loom, Pico oder Yan. Im Fall von Spring reicht eine simple Konfiguration aus, um in Spring verwaltete Komponenten als Web Service zur Verfügung zu stellen. Dies bringt den grossen Vorteil, dass die betroffene Komponente mit keiner zusätzlichen Web Service API versehen werden muss, was die Möglichkeit zur Wiederverwendbarkeit in anderem Kontext verbessert.
Unabhängig davon, ob der Service aus einem Container stammt oder einzelne Java-Klassen als Web Service exportiert werden, landen alle Services in einer zentralen Service Registry. Auf diese Registry greift xFire zurück, wenn ein Request für einen Service eintrifft.



Axis 2 versus xFire


Eigenes Binding-Framework

Wie bereits anfangs erwähnt wurde, stellt das Data Binding eines der wesentlichsten Konzepte eines Web-Service-Frameworks dar. Wie auch Axis verfügt xFire über ein eigenes Binding Framework, welches jedoch nicht zwingend verwendet werden muss. Es bleibt dem Entwickler überlassen, ob er das Standard-Binding Aegis oder andere Implementierungen wie Castor, JAXB, XMLBeans, JIBX oder MessageBinding verwendet.
Wie auch Axis unterstützt xFire das Übertragen von binären Daten. Dies muss jedoch explizit auf Client- und Server-Seite konfiguriert werden.


Leistungsfähig

Grundsätzlich sind beide Frameworks sehr leistungsfähig und erlauben das Erstellen von «erwachsenen» Web-Service-Anwendungen. Leider muss man aber festhalten, dass die einzelnen Elemente einer Web-Service-Architektur zwar relativ einfach sein mögen, die Kombination der notwendigen Technologien (verschiedenste XML- und Web-Service-Standards, Transportprotokolle, Binding-Frameworks) in Summe aber eine immer noch relativ komplexe Angelegenheit ist und doch einiges an Einarbeitungszeit erfordert. Dies gilt vor allem, wenn nicht triviale Services erstellt werden sollen.
Web-Service-Frameworks sind ein sehr komplexes Themengebiet und verlangen auch ein fundamentales Wissen der Basistechnologien. Dies gilt besonders dann, wenn Services geschrieben werden sollen, die auf verschiedenen Plattformen zum Einsatz kommen.
Die Dokumentation beider Frameworks ist teilweise lückenhaft und manchmal schwer nachvollziehbar. Es ist nicht immer einfach, die Konzepte hinter diesen Bibliotheken zu verstehen. Möchte man sich ernsthaft mit dem Thema auseinandersetzen, ist also entsprechende Sekundärliteratur empfohlen.


Die Autoren

Alexander Schatten ist Assistent am Institut für Softwaretechnik und interaktive Systeme der Technischen Universität Wien. Markus Demolsky ist Consultant und Software-Engineer bei Icodex Software.




Artikel kommentieren
Kommentare werden vor der Freischaltung durch die Redaktion geprüft.

Anti-Spam-Frage: Welche Farbe hatte Rotkäppchens Kappe?
GOLD SPONSOREN
SPONSOREN & PARTNER