In einem meiner früheren Artikel habe ich beschrieben, wie man mit Apache CXF, Spring Framework sowie Jetty als embedded HTTP Server einen einfachen Webservice implementiert und bereitstellen kann. Dabei wurden JSR-181 und JAXB Annotations verwendet um die Java Klassen mit entsprechenden Metadaten anzureichern. Dies wird auch als „Implementation-First“ oder „Java-First“ Ansatz bezeichnet. In einem weiteren Artikel wurde gezeigt welche Nachteile dieser Ansatz hat und wie man die Generierung der WSDL-Datei mit Annotations beeinflussen und somit den Webservice Contract optimieren kann.
Dieser Artikel beschreibt das Vorgehen nach dem “Contract-First” bzw. „WSDL-First“ Ansatz. Bei diesem Ansatz wird die Schnittstelle vor der Implementierung in Form einer WSDL-Datei definiert. Die entsprechenden Java Klassen werden dann mit einem Codegenerator aus der WSDL-Datei generiert.
Das hier beschriebene Beispiel basiert auf Apache CXF 2.0.3, JSR-181, JAXB 2.1, Spring Framework 2.5, sowie Jetty 6.1.5. Der komplette Source Code inklusive einem Maven Build Script steht zum Download bereit.
Schritt 1: Anforderungen aufnehmen, dokumentieren und Schnittstelle entwerfen
Der Lebenszyklus für jeden Webservice beginnt mit neuen Anforderungen aus dem Fachbereich. Diese Anforderungen müssen wie bei jedem Softwareentwicklungsprojekt aufgenommen und dokumentiert werden. Anhand dieser Anforderungen kann anschließend eine Schnittstelle für den Service entworfen werden. In unserem Beispiel verwenden wir die Schnittstelle aus dem vorherigen Artikel. Das folgende UML-Diagramm zeigt die Schnittstelle des Services sowie die Datenobjekte mit denen der Service arbeitet:
Wie man dem Klassendiagramm entnehmen kann, soll unser Beispiel-Service eine Methode anbieten, die eine Kundenummer als Inputparameter entgegennimmt und einen Kunden als Output zurück gibt. Die Serviceschnittstelle wurde für dieses Beispiel zur besseren Verständlichkeit natürlich stark vereinfacht.
Schritt 2: Datenstrukturen als XML-Schema definieren
Zunächst müssen die Datenstrukturen als XML-Schema definiert werden. Es ist sinnvoll jede Datenstruktur in einer separaten XSD-Datei abzuspeichern. Auf diese Weise können die Datenstrukturen auch in anderen Services wiederverwendet werden. In unserem Beispiel entstehen folgende vier Schema-Definitionen:
Customer.xsd
Person.xsd
Gender.xsd
Address.xsd
Schritt 3: Service Interface in einer WSDL-Datei definieren
Im nächsten Schritt muss das Service Interface in einer WSDL-Datei beschrieben werden. Die WSDL-Datei inkludiert die XML-Schema Dateien, die die Datenstrukturen beschreiben und definiert die vorhanden Operationen sowie die Input- und Output-Nachrichten:
Schritt 4: Java Source Code aus WSDL-Datei definieren
Aus der WSDL-Datei kann nun mit Hilfe eines Genarators Java Code generiert werden. Apache CXF bittet dazu ein entsprechendes WSDL2Java-Tool an, welches sowohl von der Kommandozeile als auch aus Ant und Maven Skripten aufgerufen werden kann. In unserem Beispiel verwenden wir ein Maven Build-Skript und der Codegenerator wird automatisch vor dem Kompilieren aufgerufen. Die Konfiguration für den Codegenerator kann der pom.xml Datei entnommen werden.
Schritt 5: Service Interface implementieren
Nachdem die entsprechenden Java-Klassen für die Datenstrukturen und den Service generiert wurden, muss das Interface implementiert werden. Die Implementierung der Geschäftslogik befindet sich in der Klasse CustomerServiceImpl.java, welche das generierte Interface ContactService implementiert:
ArrayWie man dem Source-Code entnehmen kann, gibt diese Implementierung immer den Kunden „Max Müller“ als Output zurück wenn die Kundennummer „12345“ als Inputparameter übergeben wurde und in allen anderen Fällen wird ein BusinessLogicException mit entsprechender Fehlermeldung geworfen.
Schritt 6: Service bereitstellen
In diesem Beispiel wird der Service mit Hilfe von Jetty über HTTP bereitgestellt. Die Konfiguration der Komponenten erfolgt über das Spring Framework. Die Spring Konfiguration ist in diesem Beispiel in der Datei server-applicationContext.xml enthalten.
Über die main-Methode in der Klasse ServiceServer wird der Spring Context initialisiert und somit der Jetty Webcontainer gestartet, welcher die Service Implementierung unter http://localhost:9090/customerService verfügbar macht.
Schritt 7: Client für den Service implementieren
Um den Service anzusprechen und testen zu können, empfiehlt es sich ein Client zu implementieren. Die Implementierung von Clients ist mit Apache CXF 2.0 relativ einfach deklarativ mit Hilfe des Spring Frameworks möglich. Die Spring Konfiguration für den Service Client ist in diesem Beispiel in der Datei client-applicationContext.xml enthalten.
Die Klasse ServiceClient enthält eine main-Methode in der Spring Context initialisiert wird und auf das entsprechende Client-Bean zugegriffen wird.
Alternativ eignet sich auch soapUI hervorragend zum Testen von Webservices.






Letzte Kommentare