|
|
|
Einführung in XML-Webservices mit XML-RPC |
Diesen
Beitrag stellt zur Verfügung:
XML-RPC ist ein einfaches Protokoll für entfernte
Funktionsaufrufe über das Internet. Die XML-RPC Spezifikation, die
neben Beispielen auch eine FAQ enthält, paßt auf 7 DIN-A 4 Seiten
und wurde von Dave Winer von Userland verfaßt. XML-RPC ist leicht
zu verstehen und anzuwenden. Der Footprint einer XML-RPC
Implementierung kann sich auf wenige Kilobyte beschränken. Dies
macht XML-RPC auch für Mobile Web Services interessant.
XML-RPC ermöglicht entfernte Funktionsaufrufe über das HTTP
Protokoll. Für entfernte Funktionsaufrufe gibt es die Bezeichnung Remote
Procedure Call oder kurz RPC.
XML dient zur Codierung der Übergabeparameter an die entfernten
Proceduren. Daher der Name XML-RPC. XML-RPC ist sprachunabhängig,
Server und Clients können in beliebigen Sprachen wie Java, Perl
oder Ruby implementiert werden.
Ein Aufruf wird per HTTP-POST an den Server geschickt. Dieser
wertet das im Body enthaltene XML Dokument aus und verwendet
dessen Inhalt als Parameter für den Aufruf der gewünschten
Funktion. Das Ergebnis wird wieder in XML gepackt und zum Client übertragen.
Neben primitiven Datentypen wie String, Double und DateTime
werden auch komplexe Typen unterstützt, die aus den primitiven
Typen zusammengesetzt werden können.
Beispiel
Das Beispiel eines Warenkorbes verdeutlicht die Funktionsweise
und Entwicklung mit XML-RPC. Ein Server stellt eine Schnittstelle über
XML-RPC für den Zugriff auf ein Warenkorb-Objekt bereit. Zunächst
betrachten wir die HTTP Anfragen und Antworten, die ausgetauscht
werden. Weiter unten wird der für das Beispiel notwendige Code für
Client und Server erläutert.
Listing 1 zeigt den Request eines Clients. Wie aus der
ersten Zeile ersichtlich, wird der Request mit der HTTP
Methode POST an den Server übertragen. Als Empfänger wird der Context
/RPC2 verwendet. Der Body des Requests enthält ein XML
Dokument mit dem Root-Element "methodCall". Die
aufzurufende Methode wird über das Element "methodName"
angegeben. Die Schreibweise läßt vermuten, dass die Methode "addPosition"
auf ein Objekt "warenkorb" aufgerufen wird. Es handelt
sich bei der Angabe von "warenkorb" allerdings nicht um
eine Objektreferenz.
POST /RPC2 HTTP/1.0
User-Agent: Apache XML-RPC 1.0
Host: dchp174.oio.de
Content-Length: 221
Content-Type: text/xml
<?xml version="1.0"?>
<methodCall>
<methodName>warenkorb.addPosition</methodName>
<params>
<param><value>Dauerlutscher</value></param>
<param><value><int>10</int></value></param>
<param><value><double>0.38</double></value></param>
</params>
</methodCall>
Listing 1.) XML-RPC Request
Mit XML-RPC können nur Proceduren und keine Methoden aufgerufen
werden, da für den Aufruf einer Methode auch ein Objekt, auf dem
die Methode ausgeführt werden soll, übergeben werden muß. Der
Anbieter eines XML-RPC Web Services kann die entfernte Funktion
selbstverständlich auch über eine statische Methode realisieren.
Das nächste Element "params" enthält die Parameter
des Aufrufs. Parameter bekommen in XML-RPC keinen Namen. Allein die
Position eines Parameters entscheidet über dessen Bedeutung.
Beim Aufruf von "addPosition" wird die
Artikelbezeichnung, die Menge und der Preis übergeben.
Der Server nimmt die Anfrage entgegen und leitet den Aufruf an
die entsprechende Funktion bzw. Methode weiter. Die Antwort enthält,
wie Listing 2 zeigt, einen Wert, der die Anzahl der zum Warenkorb
hinzugefügten Positionen angibt.
HTTP/1.0 200 OK
Server: Apache XML-RPC 1.0
Connection: close
Content-Type: text/xml
Content-Length: 135
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value><int>1</int></value>
</param>
</params>
</methodResponse>
Listing 2.) Die Antwort des Servers
Über die Reihenfolge und Bedeutung der Parameter muss zwischen
Client und Server Einverständnis bestehen. Die Schnittstelle des
Servers kann nicht evolutionär verändert und erweitert werden.
Komplexe Typen
XML-RPC unterstützt die Übergabe von Parametern mit
zusammengesetzten Typen. Listing 3 zeigt eine Anfrage nach den
Positionen des Warenkorbes. Der Warenkorb kann mehrere Positionen
enthalten, die jeweils Artikel, Menge und Preis beinhalten.
POST /RPC2 HTTP/1.0
User-Agent: Apache XML-RPC 1.0
Host: dchp174.oio.de
Content-Length: 67
Content-Type: text/xml
<methodCall>
<methodName>warenkorb.getPositionen</methodName>
</methodCall>
Listing 3.) Frage nach dem Inhalt des
Warenkorbes
Abbildung 1 zeigt, wie die Positionen des Warenkorbes mit den in
XML-RPC zur Verfügung stehenden Datentypen abbgebildet werden können.
Ein übergeordnetes Array nimmt jeweils ein Arry für eine Position
und deren Werte auf.
Abbildung 1.) Positionen des Warenkorbes als Parameter
HTTP/1.0 200 OK
Server: Apache XML-RPC 1.0
Connection: close
Content-Type: text/xml
Content-Length: 405
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value>
<array>
<data>
<value>
<array>
<data>
<value>Lutscher</value>
<value><int>10</int></value>
<value><double>0.39</double></value>
</data>
</array>
</value>
<value>
<array>
<data>
<value>Tee</value>
<value><int>2</int></value>
<value><double>3.98</double></value>
</data>
</array>
</value>
</data>
</array>
</value>
</param>
</params>
</methodResponse>
Listing 4.) Ausgabe des Warenkorbes
Unterstütze Datentypen
XML-RPC unterstützt die in Tabelle 1. aufgeführten Datentypen.
|
Datentyp
|
Beschreibung
|
Beispiel
|
|
boolean
|
Ein Bit.
|
true, false
|
|
int
|
32 Bit Integer mit Vorzeichen
|
10, -10, 0
|
|
double
|
Fliesskommazahl mit doppelter Präzision
|
-94.4, -0.5, 0.74
|
|
string
|
Zeichenkette
|
Hossa, Bar, Foo
|
|
dateTime.iso8601
|
Zeit und Datum
|
20021105T14:14:55
|
|
array
|
Eindimensionales Array. Der Typ der Werte ist beliebig
|
|
|
struct
|
Schlüssel-Wert Paare. Der Schlüssel ist ein string, der Wert kann von beliebigem Typ sein. Structs in XML-PRC entsprechen Maps oder Hashtables in Java.
|
|
|
base64
|
Base64 encodierte Binärdaten
|
|
Tabelle 1.) Datentypen
Fehlerbehandlung
Fehlermeldungen, die bei der Ausführung eines Requests
auf dem Server auftreten, können dem Client wie Listing 5 zeigt mit
einem fault-Element übergeben werden. Das fault-Element enthält
ein Struct mit Fehlercode und Fehlerbeschreibung. Im Beispiel
wird eine Java Exception in das fault-Element eingepackt.
Der HTTP Status Code ist auch im Fehlerfall "200
OK". Nur im Body der Nachricht ist der Fehler erkennbar. Für
das Fehlerhandling wurde nicht auf die Mechanismen von HTTP zurückgegriffen,
sondern mit dem fault-Element etwas eigenes geschaffen.
<?xml version="1.0"?>
HTTP/1.0 200 OK
Server: Apache XML-RPC 1.0
Connection: close
Content-Type: text/xml
Content-Length: 317
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultString</name>
<value>java.lang.StringIndexOutOfBoundsException:
String index out of range: -1</value>
</member>
<member>
<name>faultCode</name>
<value><int>0</int></value>
</member>
</struct>
</value>
</fault>
</methodResponse>
Listing 5.) Fehlermeldung
Beispiel XML-RPC mit Java
Das folgende Codebeispiel wurde für die Implementierung Apache
XML-RPC geschrieben. Für XML-RPC gibt es kein standardisiertes API
wie z.B. JAX-RPC für SOAP. Jede Implementierung verwendet ihre
eigenen Schnittstellen und Klassen.
Betrachten wir zunächst den Code für den Server. Der Server
besteht aus einer main-Methode und einer normalen Java Klasse, die
den Warenkorb implementiert.
Im Code in Listing 6 wird ein kleiner Webserver gestartet, der
von Apache XML-RPC mitgeliefert wird. An den Namen "warenkorb"
wird anschließend ein Objekt vom Typ Warenkorb gebunden.
public class Server {
public static void main(String args[]) throws IOException {
Warenkorb warenkorb = new Warenkorb();
WebServer webserver = new WebServer( 5555);
webserver.addHandler("warenkorb", warenkorb);
}
}
Listing 6.) XML-PRC Server
Bei der Implementierung des Warenkorbes handelt es sich um eine
normale Java Klasse, die in Listing 7 abgedruckt ist. Das einzige
XML-RPC spezifische an dieser Klasse ist die Methode "getPositionen",
die den Rückgabewert in Vektoren einpackt, so dass XML-RPC diese in
die Rückgabestruktur packen kann.
public class Warenkorb {
private Vector positionen = new Vector();
public int addPosition( String ware, int menge, double preis) {
positionen.add( new Position( ware, menge, preis));
return 1;
}
public Collection getPositionen() {
Vector ret = new Vector();
Iterator positionIter = positionen.iterator();
while( positionIter.hasNext()) {
ret.add(((Position)positionIter.next()).getParams());
}
return ret;
}
}
Listing 7.) Implementierung des Warenkorbes
Jetzt fehlt noch der Client, der die Methoden der Klasse
Warenkorb über das Netz aufruft. Im Listing 8 wird ein Vector
mit den Übergabeparametern gefüllt, die beim Aufruf übergeben
werden. Der Aufruf erfolgt über eine Klasse "XmlRpcClient",
die mit der Adresse des Servers initialisiert wurde. Beim Aufruf des
Servers mit der Methode execute wird der Funktionsname auf dem
Server und die Parameter übergeben.
XmlRpcClient xmlrpc = new XmlRpcClient("http://hermes.oio.de:5555/RPC2");
Vector params = new Vector();
params.addElement( "Lutscher");
params.addElement( new Integer(10));
params.addElement( new Double( 0.39));
xmlrpc.execute("warenkorb.addPosition", params);
Listing 8.) XML-RPC Client
Performance
Es liegt die Vermutung nahe, dass die Verarbeitung der in XML
codierten Nachrichten viel Zeit in Anspruch nimmt und daher die
Performance stark beeinträchtigt wird. Die Struktur der Nachrichten
ist im Gegensatz zu SOAP Messages einfach. Es fehlen u.a. Angaben für
Namespaces und für das Encoding. Das Parsen der XML Nachrichten
kann über kompakte und schnelle Parser geschehen, die weder
Namespaces, noch Attribute oder DTDs kennen. In der Praxis ist daher
XML-RPC recht performant. Die Roundtrip-Zeiten für entfernte
Aufrufe liegen meist bei wenigen Millisekunden. Der Speicher und CPU
Verbrauch für XML-RPC ist aufgrund der Größe zu vernachlässigen.
Implementierungen
Zahlreiche XML-RPC Implementierungen sind für Unix, Linux,
Windows und Mac verfügbar. Die Liste zählt nur wenige der verfügbaren
Implementierungen auf. Allein für PHP sind mehr als fünf
Implementierungen verfügbar.
Apache XML-RPC
Apache XML-RPC ist eine kompakte Implementierung für Java. Zusätzlich
zum Standard gibt es Erweiterungen für Servlets und SSL. Ein Web
Container wie Jakarta Tomcat kann als Server dienen oder es kann ein
eingebauter spezieller HTTP Server verwendet werden.
Für die Einbindung von Apache XML-RPC genügt ein 57 KByte
grosses Jar-File, welches bereits den XML Parser MinML enthält.
Apache XML-RPC eignet sich aufgrund der geringen Größe auch für
den mobilen Einsatz auf dem Handy mit der Java Micro Edition.
Anwendungen mit XML-RPC Unterstützung
Eine Reihe von Anwendungen bietet Schnittstellen über XML-RPC
an. Neben den Produkten von Userland wie Frontier, Manila und Radio
unterstützen Zope oder KDE ebenfalls XML-RPC.
Grenzen von XML-RPC
XML-RPC Implementierungen verwenden oft kleine kompakte XML
Parser wie MinML. Nicht immer kann davon ausgegangen werden, dass
der verwendete Parser auch Unicode unterstützt.
Für XML-RPC gibt es keine Schnittstellenbeschreibungen im Stil
von WSDL oder CORBA IDL. Proxys für den Zugriff auf den Server können
daher nicht automatisiert erzeugt werden.
Bei vielen Implementierungen müssen Objekte von Hand in
Strukturen aus Arrays und Struts (Maps oder Hashtables) übersetzt
werden. Das automatische Serialisieren hat seine Grenzen.
XML-RPC ist als endgültiger Standard anzusehen, der sich in nächster
Zeit nicht mehr weiter entwickeln wird.
Fazit
Kommunikationspartner in anderen Organisationen, die Dienste
bereitstellen oder Dienste verwenden möchten, beeinflussen neben
den zur Verfügung stehenden Entwicklungstools die Entscheidung für
ein Webservice Protokoll. Im Online-Publishing, bei Weblogs und
Microcontent ist XML-RPC stark vertreten, während SOAP im eBusiness
Umfeld dominiert.
Die Schlankheit und Unkompliziertheit von XML-RPC ist zugleich
Vorteil und Nachteil. Wer schnell und unkompliziert Web Services
realisieren möchte, sollte das Protokoll XML-RPC ins Auge fassen.
Ressourcen
XML-RPC Home Page
XML-RPC Homepage bei Userland
Apache
XML-RPC
Die Implementierung von Apache
MinML
a minimal XML parser
Kleiner kompakter XML Parser, der in ein 14 KByte Jar passt
Unicode
support in XML-RPC libraries
Tabelle, die XML-RPC Implementierungen und ihre Unterstützung für
Unicode auflistet
|