Abstract

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.

Einige Definitionsversuche

Was ist ein Web-Service?

Definition

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.

SOAP am Beispiel

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> 

Beispiel einer WSDL-Beschreibung

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>

Beispiel UDDI

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>

Web-Services - Orchestrierung

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: