Gerippe für Java-Seifenkisten

Spring-WS

Das Produkt der Spring-Community zielt auf die Umsetzung dokumentengetriebener Web Services gemäß dem Contract-First-Ansatz ab [6]. JAX-WS bietet es nicht an. Somit unterscheidet es sich klar von den vorherigen Frameworks. Wenig überraschend lassen sich Spring-WS-Dienste gut ins restliche Spring-Universum integrieren. Von der Architektur her weist das Framework Ähnlichkeiten mit Spring-MVC auf. Weiterhin unterstützt es WS-Security und bringt eine mit Acegi Security [7] harmonierende Implementierung mit. Eine eigene Toolsuite vereinfacht die Programmierung.

Bei der Erstellung eines Web Service mit Spring-WS ist im ersten Schritt der Vertrag zu spezifizieren. Dazu muss aber keine vollständige WSDL (Web Service Description Language) geschrieben werden. Es reicht, die Dokumenttypen in Form einer XSD-Datei zu definieren (Listing 8). Zur Laufzeit kann dann die Runtime anhand des Schemas, der Serviceklasse und der Konfiguration dynamisch eine passende WSDL erzeugen. Im nächsten Schritt codiert der Entwickler die eigentliche Web-Service-Klasse. Am einfachsten geht das mithilfe von Annotationen. Durch @Endpoint wird die Klasse als ebensolcher ausgezeichnet und für jede Methode wird über @PayloadRoot festgelegt, welchen Dokumenttyp sie verarbeiten kann (Listing 9). Die zur Laufzeit bei der Web-Service-Methode eingehenden Anfragedaten lassen sich mittels @RequestPayload als Methodenargument injizieren. Liefert die Methode Antwortdaten zurück, ist sie außerdem noch mit @ResponsePayload zu annotieren.

Listing 8

  ...
Listing 9
...
@Endpoint 
public class CalculatorWS {
  @PayloadRoot(namespace = "http://calculator.javamagazin.de",
               localPart = "SumRequest")
  @ResponsePayload
  public SumResponse sum(@RequestPayload SumRequest request) {
    long a = request.getA();
    long b = request.getB();

    SumResponse response = new SumResponse();
    response.setReturn(a + b);
    return response;
  }
  ...
}

Große Auswahl hat der Programmierer in Bezug auf die Typen, die beim Injizieren der Anfragedaten und beim Zurückliefern der Antwortdaten zum Einsatz gelangen dürfen. So kann er sich einerseits den XML Payload übergeben lassen, diesen mit JAXP (Java API for XML Processing) oder einem alternativen API weiterverarbeiten und als Rückgabewert ein Java-XML-Objekt zurückliefern. Andererseits kann er sich auch eines Data-Binding-Frameworks bedienen und dieses das Marshalling beziehungsweise Unmarshalling durchführen lassen. Spring-WS unterstützt in diesem Zusammenhang Castor, JAXB, JiBX, XML Beans und XStream. In Listing 9 setzen wir z. B. JAXB-annotierte Transferobjekte ein. Natürlich sind auch Mischformen beider Varianten denkbar und in der Praxis anzutreffen.

Bei Spring-WS begegnen uns wiederum Interceptors, die sich client- und serverseitig einsetzen lassen. Zur Realisierung einer solchen Komponente schreibt man eine Klasse, die je nach Typ entweder org.springframework.ws.client.support.interceptor.ClientInterceptor oder org.springframework.ws.server.EndpointInterceptor als Interface implementiert. Darüber hinaus sind in den Bibliotheken verschiedene Klassen enthalten, von denen sich komfortabel ableiten lässt. Die Aktivierung von Interceptors wird zumeist auf dem Weg der Konfiguration herbeigeführt.

Das Ausrollen der Dienste ist auch hier in Webapplikationsform durchführbar. Das Servlet org.springframework.ws.transport.http.MessageDispatcherServlet agiert dabei als Front Controller. Die Konfiguration der Endpunkte erfolgt in einer Spring-Konfigurationsdatei (Listing 10). Wer es einfach liebt, der aktiviert darin den automatischen Scan- und Deploy-Modus. Die Einstellungen für die dynamische Bereitstellung der WSDL zur Laufzeit sind, genauso wie viele weitere, ebenfalls in dieser Datei vorzunehmen. Die Schemadatei legt der Entwickler üblicherweise im Verzeichnis WEB-INF/xsd ab.

Listing 10

Nun ist noch zu klären, wie sich mit Spring-WS ein Client bauen lässt. Das Framework stellt für diesen Zweck die Klasse org.springframework.ws.client.core.WebServiceTemplate bereit (Listing 11), die entsprechende Methoden anbietet. Die Anfragedaten kann der Nutzer analog zu vorhin in unterschiedlichen Formaten übergeben. Auch in Bezug auf das Antwortdatenformat zeigt sich das System flexibel. Wir setzen im Listing 11 der Einfachheit halber erneut auf JAXB. Für die asynchrone Operationsausführung bietet die Klasse ebenfalls Methoden.

Listing 11
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("de.javamagazin.calculator");

WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
webServiceTemplate.setMarshaller(marshaller);
webServiceTemplate.setUnmarshaller(marshaller);

SumRequest request = new SumRequest();
request.setA(1);
request.setB(2);

SumResponse response = (SumResponse) webServiceTemplate.marshalSendAndReceive("http://localhost:8080/sws/services/CalculatorWS", request);

System.out.println("Result: " + response.getReturn());
Fazit und Ausblick

Mit Apache Axis2, Apache CXF, Metro und Spring-WS stellte dieser Artikel die bedeutendsten Java-Frameworks zur Realisierung von SOAP Web Services und zugehöriger Clients vor und zeigte, welche zusätzlichen Möglichkeiten sich durch ihre Verwendung auftun. Wir stellten fest, dass der Programmierer bei Spring-WS im Gegensatz zu den Konkurrenzprodukten weder auf JAX-WS noch auf den Code-First-Ansatz zurückgreifen kann. Eine Gemeinsamkeit ist allen Produkten die Unterstützung von client- und serverseitigen Interceptors. Auch das Deployment der Webdienste als Webapplikation bieten alle an. Die Frage, wann man welches Framework nutzen sollte, lässt sich nur schwierig beantworten. Zu sehr hängt diese Entscheidung von den Rahmenbedingungen für das Projekt und der Erfahrung des Entwicklers ab. Grundsätzlich empfiehlt es sich, auf Standards zu setzen. Andererseits steht mit Spring-WS eine zwar gewöhnungsbedürftige, jedoch sehr mächtige Lösung zur Verfügung, die speziell erfahrenen Spring-Entwicklern zusagen wird. Nachdem aber mittlerweile alle Systeme sehr ausgereift sind, braucht sich keiner vor der zu treffenden Auswahl zu fürchten.

Im letzten Teil dieser Artikelserie geht es dann um Frameworks, mit deren Hilfe sich RESTful Web Services und Clients erstellen lassen. Hierbei werden wir Apache CXF, Jersey und RESTEasy unter die Lupe nehmen.

Bernhard Löwenstein (b.loewenstein[at]gmx.at) arbeitet als Projektleiter und Softwareentwickler für die Potsdamer Intervista AG. Er ist außerdem als IT-Trainer tätig und schreibt regelmäßig Artikel für verschiedene deutsche Fachmagazine.
Kommentare

Schreibe einen Kommentar

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