Zu Ihren Diensten, Monsieur

Web Services mit Spring WS

Thorsten Kamann

Für den Datenaustausch oder das Anbieten von Diensten zwischen Anwendungen werden oft Web Services verwendet. Um einen Web Service anzubieten oder zu verwenden, gibt es sehr viele Möglichkeiten und Vorgehensweisen. Dieser dreiteilige Artikel stellt Ihnen die Möglichkeiten vor, die Spring WS Ihnen bietet.

Das Spring Framework [1] bietet nativ eine Unterstützung für die Verwendung von Web Services. Sie können dabei das zugrunde liegende Framework selbst bestimmen, z. B. Axis [2] oder Apache XCF [3].

Spring WS [4] ist ein Projekt aus dem SpringSource-Umfeld und hat das Ziel, die Entwicklung von Web Services zu vereinfachen. Dabei werden viele der etablierten JAXP-Frameworks, z. B. DOM, SAX und StAX, aber genauso JDOM, dom4j und XOM unterstützt. Darüber hinaus existiert innerhalb von Spring WS ein Modul, das für das XML-Mapping (O/X Mapper) verantwortlich zeichnet. Dieses Modul unterstützt JAXB 1/2, Castor, XMLBeans, JiBX und XStream. Das OXM-Modul ist inzwischen in das Spring Framework übernommen worden und steht somit auch für andere Anwendungen zur Verfügung. Alle Features des Spring Frameworks können hier ebenfalls genutzt werden. Das betrifft nicht nur die Konfiguration und Dependency Injection, sondern auch Sicherheitsaspekte, wenn Sie Spring Security verwenden wollen oder können. Abgerundet wird die Featureliste mit der Unterstützung für WS-Security, wenn Sie die SOAP-Nachrichten ver- und entschlüsseln oder signieren wollen.

Die ganze Featureliste wird von den Entwicklern als „Makes the Best Practice an Easy Practice“ bezeichnet. Die Artikelserie wird zeigen, ob sie Recht behalten. Der erste Teil der Serie enthält die Basics zu Spring WS. Hier werden wir ein kleines Projekt entwickeln, indem Sie einen Web Service implementieren, der die Funktionsweise und Features von Spring WS beleuchtet. Der zweite Teil der Serie knüpft nahtlos an den ersten Teil an und diskutiert die Schwachstellen der Lösung. Danach werden wir gemeinsam eine bessere Lösung entwickeln.

Im dritten Teil werden wir den Web Service mit Spring Security etwas sicherer machen, zusätzlich einen Blick auf die Architektur von Spring-WS-Projekten werfen und das Thema Integrationstest betrachten.

Doch nun genug geredet…

… beginnen wir mit einem Beispielprojekt. Wir wollen in diesem Projekt einen Web Service entwickeln, wie er in Abbildung 1 dargestellt ist. Der ProductService enthält lediglich eine Web-Service-Methode. Diese findet Produkte anhand der Warengruppe (Category), des Lieferanten (Supplier) und einer frei konfigurierbaren Zeitspanne (DateRange).

Abb. 1: Der ProductService

Das dazu gehörende Domänenmodell ist in Abbildung 2 zu sehen. Die Warengruppe (Category) und der Lieferant (Supplier) haben lediglich eine ID und name-Property. Das gefundene Produkt hält Referenzen auf den Lieferanten und die Warengruppe. Auf diese beiden Referenzen komme ich später noch genauer zu sprechen.

Abb. 2: Domänenmodell für den ProductService

[ header = Seite 2: Schritt 1: Projekt erstellen ]

Schritt 1: Projekt erstellen

Spring WS bietet einen Maven-Archetypen, auf den wir hier aber bewusst verzichten, um die Schritte besser nachvollziehen zu können, die benötigt werden, um ein solches Projekt zu erstellen. Als Erstes brauchen wir ein Eclipse-Projekt. Da dieses später auf einem Tomcat deployt werden soll, bietet sich als Projekttyp ein Dynamisches Webprojekt an. Beenden Sie den Projekt-Wizard nicht mit FINISH schon auf der ersten Seite, sondern gehen Sie alle drei Seiten mit NEXT durch. Auf der zweiten Seite ändern Sie den Pfad zu dem Source-Verzeichnis auf src/main/java und auf der dritten Seite das Verzeichnis für den WebContent auf src/main/web. Zusätzlich brauchen Sie ein weiteres Source-Verzeichnis, das weitere Ressourcen aufnehmen kann. Nennen Sie das Verzeichnis src/main/resources.

