Unter einem Web-Service versteht man zunächst eine
Dienstleistung im klassischen Sinne (mit Merkmalen wie
Immaterialität und damit nicht-Lagerfähigkeit,
standortunabhängiger Produktion und der mangelnden
Entkopplung von Erzeugung und Konsumption), die über das
World Wide Web erbracht wird.
Die einzigen hierbei verbindlich benötigten Standards sind
die namensgebenden Web-Techniken. Hierzu gehören in erster
Linie die physischen Hardwareinfrastrukturen sowie die
benötigten Internet-Protokolle, z.B. TCP/IP.


Ein Web-Service ist eine über das Web erbrachte
Dienstleistung, die abgestimmte Inhalte in einem
abgestimmten Format über standardisierte
Kommunikationsmechanismen zur Verfügung stellt. Er ist
über ein offenes, im Internet verwendetes Protokoll
zugreifbar.
Darüber hinaus existieren Beschreibungen über die Natur
der angebotenen Leistung, seine Schnittstelle ist
veröffentlicht
.
Optional existieren Verzeichnisse, die das Auffinden von
für einen Verbraucher interessanten Diensten
ermöglichen.
In der technischen Umsetzung einer
Web-Service-Architektur sind nicht alle Protokolle,
Sprach- und Beschreibungsebenen zwingend zu realisieren.

