Web Services mit Spring-WS – Teil 3

Spring-WS und Spring Security

Thorsten Kamann
WS-Client mit JAXB2

Nun ist ja bekanntlich nicht alles so einfach, wie es oft in Beispielen dargestellt wird. Die meisten Web Services haben eine größere Komplexität und es ist besser, nicht allzu sehr mit XML in Berührung zu kommen. Zum einen ist die Verarbeitung mit XML oft nicht sehr fehlertolerant, zum anderen ist es aufwändig zu programmieren und zu testen. Zum Glück gibt es dafür auch Alternativen. Im zweiten Teil der Serie haben wir denselben Web Service auf Basis von JAXB implementiert. JAXB hat die Möglichkeit aus einem XML Schema ein Java-API zu generieren. Gegen dieses API lässt sich leichter programmieren als gegen XML. Dieses API kann nicht nur auf der Serverseite zum Einsatz kommen, sondern auch auf der Clientseite. Das XML Schema, das wir im zweiten Teil verwendet haben, besteht aus zwei Teilen. Es gibt einen ProductRequest (Abb. 2), der alle benötigten Daten für die Anfrage an den Web Service definiert. Für die Antwort ist die ProductResponse (Abb. 3) zuständig.

Abb. 1: ProductRequest

Abb. 2: ProductResponse

Aus diesen Schemadefinitionen generiert JAXB ein API. Als zusätzliches Feature werden Fluent-Interface-Methoden generiert, mit denen die Objekte leicht konfiguriert werden können.

Abb. 3: Das generierte Java-APIAbb. 3: Das generierte Java-API (Vergrößern)

Die Vorgehensweise für die Erstellung eines Clients ist übersichtlich:

  1. Request konfigurieren
  2. Request absenden und Response empfangen
  3. Response verarbeiten

Mit den Fluent-Interface-Methoden ist der erste Schritt sehr schnell erledigt (Listing 4).

Listing 4
public class ProductServiceClientJAXB {
 public List getProducts(){
  ProductRequest request = new ProductRequest();
  request.withCategory(new CategoryType().withId(2).withName("Toys"))
   .withSupplier(
    new SupplierType().withId(3)
      .withName("Toys and more LTD."))
   .withDateRange(
    new DateRangeType()
     .withStartDate(.)
     .withEndDate(.));
 }  
}

Die with*-Methoden sind die generierten Fluent-Interface-Methoden, mit denen sich eine Menge Code einsparen lässt. Diese Methode ist natürlich noch nicht vollständig. Es fehlen noch der eigentlich Aufruf des Web Services und die Rückgabe der Antwort. In unserem Beispiel ist das eine Liste mit Produkten. Die Web-Service-Implementierung liefert immer eine Liste von zwei Produkten zurück. Für die Implementierung des einfachen Clients haben wir eine der zahlreichen sendSourceAndReceive*-Methoden des WebServiceTemplates verwendet. Für diesen Client brauchen wir etwas mehr. Der Request muss in XML umgewandelt werden, bevor er an den Web Service übermittelt wird. Trotz der Verwendung von JAXB funktioniert der Web Service nur mit XML-Request und –Response. Wir verwenden nur ein Tool, das uns die lästige Arbeit mit XML abnimmt.

Der Prozess, aus Java-Code XML zu erzeugen, nennt sich Marshalling [4] oder Serialization. Der umgekehrte Weg, um aus XML wieder Objekte zu erstellen, nennt sich Unmarshalling oder Deserialzation. Damit dieser Prozess automatisiert abläuft, bietet das WebServiceTemplate natürlich auch Methoden an: marshallSendAndReceive*. Somit reduziert sich der Aufruf eines Web Service auf eine Zeile Code (Listing 5). Der Methode wird der konfigurierte Request übergeben, und als Antwort bekommt man die Response als ProductResponse zurück.

Listing 5
private ProductResponse getProductResponse(ProductRequest request) {
 ProductResponse response = (ProductResponse) wsTemplate
       .marshalSendAndReceive(request);
 return response;
}

Nachdem Sie die Methode in Ihrer Klasse eingefügt haben, wird sich der Compiler darüber beschweren, dass er wsTemplate nicht auflösen kann. Damit hat er natürlich recht. Also fügen Sie ein Feld zu Ihrer Klasse hinzu:

public class ProductServiceClientJAXB {
 private WebServiceTemplate wsTemplate;
 .
}
Geschrieben von
Thorsten Kamann
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.