Schritt 2: Ein XML Schema erstellen

XML Schema? Wofür das denn? Spring WS geht streng nach dem Ansatz Contract-First (Kasten: „Contract-First vs. Contract-Last“) vor. Deswegen benötigen Sie zuerst einen Vertrag. Dieser Vertrag, der die Schnittstelle des Web Service beschreibt, kann eine WSDL sein oder in diesem Fall ein XML Schema. Der Vorteil eines XML Schemas gegenüber einer WSDL ist, dass man sich bei der Definition des Vertrags auf die eigentliche Schnittstelle konzentrieren kann, ohne von den technischen Details einer WSDL abgelenkt zu werden.

In Abbildung 3 sehen Sie eine Darstellung des Schemas. Da wir lediglich eine Web-Service-Methode anbieten wollen, brauchen wir auch nur ein Element. Im Sinne der Namensgebung in WSDLs nennen wir das Element hier ProductRequest. Wie in Abbildung 1 zu sehen ist, benötigt dieser Request drei Parameter: Category, Supplier und DateRange. Diese werden in dem Schema als anonyme komplexe Datentypen angelegt. Diese Typen bekommen noch die benötigten Attribute (Abb. 2), und fertig ist das Schema (Listing 1).

Abb. 3: Schematische Darstellung des verwendeten XML Schemas

<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="http: //www.itemis.de/hoa/spring/ws/product" elementFormDefault="qualified" 
xmlns="http: //www.w3.org/2001/XMLSchema" xmlns:p="http: //www.itemis.de/hoa/spring/ws/product"> <element name="ProductRequest"> <complexType> <all> <element name="Category" type="p:CategoryType" /> <element name="Supplier" type="p:SupplierType"></element> <element name="DateRange" type="p:DateRange"></element> </all> </complexType> </element> <complexType name="CategoryType"> <sequence> <element name="id" type="int"></element> <element name="name" type="string"></element> </sequence> </complexType> <complexType name="SupplierType"> <sequence> <element name="id" type="int"></element> <element name="name" type="string"></element> </sequence> </complexType> <complexType name="DateRange"> <sequence> <element name="startDate" type="date"></element> <element name="endDate" type="date"></element> </sequence> </complexType> </schema>

Das Schema speichern Sie am besten unter src/main/resources/META-INF/schema/Products.xsd.

[ header = Seite 3: Schritt 3: Domänenmodell und Serviceklasse implementieren ]

Schritt 3: Domänenmodell und Serviceklasse implementieren

Insgesamt müssen Sie dafür fünf Klassen implementieren. Wir verzichten für dieses Beispiel komplett auf Interfaces. Die vier Domänenklassen sind einfache POJOs mit Gettern und Settern. Diese finden Sie natürlich schon implementiert in dem mitgelieferten Beispiel. Die Serviceklasse implementiert die eigentliche Businesslogik. In einem realen Projekt würde die Servicemethode über Datenzugriffskomponenten auf eine Datenbank zugreifen und die in Frage kommenden Produkte dort abfragen. Für dieses Beispiel habe ich es uns etwas einfacher gemacht und gebe immer eine Liste mit zwei Produkten zurück (Listing 2).

public class ProductService {

public List<Product> findProductsForSupplierAndCategoryInDateRange(
Category category, Supplier supplier, DateRange dateRange) {

List<Product> products = new ArrayList<Product>();

products.add(new Product(12345, "Product1", category, supplier));
products.add(new Product(12346, "Product2", category, supplier));
return products;
}
}

