Im Zusammenhang mit SOAP und Web Services ist meist nur von Java und .NET als Entwicklungsumgebungen die Rede. Während für einige die .NET-Welt aus Glaubensgründen ausscheidet, gestaltet sich die Entwicklung mit Java recht aufwändig. Da müssen Pakete im dreistelligen MB-Bereich geladen und anschließend konfiguriert werden. So stellte der Autor des Beitrags Bestell Service (XML Magazin 01.2002) in seinem Fazit fest, dass der meiste Aufwand in der Bereitstellung und Konfiguration der Umgebung liegt [1].
Genau hier verspricht das Open Source-Toolkit SOAP::Lite Abhilfe, trägt es den Lite-Gedanken doch schon in seinem Namen. Möglich ist dies durch eine Reihe von Weiterentwicklungen, welche Perl in den letzten Jahren erfahren hat, die jedoch, wie ich in einigen Gesprächen feststellen musste, weithin gar nicht bekannt sind. Perl kämpft mit dem verbreiteten Vorurteil, nur für einfache Skripte und CGI-Programmierung zu taugen. Da die Basics einfach zu erlernen sind, kann damit praktisch jeder programmieren, was sich dann wieder negativ auf die Qualität der Programme auswirkt. Mittlerweile hat sich die Perl-Gemeinde des Themas Idiotic Perl angenommen und versucht hier Aufklärungsarbeit zu leisten. An erster Stelle der erwähnten Weiterentwicklungen von Perl ist die Objektorientierung zu nennen. Perl verfügt über die meisten Merkmale objektorientierter Sprachen. Somit erlaubt es die Entwicklung umfangreicher objektorientierter Frameworks, wozu auch SOAP::Lite gerechnet werden kann. Die zweite wichtige Neuerung (obwohl auch schon einige Jahre alt) ist die Unterstützung von Unicode. Damit wurde die Verarbeitung von XML möglich. Einzigartig ist das CPAN, das Comprehensive Perl Archive Network, welches nicht nur eine zentrale Sammlung von Perl-Modulen darstellt, sondern darüber hinaus noch ein einheitliches Verfahren zur Installation von Perl-Modulen definiert. Der Begriff Modul steht in der Perl-Welt sowohl für eine einzelne Datei (die eine oder mehrere Klassen enthalten kann) als auch für ganze Klassenbibliotheken.
Zurück zu SOAP::Lite. Zu dessen Features gehören die Unterstützung von SOAP 1.1 und SOAP 1.2, verschiedenen Transportprotokollen (FTP, HTTP, IO, Jabber, SMTP, POP3, TCP und MQSeries) und neben SOAP auch XML-RPC als Protokoll. Auf der zugehörigen Website [2] findet man eine Auflistung aller Merkmale. Für Windows existieren verschiedene .dll-Dateien und eine Reihe von Beispielen für COM, .NET, VB, C# usw. Von der Homepage oder vom CPAN [3] kann die Software heruntergeladen werden. Die Installation unter Unix erfolgt dann nach dem CPAN-Strickmuster:
perl Makefile.PLmakemake testmake install
perl -MCPAN -e shell> install <i>SOAP::Lite</i>
Die folgenden Beispiele beschränken sich auf HTTP als Transportprotokoll. Beginnen wir mit einem einfachen Client aus den Beispielprogrammen (client.pl). Die Programme sind in der Distribution enthalten oder können von guide.soaplite.com heruntergeladen werden Die Methode uri enthält den Namespace des Services, die Methode proxy die Adresse. In diesem Fall wird mit hibye.cgi ein CGI-Script aufgerufen:
#!perl -wuse <i>SOAP::Lite</i>;print <i>SOAP::Lite</i>-> uri('http://www.soaplite.com/Demo')-> proxy('http://localhost/cgi-bin/hibye.cgi')-> hi()-> result;
1 #!perl -w2 use SOAP::Transport::HTTP;34 SOAP::Transport::HTTP::CGI5 -> dispatch_to('Demo')6 -> handle;78 package Demo;9 sub hi {10 return "hello, world";11 }12 sub bye {13 return "goodbye, cruel world";14 }
Die hier gewählte Syntax weicht von der üblichen Form ab. Statt mit einem Konstruktoraufruf ein Objekt zu erzeugen und dann nacheinander dessen Methoden aufzurufen, können hier jede Methode der Klasse aufgerufen und weitere Methodenaufrufe aneinandergehängt werden (mit dem -> Operator). Returnwert ist immer das mit der ersten Methode erzeugte Objekt. Für Perl-Liebhaber bietet der Source von SOAP::Lite einige Beispiele zum Thema Codegenerierung.
Um die Performance zu verbessern, werden wir als nächstes den Server nicht als CGI-Programm ausführen, sondern vom Apache selbst mit Hilfe des Perl-Interpreters aus mod_perl. Dies vermeidet das Starten eines neuen Prozesses und das Kompilieren des Programms bei jedem Request. Voraussetzung hierfür ist, dass Apache mit mod_perl kompiliert wurde. Unter perl.apache.org findet man die notwendige Software und die Dokumentation zur Installation. Viele Linux-Distributionen enthalten bereits einen entsprechenden Apache. Zur Installation unseres Web Services sind dann vier Schritte notwendig: Zuerst muss man einen Apache-Handler schreiben. Das ist nicht besonders schwierig, wie der folgende Quellcode zeigt:
1 package My::SOAP::Apache;2 use SOAP::Transport::HTTP;34 my $server = SOAP::Transport::HTTP::Apache5 -> dispatch_to('Demo')67 sub handler { $server->handler(@_) }89 1;
<i>dispatch_to('Demo', 'My::SOAP::PLZ','My::SOAP::XY::func1')</i>
Schritt 2 ist die Konfiguration von Apache, hierzu muss die httpd.conf-Datei noch angepasst werden:
<Location /soap>SetHandler perl-scriptPerlHandler My::SOAP::Apache</Location>
#!perl -wuse <i>SOAP::Lite</i>;print <i>SOAP::Lite</i>-> uri('http://www.soaplite.com/Demo')-> proxy('http://localhost/soap')-> hi()-> result;
1 #!perl -w23 use <i>SOAP::Lite</i> +autodispatch =>4 uri => 'http://www.soaplite.com/Temperatures',5 proxy => 'http://localhost/cgi-bin/temper.cgi';67 my $temperatures = Temperatures->new(100);8 print $temperatures->as_fahrenheit;
Serialisierung, Typen und Namen
Perl ist eine typenlose Sprache, daher gestaltet sich für Perl bei einfachen Datentypen die Serialisierung/Deserialisierung recht einfach. Befindet sich der Serialisierer im autotype-Modus, wandelt er die Parameter nach sinnvollen Regeln um. Eine Variable mit dem Wert abc bekommt den Typ string, eine Variable mit dem Wert 123 den Typ int, ein Hash wird in den Typ SOAPStruct umgewandelt usw. Das Autotyping kann ganz abgeschaltet werden oder man kann zu jeder Variablen den zugehörigen Typ mit angegeben. Dazu wird ein Objekt vom Typ SOAP::Data erzeugt und übergeben. Soll eine Variable mit einem Wert 123 als String übergeben werden muss statt$soap->function(123)$soap->function (SOAP::Data->type(string=>123) )
$soap->function (SOAP::Data->type(string=>123) ->name('myvar') )
Serialisierer und Deserialisierer können durch eigene Klassen überschrieben werden. Dazu muss nur eine Unterklasse von deserializer/serializer entwickelt werden und bei der Erzeugung des Server-Objekts (bzw. des Clients, wenn dort ein eigener Serializer verwendet wird) angegeben werden:
use SOAP::Transport::HTTP;my $server = SOAP::Transport::HTTP::Apache-> new (LocalPort => 80)# register deserializer-> deserializer(MyDeserializer->new)-> dispatch_to(...)
Interoperabilität
Die Dokumentation beschreibt eine Reihe von Clients für den Zugriff auf vorhandene Services, welche mit anderen Toolkits erstellt wurden. Am Beispiel eines .NET-Services sollen die notwendigen Anpassungen gezeigt werden. Services unter .NET erwarten zum einen benamte Parameter. Wie diese erzeugt werden, wurde schon beschrieben. Weiterhin verlangt .NET das Header-Feld SOAPAction in der Form service namespace, gefolgt von einem Slash, gefolgt vom Methodennamen. SOAP::Lite trennt Namespace und Methodenname jedoch durch ein #. Die notwendige Anpassung ist recht einfach (siehe Listing 2). Der Methode on_action wird ein Perl-Codeblock übergeben, in welchem die notwendigen Anpassungen durchgeführt werden. Mit der Anweisung sub {...} wird eine anonyme Subroutine erzeugt, welche mit der Funktion sprintf die übergebenen Parameter formatiert. Andere Server verlangen hier gegebenenfalls andere Formate. Dies ist ein schönes Beispiel für die Anpassungsfähigkeit von SOAP::Lite durch Eigenschaften der Sprache Perl.Mehr Informationen zum Thema Interoperabilität findet sich unter [5], Ergebnisse zu SOAP::Lite unter [6]. Listing 2
use SOAP::Lite;my $name = shift;print "\n\nCalling the SOAP Server to say hello\n\n";print "The SOAP Server says: ";print SOAP::Lite-> uri('urn:Example1')->on_action(sub{sprintf '%s/%s', @_ })->proxy('http://localhost:8080/helloworld/example1.asmx')->sayHello(SOAP::Data->name(name => $name)->type->('string')->uri('urn:Example1'))->result . "\n\n";
WSDL
SOAP::Lite unterstützt auch WSDL. Um einen Service zu verwenden, genügt dann die Angabe der URL:use SOAP::Liteservice => 'http://www.xmethods.net/sd/StockQuoteService.wsdl';print getQuote('MSFT'), "\n";
In der Dokumentation wird darauf hingewiesen, dass komplexe Datentypen noch nicht funktionieren. Mit dem mitgelieferten Programm stubmaker.pl können Stubs erzeugt werden. Damit wird nichts anderes als ein Perl-Modul mit dem entsprechenden Namen erzeugt, welches dann wie andere Module mit use verwendet werden kann. Der Aufruf von
perl stubmaker.pl http://www.xmethods.net/sd/StockQuoteService.wsdl<i></i>
Fehlerbehandlung
Fehler bei SOAP-Requests können sowohl beim Transport als auch in der Anwendung selbst liegen. SOAP::Lite bietet hier mehrere Varianten der Fehlerbehandlung. Standardmäßig beendet sich ein Client bei einem Transportfehler mit der Fehlermeldung und ignoriert Anwendungsfehler. Um einen solchen festzustellen, muss daher die fault)=-Methode des Result-Objekts verwendet werden:...my $result = $soap->hi();unless ($result->fault) {print $result->result();} else {print join ', ',$result->faultcode,$result->faultstring;}
my $soap = <i>SOAP::Lite</i>-> uri('http://www.soaplite.com/Temperatures')-> proxy('http://services.soaplite.com/temper.cgi')-> on_fault(sub { my($soap, $res) = @_;die ref $res ? $res->faultstring : $soap->transport->status, "\n";});
sub my_method {# do something herereturn $result if $everything_is_ok;die "Something bad happened\n";}sub die_with_fault {die SOAP::Fault->faultcode('Server.Custom') # Server->faultstring('Died in server method') # Application error->faultdetail(bless {code => 1} => 'BadError')->faultactor('http://www.soaplite.com/custom');}
Fazit
SOAP::Lite ist ein recht umfangreiches Toolkit zur Entwicklung von Clients und Servern für Web Services. Die Verwendung leistungsfähiger Module aus dem CPAN wie HTTP::Cookie oder LWP::UserAgent sowie die modulare Architektur ergeben zusammen mit Eigenschaften von Perl wie anonyme Subroutinen ein sehr flexibles und leistungsfähiges System. Die Dokumentation beschreibt eine Reihe weiterer Features von SOAP::Lite wie Zugriff über SSL, Authentifizierung, Cookies usw. Im Cookbook werden weitere Anwendungsfälle beschrieben, wie das Einfügen eines eigenen Header-Feldes, Zugriff auf den Envelope und natürlich auch die Verwendung von XML-RPC statt SOAP. Die aktuelle Versionsnummer 0.58 sollte niemanden vor dem Einsatz zurückschrecken: Der Code ist sehr stabil und Perl-Autoren sind generell sehr zurückhaltend mit der Vergabe einer 1.* Version.Der Autor ist freiberuflicher Softwareentwickler und arbeitet am liebsten mit Perl. Zu erreichen ist er unter rolf.schaufelberger@web.de.
Links und Literatur
- [1] XML-Magazin 01.2002, S.18
- [2] Soap-Lite Homepage: www.soaplite.com/
- [3] www.perl.com/CPAN/
- [4] Alles zu mod_perl und Apache: perl.apache.org/
- [5] www.xmethods.com/ilab/
- [6] interop.soaplite.com/
- [7] Perl Homepage: www.perl.com/
- [8] Perl für Windows: www.activestate.com/