Das hier vorgestellte Beispiel wurde für die SOAP Infrastruktur Apache Axis (in Apache Tomcat) entwickelt. Als Einstiegsbeispiel soll hier ein Zahlenaddier-Dienst dienen, der die hochkomplexe Aufgabe hat, zwei Zahlen miteinander zu addieren ;). Die Serverkomponente dieses Beispiels führt die Rechenoperation durch, die Clientkomponente greift darauf zu.
Serverkomponente
// Example service for SOAP Axis Release Candidate 1
import java.util.*;
import java.lang.*;
public class Add{
public int add(int number1, int number2)
{
return (number1+number2);
} //add()
} //class Add
Einbinden der Serverkomponente in einen Application Server, hier: Tomcat
Nach dem Compilieren muß die resultierende Java Klasse (
Add.class
) innerhalb des Tomcat Verzeichnisbaumes in ein
bestimmtes Unterverzeichnis des Tomcat Verzeichnisbaumes
kopiert werden (z.B.
webapps/axis/WEB-INF/classes/
).
Zusätzlich dazu benötigt man für jeden Service einen
Deployment Descriptor, der als Datei vorliegt. Für unser
Beispiel ist dies die Datei
DeploymentDescriptor.wsdd
mit folgendem Inhalt:
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="NumberAdder" provider="java:RPC">
<parameter name="className" value="Add"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment>
Mit dem Parameter
allowedMethods
kann der Zugriff auf Methoden gesteuert werden, *
bedeutet, daß der Zugriff auf alle Methoden der Klasse
erlaubt ist.
Abschließend muß mit folgendem Befehl der Service in Tomcat eingebunden werden:
java org.apache.axis.client.AdminClient
DeploymentDescriptor.wsdd
Clientkomponente
import java.net.*;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
// Types for ParameterModes
import org.apache.axis.encoding.XMLType;
import org.apache.axis.utils.Options;
import javax.xml.rpc.ParameterMode;
import javax.xml.namespace.QName;
public class AddClient {
public static void main(String [] args) throws Exception{
if (args.length <=2) {
System.out.println ("\n-------------------\nUSAGE: AddClient int int url\n---------------------\n");
}
URL url = new URL(args[2]);
// construct a call
Call myCall = new Call(url);
// set the URL of the call endpoint
myCall.setTargetEndpointAddress(url);
// the child of the SOAP Body element schould look like this:
// <ns1:add xmlns:ns1="urn:NumberAdder"></ns1:add>
myCall.setOperationName( new QName("urn:NumberAdder", "add") );
// prepare the parameters for the call
myCall.addParameter("number1", XMLType.XSD_INT, ParameterMode.IN);
myCall.addParameter("number2", XMLType.XSD_INT, ParameterMode.IN);
// set the return type of the call
myCall.setReturnType(XMLType.XSD_INT);
// invoke the call
Object myParams[] = new Object[2];
myParams[0]=(Object) new Integer(args[0]);
myParams[1]=(Object) new Integer(args[1]);
Integer resp = (Integer) myCall.invoke(myParams);
System.out.println(resp);
} // End main
} // End Class AddClient Nach dem Kompilieren kann man die Clientkomponente mit folgendem Befehl zum Aufruf der Serverkomponente benutzen:
java AddClient 3 29
http://localhost/axis/services/NumberAdder
Netzverkehr
Und so sieht der SOAP Aufruf aus, der bei obigem Beispiel zwischen Client und Server übertragen wird:
POST /axis/servlet/AxisServlet HTTP/1.0 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/beta3 Host: 10.0.0.160 Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 472 <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:add soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:NumberAdder"> <number1 xsi:type="xsd:int">1</number1> <number2 xsi:type="xsd:int">2</number2> </ns1:add> </soapenv:Body> </soapenv:Envelope> HTTP/1.1 200 OK Date: Sun, 22 Sep 2002 11:16:42 GMT Server: MyHTTPServer Content-Type: text/xml; charset=utf-8 Connection: close <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:addResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:NumberAdder"> <addReturn xsi:type="xsd:int">3</addReturn> </ns1:addResponse> </soapenv:Body> </soapenv:Envelope>
Zur SOAP-Anfrage des vorhergehenden Beispiels soll hier eine diesen Dienst beschreibende WSDL-Datei vorgestellt werden.
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:add soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:NumberAdder"> <number1 xsi:type="xsd:int">1</number1> <number2 xsi:type="xsd:int">2</number2> </ns1:add> </soapenv:Body> </soapenv:Envelope>
<?xml version="1.0" encoding="utf-8" ?>
<description
xmlns="http://www.w3.org/ns/wsdl"
targetNamespace= "http://www.example.com/NumberAdder/wsdl"
xmlns:tns= "http://www.example.com/NumberAdder/wsdl"
xmlns:ghns = "http://www.example.com/schemas/NumberAdder"
xmlns:wsoap= "http://www.w3.org/ns/wsdl/soap"
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsdlx= "http://www.w3.org/ns/wsdl-extensions">
<documentation>
This document describes the NumberAdder Web service.
</documentation>
<types>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/schemas/NumberAdder"
xmlns="http://www.example.com/schemas/NumberAdder">
<xs:element name="add">
<xs:complexType>
<xs:sequence>
<xs:element name="number1" type="xs:int"/>
<xs:element name="number2" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="addResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="addReturn" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</types>
<interface name = "NumberAdderInterface" >
<operation name="opAdd"
pattern="http://www.w3.org/ns/wsdl/in-out"
style="http://www.w3.org/ns/wsdl/style/iri"
wsdlx:safe = "true">
<input messageLabel="In"
element="ghns:add" />
<output messageLabel="Out"
element="ghns:addResponse" />
</operation>
</interface>
<binding name="numberAdderSOAPBinding"
interface="tns:NumberAdderInterface"
type="http://www.w3.org/ns/wsdl/soap"
wsoap:protocol="http://www.w3.org/2003/05/soap/bindings/HTTP/">
<operation ref="tns:opAdd"
wsoap:mep="http://www.w3.org/2003/05/soap/mep/soap-response"/>
</binding>
<service name="NumberAdderService"
interface="tns:NumberAdderInterface">
<endpoint name="NumberAdderEndpoint"
binding="tns:numberAdderSOAPBinding"
address ="http://localhost/axis/services/NumberAdder "/>
</service>
</description>Universal Description, Discovery, and Integration (UDDI) ist eine Spezifikation, der einen Verzeichnisdienst für Web Services zur Verfügung stellt und verschiedene XML-Vokabulare zur Kommunikation zwischen Verbrauchern und einem UDDI-Server zur Verfügung stellt.
Nachfolgendes Beispiel zeigt eine typische Anfrage, die
nach Firmen sucht, die WSDL-Basierte Web Services für
beliebige Transportgüter zur Verfügung stellt (Suche
nach
United Nations Standard Products & Services
Code
mit der ID
78NNNNNN
, Transportation and Storage and Mail Services). Die
Firmen, die gefunden werden, sollen dann absteigend
sortiert zurückgeliefert werden.
(UDDI unterstützt neben der Suche nach
UNSPSC
Codes noch weitere (international und national)
standardisierte numerische Kategorien:
NAICS
,
D-U-N-S
,
ISO 3166
und
SIC
)
<find_business xmlns="urn:uddi-org:api_v3">
<!--find businesses that have WSDL-based bindings related
to Transporting Goods -->
<findQualifiers>
<findQualifier>
uddi:uddi.org:findqualifier:sortbynamedesc
</findQualifier>
<findQualifier>
uddi:uddi.org:sortorder:uts-10
</findQualifier>
<findQualifier>
uddi:uddi.org:findqualifier:orallkeys
</findQualifier>
</findQualifiers>
<!-- discover tModels that are of the WSDL type and related
to Transporting Goods -->
<find_tModel xmlns="urn:uddi-org:api_v3">
<findQualifiers>
<findQualifier>
uddi:uddi.org:findqualifier:approximatematch
</findQualifier>
<findQualifier>
uddi:uddi.org:findqualifier:orlikekeys
</findQualifier>
<findQualifier>
uddi:uddi.org:sortorder:uts-10
</findQualifier>
</findQualifiers>
<categoryBag>
<keyedReference keyValue="wsdlSpec"
tModelKey="uddi:uddi.org:categorization:types"/>
<keyedReference keyValue="78%"
tModelKey="uddi:uddi.org:ubr:categorization:unspsc"/>
</categoryBag>
</find_tModel>
</find_business>Ein mögliches Ergebnis einer solchen Anfrage könnte etwa lauten:
<businessEntity
businessKey="uddi:macroroute.com:uddi2:macroroute.com:3f10…"
operator="Macroroute UDDI Services"
authorizedName="…"
xmlns="urn:uddi-org:api_v3">
<discoveryURLs>
<discoveryURL useType="homepage">http://macroroute.example.com/</discoveryURL>
<discoveryURL useType="businessEntity">
http://macroroute.example.com/transportation/
</discoveryURL>
</discoveryURLs>
<name xml:lang="en">Transportation Business</name>
<description xml:lang="en">Transportation Business</description>
<businessServices>
<businessService
serviceKey="…"
businessKey="uddi:macroroute.com:3f10…">
<name xml:lang="en">Packet Transportation and Delivery, Home Pickup Service</name>
<description xml:lang="en">Packet Transportation and Delivery, Home Pickup Service</description>
<bindingTemplates>
<bindingTemplate
bindingKey="…."
serviceKey="…">
<accessPoint useType="wsdlDeployment">
http://macroroute.example.org/PickupPacketTransportationWebService/pickup.wsdl
</accessPoint>
<!--
Es können auch direkte Zugriffsinformationen
in einer UDDI Antwort enthalten sein.
Üblicherweise ist dies der Fall, wenn keine WSDL-Datei
für einen Service hinterlegt ist.
<accessPoint URLType="https">
http://macroroute.example.com/pickup
</accessPoint>
<accessPoint useType="endPoint">
tel:+1-512-555-1212
</accessPoint>-->
<categoryBag>
<keyedReference keyName="uddi-org:types:wsdl"
keyValue="wsdlDeployment"
tModelKey="uddi:uddi.org:categorization:types"/>
</categoryBag>
</bindingTemplate>
</bindingTemplates>
<categoryBag>
<keyedReference
tModelKey="…"
keyName="Packet Transportation"
keyValue="1010" />
</categoryBag>
</businessService>
</businessServices>
</businessEntity>
Das Beispiel zeigt verschiedene Web-Services, die zusammen den Dienst der wechselseitigen Umrechnung von Geldbeträgen des europäischen Währungsraumes erbringen. Die Verwendungsbeziehungen sind als gerichtete Kanten ausgehend vom nutzenden Dienst hin zum benutzten dargestellt. Die Dienste sind auch eigenständig nutzbar.
Insgesamt wird das durch die Europäische Zentralbank
vorgegebene Verfahren der Berechnung, die
Zwischen-Nutzung
des Euros (sog. Triangulation), benutzt. Dabei wird
zunächst die Ursprungslandeswährung in das
Euro-Äquivalent überführt, welches dann in die
gewünschte Zielwährung umgerechnet wird.
Die Verteilung der Aufgaben ist hierbei wie folgt:
ExchangeRates
liefert auf Anfrage mit dem amtlichen Währungskürzel
den entsprechenden, durch die Europäische
Zentralbank festgelegten, Umrechnungskurs.
EuroConverter
rechnet einen Betrag der Landeswährung in die
Eurosumme um, bzw. umgekehrt. Zur Berechnung wird
der durch ExchangeRates bereitgestellte Wechselkurs
benötigt.
CurrencyConvert
erlaubt die Umrechnung zwischen allen Währungen des
europäischen Währungsraumes. Gemäß der Festlegung
durch die Europäische Zentralbank darf dieser
Vorgang ausschließlich durch Umrechnung in Euro
ausgeführt werden (Triangulation). Daher muß
zunächst der Ursprungsbetrag nach Euro, anschließend
dieser Wert in die Zielwährung konvertiert werden.
Zur Realisierung nutzt
CurrencyConvert
die durch
EuroConverter
angebotenen Funktionen.