Contract First vs. Contract Last
Es gibt zwei Ansätze, wie Web Services entwickelt werden können. Entweder man beginnt, eine WSDL zu definieren und erzeugt aus dieser den benötigten Java-Quellcode (Contract First), oder man schreibt zuerst den Java-Quellcode und erzeugt daraus eine WSDL (Contract Last). Doch welche Methode ist die bessere? Wie bei vielem kann man das nicht abschließend beantworten. Doch es gibt einige Argumente für den Contract-First-Ansatz. Definieren Sie zuerst die WSDL, dann haben Sie viel mehr Steuerungsmöglichkeiten, um die WSDL zu optimieren. Oft referenzieren Klassen ja andere Klassen, die nicht in der WSDL definiert werden sollen. Dies kann besser in einer WSDL umgangen werden. Ein anderer Punkt ist die Interoperabilität. Beschränkt man sich bei den Datentypen auf die Typen, die in einem XML Schema definiert werden können, dann wird es in den wenigsten Fällen zu Problemen in den verschiedenen Sprachen kommen, die den Web Service später konsumieren. Es gibt noch einige andere Punkte zu diesem Thema, die die Spring-WS-Entwickler unter [5] zusammengetragen haben.

Schritt 4: Maven konfigurieren

Bisher haben wir nur die Bordmittel der JVM verwendet. Der nächste Schritt ist allerdings die Implementierung des Endpoints. Der Endpoint ist die Instanz, die die Anfragen von einem Web-Service-Konsumenten beantwortet. In diesem Teil verwenden wir JDOM, um die Anfrage zu analysieren und aus dem SOAP-Body die benötigten Daten zu extrahieren. Außerdem greifen wir zum ersten Mal auf Spring-WS-Funktionen zurück. Um die benötigten Bibliotheken in das Projekt zu integrieren, verwenden wir Maven. Dazu aktivieren wir für unser Projekt das Maven Dependency Management (Rechtsklick auf PROJEKT | MAVEN | ENABLE DEPENDENCY MANAGEMENT). Daraufhin erscheint ein Dialogfenster wie in Abbildung 4 zu sehen ist. Tragen Sie hier die gewünschten Daten ein und klicken auf FINISH.

Abb. 4: Dialog zum Aktivieren des Maven-Dependency-Managements

Um den Endpoint zu implementieren, benötigen wir zuerst nur zwei Abhängigkeiten:

  • spring-ws-core
  • jdom

Mit Maven ist es sehr einfach, diese Abhängigkeit hinzuzufügen. Sie brauchen nur die pom.xml und in dem POM-Editor die Quellansicht zu öffnen (der rechte Tab mit der Beschriftung pom.xml). Dort fügen Sie den Inhalt aus Listing 3 ein.

<dependencies>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>1.1</version>
</dependency>
</dependencies>

Nun haben Sie alles beisammen, um mit der Implementierung des Endpoints zu beginnen.

[ header = Seite 4: Schritt 5: Implementierung des Endpoints ]

Schritt 5: Implementierung des Endpoints

Ein Endpoint wird benötigt, damit die Anfragen beantworten werden können. Der Endpoint muss den SOAP-Request verarbeiten können und auch wissen, was er mit den Daten anfangen soll. Damit Spring WS eine Klasse als Endpoint erkennt, muss diese das Interface org.springframework.ws.server.endpoint.PayloadEndpoint implementieren. Aber Spring wäre nicht Spring (das gilt auch für Spring WS), wenn es da nicht schon was vorbereitet hätte. Es gibt schon einige abstrakte Implementierungen, die Sie direkt verwenden können und die Ihnen viel Arbeit ersparen. Abbildung 5 zeigt die verfügbaren Implementierungen.

Abb. 5: Typhierarchie des Interfaces PayloadEndpoint

Da wir für diesen Artikelteil jDOM verwenden wollen, benutzen wir die AbstractJDomPayloadEndpoint-Implementierung. Die einzige Methode, die wir implementieren müssen, ist die protected Element invokeInternal(Element requestElement) throws Exception {}. Listing 4 zeigt eine erste Implementierung unseres Endpoints. Im Konstruktor des Endpoints definieren wir schon die XPath Expressions, mit denen wir später den Body des SOAP-Requests parsen wollen, um an die notwendigen Daten zu kommen.

public class ProductServiceEndpoint extends AbstractJDomPayloadEndpoint {
private XPath categoryExpression;
private Namespace namespace;
private XPath supplierExpression;
private XPath dateRangeExpression;


public ProductServiceEndpoint () throws JDOMException {
namespace = Namespace.getNamespace("prod",
"http: //www.itemis.de/hoa/spring/ws/product");
categoryExpression = XPath.newInstance("//prod:Category");
categoryExpression.addNamespace(namespace);

supplierExpression = XPath.newInstance("//prod:Supplier");
supplierExpression.addNamespace(namespace);

dateRangeExpression = XPath.newInstance("//prod:DateRange");
dateRangeExpression.addNamespace(namespace);

}

@Override
protected Element invokeInternal(Element requestElement){
return null ;
}

}

Die Methode invokeInternal bekommt als Parameter den Body des SOAP-Requests. Mit den drei Xpath-Expressions werden die Elemente für die drei Parameter für die Servicemethode ermittelt. Doch halt! Wie rufen wir diese Servicemethode überhaupt auf? Wir haben noch keine Referenz auf die Serviceklasse. Das erledigen wir schnell, indem wir ein Feld und eine zugehörige Setter-Methode für den ProductService definieren. Nachdem dies erledigt ist, können wir uns der Implementierung der invokeInternal-Methode widmen. Der eigentliche Serviceaufruf geschieht mit Java-Mitteln, d. h. aus den Daten des SOAP-Bodys müssen die entsprechenden Objekte erzeugt werden. In Listing 5 finden Sie eine mögliche Lösung dieser Aufgabe.

protected Element invokeInternal(Element requestElement) throws Exception {
Category category = null;
Supplier supplier = null;
DateRange dateRange = null;

Element categoryElement = (Element) categoryExpression
.selectSingleNode(requestElement);
category = new Category();
category.setId(Integer.parseInt(categoryElement.getChildText("id",
namespace)));
category.setName(categoryElement.getChildText("name", namespace));

Element supplierElement = (Element) supplierExpression
.selectSingleNode(requestElement);
supplier = new Supplier();
supplier.setId(Integer.parseInt(supplierElement.getChildText("id",
namespace)));
supplier.setName(supplierElement.getChildText("name", namespace));

SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yy");
Element dateRangeElement = (Element) dateRangeExpression
.selectSingleNode(requestElement);
dateRange = new DateRange();
dateRange.setStartDate(dateFormat.parse(dateRangeElement.getChildText(
"startDate", namespace)));

Die Vorgehensweise ist einfach. Erst wird das Element mit der Xpath-Expression (z. B. Category) ermittelt. Die Properties der zugehörigen Klasse werden dann mit der Funktion getChildTextermittelt. Etwas aufwändiger ist die Erzeugung des DateRange-Objekts. Hier müssen wir den Inhalt der Kindelemente in ein Datum wandeln. Dazu können Sie am besten das SimpleDateFormataus dem java.text Package verwenden. Nun ist es an der Zeit, den Service mit den frisch erstellten Objekten abzufragen:

List<Product> products = productService .findProductsForSupplierAndCategoryInDateRange(category,
supplier, dateRange);


Jetzt ist das Meiste schon getan. Wir haben eine Liste mit den gefundenen Produkten. Allerdings stellt uns diese Liste vor einige Probleme. Wenn Sie sich das Klassendiagramm aus Abbildung 2 noch einmal ansehen, erkennen Sie, dass die Klasse Product Referenzen auf Category und Supplier hält. Da die Methode invokeInternal ein jDOM-Element als Rückgabe liefert, muss der ganze Objektbaum, der an dem Product hängt, in XML bereitgestellt werden. Diesen Vorgang nennt man Marshalling. Spring WS liefert einen leistungsfähigen O/X-Mapper. Wie bei Spring üblich, ist dies nur eine Abstraktionsschicht über vorhandene Frameworks:

  • JAXB 1 und 2
  • Castor
  • XMLBeans
  • JiBX
  • XStream

Um nun in unserem Endpoint einen Marshaller zu verwenden, reicht es, ein Feld vom Typ org.springframework.oxm.Marshaller (ist ein Interface) und die zugehörige Setter-Methode zu erstellen. Im nächsten Schritt erstellen wir die zugehörige Spring-Konfiguration, die eine konkrete Implementierung in unseren Endpoint injiziert. Das Interface hat nur folgende interessante Methode:

void marshal(Object graph, javax.xml.transform.Result result)
throws XmlMappingException, IOException;

Um diese Methode aufzurufen, brauchen wir lediglich das Objekt, das in XML bereitgestellt werden soll und eine Implementierung des Interfaces javax.xml.transform.Result. jDOM liefert bereits eine passende Implementierung dieses Interfaces, sodass wir die Methode nur um einige Zeilen erweitern müssen (Listing 6).

protected Element invokeInternal(Element requestElement) throws Exception {

…

JDOMResult result = new JDOMResult();

marshaller.marshal(products, result);
return (Element) result.getResult().get(0);
}

Damit der Endpoint nun verwendet werden kann, brauchen wir noch ein paar weitere Bibliotheken. Die wichtigsten davon sind Castor und Jaxen. Castor ist für das Marshalling zuständig und Jaxen wird für die Auswertung der XPath-Expressions benötigt. Allerdings ist die pom.xml von Jaxen nicht sonderlich gut gepflegt. Aus diesem Grund müssen einige Abhängigkeiten, die Jaxen definiert, ausgeschlossen werden.

[ header = Seite 5: Schritt 6: Spring konfigurieren ]

Schritt 6: Spring konfigurieren

Bisher haben wir von Spring recht wenig gesehen. Die erstellten Klassen waren allesamt POJOs. Lediglich zweimal kamen schon Spring-Artefakte ins Spiel. Einmal die abstrakte KlasseAbstractJDomPayloadEndpoint, mit der wir unseren Endpoint erweitert haben. Das andere Mal als wir den Marshaller des Spring O/X Mappers verwendeten. Doch nun ist es an der Zeit, sämtliche Komponenten miteinander zu verdrahten. Es gibt zwei Klassen, die typische Spring Beans sind: die ProductService– und die ProductServiceEndpoint-Klasse. Der ProductServiceEndpoint hält eine Referenz auf den ProductService. Somit muss dies ebenfalls in der Spring-Konfiguration abgebildet werden (Listing 7).

<beans xmlns="http: //www.springframework.org/schema/beans"
xmlns:xsi="http: //www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http: //www.springframework.org/schema/beans 
http: //www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="ProductService" class="de.itemis.hoa.spring.ws.service.ProductService"/> <bean id="ProductServiceEndpoint" class="de.itemis.hoa.spring.ws.endpoint.ProductServiceEndpoint"> <property name="productService" ref="ProductService"/> <property name="marshaller" ref="castorMarshaller"/> </bean> <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/> </beans>

Diese Spring-Konfiguration können wir als spring-ws-servlet.xml unter META-INF/spring abspeichern. Im nächsten Schritt wird die web.xml dahingehend konfiguriert, dass diese Datei beim Start der Anwendung herangezogen und der Spring-Kontext aufgebaut wird. Zusätzlich ist bereits der Marshaller injiziert worden. Der CastorMarshaller kommt ohne jegliche weitere Konfiguration aus. Erst wenn das XML-Format, in das der Marshaller die Objekte bereitstellen soll, angepasst werden muss, kann der CastorMarshaller konfigurativ angepasst werden.

Neben den beiden Klassen, die jetzt miteinander verdrahtet wurden, müssen noch der Endpoint und die WSDL-Generierung konfiguriert werden. Die Konfiguration des Endpoints ist recht einfach mit einem Mapping zwischen Namespace und der konfigurierten Bean hergestellt. Optional können Sie noch einen Logging Interceptor hinzufügen (Listing 8).

<bean class="org.springframework...mapping.PayloadRootQNameEndpointMapping">
<property name="mappings">
<props>
<prop
key="{http: //www.itemis.de/hoa/spring/ws/product}ProductRequest">
ProductServiceEndpoint</prop>
</props>
</property>
<property name="interceptors">
<bean
class="org.springframework...interceptor.PayloadLoggingInterceptor"/>
</property>
</bean>

In Listing 9 sehen Sie die Konfiguration für die automatische WSDL-Generierung. Über die Properties portTypeName und locationURI können Sie die generierte WSDL beeinflussen. Im nächsten Schritt sehen Sie noch, wie die locationURI an die wirkliche Serverumgebung angepasst werden kann. Die Klasse DefaultWsdl11Definition bietet noch einige andere Konfigurationsparameter, die Sie im entsprechenden Javadoc nachlesen können.

<bean id="product"
class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
<property name="schema" ref="schema" />
<property name="portTypeName" value="ProductResource" />
<property name="locationUri" value="/productService/" />
<property name="targetNamespace"
value="http: //www.itemis.de/hoa/spring/ws/product/definitions" />
</bean>

<bean id="schema" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:META-INF/schema/Product.xsd" />
</bean>

[ header = Seite 6: Schritt 7: Konfiguration des Web Descriptors ]

Schritt 7: Konfiguration des Web Descriptors

Der letzte Schritt ist es, den Web Descriptor (web.xml) zu konfigurieren. Die web.xml befindet sich im Verzeichnis src/main/web/WEB-INF. In dieser web.xml werden nur dasMessageDispatcherServlet aus dem Spring WS Framework und die zugehörigen Mappings konfiguriert (Listing 10). Das MessageDispatcherServlet hat in unserem Beispiel zwei Parameter:contextConfigLocation und tarnsformWsdlLocations. Der erste Parameter gibt an, wo die initiale Kontextkonfiguration zu finden ist. In unserem Beispiel ist das die spring-ws-servlet.xml, die wir im vorangegangenen Schritt erstellt haben. Der zweite Parameter ist fast noch interessanter. Hiermit können Sie angeben, ob die URIs, die in der WSDL enthalten sind, so umgewandelt werden, dass der aktuelle Servername, Port und Anwendungsname enthalten sind.

<web-app id="WebApp_ID" version="2.4"
xmlns="http: //java.sun.com/xml/ns/j2ee" xmlns:xsi="http: //www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http: //java.sun.com/xml/ns/j2ee http: //java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Product Catalogue Service</display-name>

<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>
org.springframework.ws.transport.http.MessageDispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:META-INF/spring/spring-ws-servlet.xml
</param-value>
</init-param>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Schritt 8: Starten der Webanwendung und Testen des Web Service mit SoapUI

In den letzten 7 Schritten haben wir eine Anwendung erstellt, die einen Web Service zur Verfügung stellt. Der letzte Teil unseres Vorhabens besteht darin, die Anwendung auf einem Tomcat zu deployen. Mit Eclipse geht das sehr einfach mit RUN AS… | RUN ON SERVER. Die Server-Runtime haben Sie bereits bei der Erstellung des Projekts festgelegt. Die Anwendung wird automatisch auf dem Server deployt und gestartet. Nach wenigen Sekunden ist das erledigt. Ein Aufruf des URLs http://localhost:8080/articles-spring-ws-dom/productService/product.wsdl zeigt die von Spring WS generierte WSDL. Doch was nun? Die Anwendung enthält noch keinen Clientcode. Wir können den Web Service nicht ausprobieren. Jetzt kommt SoapUI [6] ins Spiel. SoapUI ist ein Web-Service-Testing-Tool. Damit können SOAP-Requests abgesetzt werden und genau diese Funktion verwenden wir auch, um den Web Service aufzurufen. Im Beispielprojekt finden Sie ein Verzeichnis soap-ui. Die dort enthaltene XML-Datei ist ein SoapUI-Projekt. Wenn Sie dieses Projekt öffnen, finden Sie links im Navigator einen vorbereiteten Request. Diesen können Sie ausführen und erhalten einen Response mit 2 Products.

Zusammenfassung

In diesem ersten Teil der Artikelserie haben wir bereits einen funktionsfähigen Web Service erstellt. Allerdings sind viele Dinge noch nicht optimal. Zum einem haben wir noch keinen richtigen Client. Zum anderen arbeiten wir direkt auf dem SOAP-Body. Das ist bei größeren Requests nicht zielführend. Viel lieber wollen wir direkt mit Java-Objekten arbeiten. Deswegen werden wir im nächsten Teil den Web Service auf JAXB 2 umstellen und einen Client implementieren, so dass wir SoapUI nicht mehr für das Testen der Anwendung brauchen.

Thorsten Kamann ist als Softwarearchitekt und als Coach bei itemis tätig. Seine Schwerpunkte sind webbasierte Technologien, MDSD, leichtgewichtige und flexible Architekturen und Open Source. Er ist Project Lead bei der Fornax Platform, einer Plattform für die Entwicklung von MDSD-related Tools und Groovy-Commiter. Darüber hinaus schreibt er Bücher, veröffentlicht regelmäßig Artikel in Fachmagazinen und hält Vorträge auf Fachkonferenzen zu obigen Themen.
Geschrieben von
Thorsten Kamann
Kommentare

Schreibe einen Kommentar

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