Technologien

Werbung
Technologien
Einleitung
Dieses Dokument soll einen Einblick in die Technologien geben, die in den Tutorials
angewendet werden. Natürlich werden alle Themen nur kurz angesprochen und für tieferes
Hintergrundwissen wird das Durcharbeiten entsprechender Literatur empfohlen.
@Autor Andre Haferkorn
Inhaltsverzeichnis
1
XML__________________________________________________ 1
1.1
Aufbau von XML______________________________________________
1.2
XML-Namespaces ____________________________________________
1.3
XML Schema (XSD) ___________________________________________
1.3.1
XSD Simple Type __________________________________________
1.3.2
XSD Complex Type ________________________________________
1.3.3
XML Schema und Namespaces _______________________________
1.3.4
XML-Dokumente mit XML Schema_____________________________
1.4
Verarbeitung von XML _________________________________________
1.4.1
DOM ____________________________________________________
1.4.2
SAX ____________________________________________________
1.4.3
JAXP ____________________________________________________
2
2.1
2.2
3
3.1
3.2
4
1
1
2
3
3
3
4
5
5
6
7
WSDL ________________________________________________ 9
Was ist WSDL ________________________________________________ 9
Aufbau von WSDL-Dokumenten _________________________________ 9
SOAP _______________________________________________ 11
Was ist SOAP _______________________________________________ 11
Aufbau von SOAP ___________________________________________ 11
AXIS ________________________________________________ 12
4.1
Was ist Axis ________________________________________________
4.2
Web Services mit Axis ________________________________________
4.2.1
Web Services erstellen als Java Web Service (jws) _______________
4.2.2
Web Service erstellen mit WSDD _____________________________
4.2.3
Web Service erstellen als Web Applikation______________________
4.3
Axis und WSDL _____________________________________________
4.3.1
Java2WSDL _____________________________________________
4.3.2
WSDL2Java _____________________________________________
12
12
12
13
14
15
15
15
1 XML
Dieses Tutorial soll kein Handbuch für XML darstellen. Dafür gibt es genügend Bücher. An
dieser Stelle werden nur die Grundlagen für die weiteren Beispiele gelegt.
1.1 Aufbau von XML
XML steht für Extensible Markup Language und ist ein Standard zur Erstellung strukturierter
Dokumente. ‚Strukturiert’ bedeutet, dass die Teile des Dokumentes, die Elemente, einer
Baumstruktur folgen. Jeder Teil dieses Baumes, von der Wurzel (Root-Element) bis zu den
Blättern (Text-Wert) stellt einen Knoten dar (node). Ein Knoten kann weitere Knoten, so
genannte Kindknoten (child nodes), beinhalten. Der Elternknoten (parent node) gruppiert die
Kindknoten durch Umschließen mit einem Start-Tag <element> und einem End-Tag
</element>. Die Tags wirken dabei als eine Art Klammern. Das äußerste Klammernpaar ist
die Wurzel. In einem wohlgeformten XML-Dokument darf es nur einen Wurzelknoten geben.
Das folgende XML-Dokument verdeutlicht den Zusammenhang. In diesem Beispiel ist
<Person> der Wurzelknoten und <Name>, <Adresse> und <Telefon> sind dessen
Kindknoten.
<?xml version="1.0" encoding="UTF-8"?>
<Person>
<Name>Max Mustermann</Name>
<Adresse>Hauptstr. 1, 01234 Irgendwo</Adresse>
<Telefon>+49/321/123456-100</Telefon>
</Person>
1.2 XML-Namespaces
Die oben verwendeten Elemente-Namen sind Weltweit nicht eindeutig. So gibt es sicher
Firmen, die eine Person anders definieren würden. Um den Element-Namen eindeutig zu
machen, wird er um einen (weltweit) eindeutigen Bezeichner, den Namespace (z. B.
http://my-domain.com/Person), erweitert. Der Namespace ist hierbei nichts weiter als eine
Zeichenkette. Üblicherweise wird der String in Form einer URL verwendet, denn durch diese
ist die Eindeutigkeit gewährleistet – der Domain-Anteil ist immer nur einer bestimmten
Organisation/Person zugeordnet. Außerdem wird oft an die Stelle, auf die der Link verweist
die genaue Spezifikation der Dokumentenstruktur hinterlegt.
Es kann nun passieren, dass in einem XML-Dokument gleiche Element-Namen von
unterschiedlichen Organisationen verwendet werden. Deshalb empfiehlt es sich bei der
Verwendung eines Elements immer den Namespace mit anzugeben. Im obigen Fall würden
die Elemente-Namen dadurch recht lang werden. Deshalb gibt es Namespace-Präfixe. Diese
müssen nur Dokumentweit eindeutig sein und können deshalb viel kürzer sein. Ein
Dokument, dessen Elemente Namespace-Präfixe verwenden, kann z. B. so aussehen.
<?xml version="1.0" encoding="UTF-8"?>
<myns:Person xmlns:myns="http://my-domain.com/Person">
<myns:Name>Max Mustermann</myns:Name>
<myns:Adresse>Hauptstr. 1, 01234 Irgendwo</myns:Adresse>
<myns:Telefon>+49/321/123456-100</myns:Telefon>
</myns:Person>
1
Gibt es nur einen Namespace im gesamten Dokument (bzw. für einen Elternknoten und seine
Kindknoten) so kann ein Default-Namespace im Wurzel-Knoten (bzw. im jeweiligen
Elternknoten) in der Form xmlns="Namespace-URI" festgelegt und auf die Angabe von
Präfixen verzichtet werden.
<?xml version="1.0" encoding="UTF-8"?>
<Person xmlns="http://my-domain.com/Person">
<Name>Max Mustermann</Name>
<Adresse>Hauptstr. 1, 01234 Irgendwo</Adresse>
<Telefon>+49/321/123456-100</Telefon>
</Person>
1.3 XML Schema (XSD)
XSD steht für XML-Schema Definition (oder kurz XML Schema). Ein XML Schema ist ein
XML-Dokument, das Meta-Informationen über den Aufbau einer XML-Datei beinhaltet. Eine
XSD-Datei kann man sich also als eine Art Klasse vorstellen, in der Eigenschaften und deren
Struktur definiert werden. Die mit dem XML Schema erstellten XML-Dokumente sind dann
sozusagen Instanzen dieser Klasse, in denen den Eigenschaften konkrete Werte zugewiesen
werden. Nur wenn die Eigenschaften, deren Werte und die Struktur des XML-Dokumentes
den Vorgaben des XML Schemas entsprechen, spricht man von einem gültigen (valid) XMLDokument. Das im letzten Abschnitt gezeigte Beispiel könnte z. B. eine Instanz des folgenden
XML Schemas sein.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="Adresse" type="xsd:string"/>
<xsd:element name="Telefon" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Die Angabe des Namespace für das XML Schema zeigt, dass es sich bei dieser Datei um ein
XML Schema handelt, denn eigentlich ist es ja auch nur ein (gewöhnliches) XML-Dokument.
Die für das Schema verfügbaren Elemente und deren Struktur werden hier jedoch nicht durch
ein (weiteres) XML Schema, sondern durch eine Spezifikation des W3C festgelegt. XMLEditoren sowie XML-Parsern müssen die Regeln dieser Spezifikation bekannt sein.
In der XSD-Datei wurden als Typen für die Elemente, bis auf das Root-Element, nur der
primitive XSD-Datentyp xsd:string verwendet. Gerade bei der Telefonnummer wäre eine
gewisse Einschränkung der Zeichen wünschenswert. XML Schema bietet deshalb die
Möglichkeit eigene Datentypen zu erstellen. Dabei wird zwischen ‚einfachen’ (simple) und
‚komplexen’ (complex) Datentypen unterschieden.
2
1.3.1 XSD Simple Type
Eine Telefonnummer folgt immer einem bestimmten Format. Es wäre wünschenswert, wenn
der Leser (das kann auch eine Maschine sein) in einem XML-Dokument auch nur
Telefonnummern vorfindet, die diesem Format entsprechen. Ein solches Format kann zum
Beispiel als xsd:simpleType definiert sein.
<xsd:simpleType name="TelefonType">
<xsd:restriction base="xsd:token">
<xsd:pattern value="((([0]{2}|[+])[0-9]{2}([/]|[ ]))|[0])([1-9]{2,5}([/]|[ ])[0-9]{3,}([-][0-9]+)?)"/>
</xsd:restriction>
</xsd:simpleType>
Mit dem Element xsd:pattern wird das Format der Telfonnummer festgelegt. Der Wert
eines Elementes, das diesen Datentyp verwendet, kann z. B. folgender sein: 0321 123456.
1.3.2 XSD Complex Type
xsd:comlexType entspricht einer Datenstruktur (in Programmiersprachen unter dem Begriff
struct bekannt). Ein Element mit einem komplexen Datentyp kann Kindelemente
primitiver, einfacher oder komplexer Datentypen enthalten. Der komplexe Datentyp für eine
Person wurde ja bereits in einem Beispiel gezeigt. Auch für den komplexen Datentyp kann
das Attribut name gesetzt werden, um diesen Datentyp mehrfach im XML Schema zu
verwenden.
<xsd:complexType name="PersonType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="Adresse" type="xsd:string"/>
<xsd:element name="Telefon" type="TelefonType"/>
</xsd:sequence>
</xsd:complexType>
1.3.3 XML Schema und Namespaces
Im Kapitel 1.2 wurde bereits der Begriff Namespace erklärt. So können mehrdeutige
Elemente-Namen wie Person durch Angabe eines Namespace (weltweit) eindeutig gemacht
werden. Bei den bisherigen XSD-Beispielen wurde auf die Verifizierung eines Namespace
verzichtet. Um den Namespace des Ziel-XML-Dokumentes zu berücksichtigen (hier war dies
http://my-domain.com/Person) muss für ein XSD-Dokument ein Target-Namespace
festgelegt werden. Um diesen Namespace für Datentypen innerhalb des XML Schemas zu
verwenden, muss außerdem ein Namespace-Präfix für den Target-Namespace festgelegt
werden. Es muss auch festgelegt werden, dass nur qualifizierte Elemente-Namen (ElementeNamen für die ein Namespace festgelegt wurde) akzeptiert werden.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://my-domain.com/Person"
xmlns:typesns="http://my-domain.com/Person"
elementFormDefault="qualified">
...
3
1.3.4 XML-Dokumente mit XML Schema
Um ein XML-Dokument gegen ein XML Schema validieren zu können, muss der Ort des
Schemas in der XML-Datei angegeben werden. Dafür sind zwei Attribute interessant, die aus
dem Namespace http://www.w3.org/2001/XMLSchema-instance (Präfix: xsi) hervorgehen:
xsi:noNamespaceSchemaLocation und xsi:schemaLocation. Bei Verwendung des
Attributs xsi:noNamespaceSchemaLocation wird der Namespace bei der Validierung
nicht berücksichtigt. Bei Verwendung des Attributs xsi:schemaLocation wird der
Namespace bei der Validierung berücksichtigt und muss entsprechend angegeben werden. Im
Folgenden werden die beiden Dateien Person.xml und Person.xsd dargestellt.
XML Schema (Person.xsd)
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema targetNamespace="http://my-domain.com/Person"
xmlns:typesns="http://my-domain.com/Person"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:element name="Person" type="typesns:PersonType"/>
<xsd:complexType name="PersonType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="Adresse" type="xsd:string"/>
<xsd:element name="Telefon" type="typesns:TelefonType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="TelefonType">
<xsd:restriction base="xsd:token">
<xsd:pattern value="…"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
XML Schema Instanz (Person.xml)
<?xml version="1.0" encoding="UTF-8"?>
<Person
xmlns="http://my-domain.com/Person"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://my-domain.com/Person Person.xsd">
<Name>Max Mustermann</Name>
<Adresse>Hauptstr. 1, 01234 Irgendwo</Adresse>
<Telefon>+49/321/123456-100</Telefon>
</Person>
In diesem Beispiel wird bei der Validierung der Namespace mit berücksichtigt. Befinden sich
außerdem beide Dateien im selben Verzeichnis, ist es nicht nötig den Pfad der XSD-Datei
explizit festzulegen.
4
1.4 Verarbeitung von XML
Nachdem im vorhergehenden Kapitel die Struktur von XML dargestellt wurde, wie sie der
Mensch sieht, wird in diesem Kapitel auf die Verarbeitung von XML-Dateien durch die
Maschine eingegangen.
1.4.1 DOM
DOM steht für Document Object Model. DOM ist schon seit langen aus der xHTML-Welt
bekannt. Dort dient DOM zum dynamischen Ändern von HTML-Seiten mit Hilfe von
JavaScript-Funktionen. DOM ist also eine API, die festlegt, wie auf xHTML-Dokumente und
XML-Dokumente zugegriffen werden kann, und wie sie verändert werden können.
Das zentrale Element bei DOM ist der Knoten (Node). Durch Hinzufügen von Knoten zu
einem bereits existierenden (Root-) Knoten kann eine beliebige Baumstruktur erstellt werden.
Auf XML angewendet bedeutet dies, dass jedes Element ein Knoten vom Typ Element ist.
Das Beispiel aus dem vorhergehenden Abschnitt kann also auch als Baumstruktur dargestellt
werden.
Document>#document
+ Element>Person
Attr>xmlns:myns=http://my-domain.com/Person
Attr>xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
Attr>xsi:noNamespaceSchemaLocation=Person.xsd
+ Element>Name
+ Text>#text=Max Mustermann
+ Element>Adresse
+ Text>#text=Hauptstr. 1, 01234 Irgendwo
+ Element>Telefon
+ Text>#text=+49/321/123456-100
Neben dem Knotentyp Element gibt es in DOM noch 11 weiter Kontentypen. Drei davon
sind ebenfalls in der Baumdarstellung enthalten: der Dokumentknoten (Document),
Attributknoten (Attr) und Textknoten (Text).
Textknoten sind besonders tückisch, da sie sich zwischen die Tags schleichen und oft nicht
zum Inhalt gehören, sondern dafür sorgen, dass das Dokument ‚schön’ gelesen werden kann.
XML-Editoren bieten dafür meist die Funktion Pretty-Print an. Um diese Formatierungen
(hauptsächlich sind das zusätzliche Leerzeichen, Tabulatoren und Zeilenumbrüche) wieder zu
entfernen, kann das XML-Dokument ‚normalisiert’ (normalize) werden. Normalize ist
sozusagen das Gegenteil zu Pretty Print. Das XML-Dokument besteht dann aus nur einer
Zeile – was das Lesen für den Menschen erschwert.
Mit Programmiersprachen oder Frameworks, die sich an die DOM-Spezifikation halten, kann
dank der DOM-API in ähnlicher Weise auf XML-Strukturen zugegriffen werden. Das wird im
folgenden Beispiel deutlich. Da wird die XML-Baumstruktur des obigen Beispiels einmal mit
JavaScript-Befehlen und zum anderen mit Java-Befehlen erstellt. Beeindruckend ist, dass
obwohl beide Sprachen außer dem Namen (‚Java’) nicht viel gemein haben, der Quellcode
aufgrund der DOM-API fast identisch ist.
5
JavaScript
var root = xmldoc.createElement("Person");
root.setAttribute("xmlns","http://my-domain.com/Person");
var name = xmldoc.createElement("Name");
name.appendChild(xmldoc.createTextNode("Max Mustermann"));
root.appendChild(name);
var adresse = xmldoc.createElement("Adresse");
adresse.appendChild(xmldoc.createTextNode("Hauptstr. 1, 01234 Irgendwo"));
root.appendChild(adresse);
var telefon = xmldoc.createElement("Telefon");
telefon.appendChild(xmldoc.createTextNode("+49/321/123456-100"));
root.appendChild(telefon);
xmldoc.appendChild(root);
Java
Element root =xmldoc.createElement("Person");
root.setAttribute("xmlns","http://my-domain.com/Person");
Element name = xmldoc.createElement("Name");
name.appendChild(xmldoc.createTextNode("Max Mustermann"));
root.appendChild(name);
Element adresse = xmldoc.createElement("Adresse");
adresse.appendChild(xmldoc.createTextNode("Hauptstr. 1, 01234 Irgendwo"));
root.appendChild(adresse);
Element telefon = xmldoc.createElement("Telefon");
telefon.appendChild(xmldoc.createTextNode("+49/321/123456-100"));
root.appendChild(telefon);
xmldoc.appendChild(root);
Ein Vorteil von DOM ist, dass nach dem Parse-Vorgang zu jeder Zeit auf alle Knoten des
Dokumentes zugegriffen werden kann. Das ist möglich, da der Parser das gesamte Dokument
zunächst in den Hauptspeicher lädt. Bei großen XML-Dokumenten kann dies jedoch zu
starken Performanz-Problemen führen.
1.4.2 SAX
SAX steht für Simple API for XML. Wird eine XML-Datei von einem SAX-Parser
eingelesen, so werden Ereignisse geworfen. Im Wesentlichen gibt es fünf Ereignisse: Start
eines Dokumentes, Ende eines Dokumentes, Start eines Elementes, Ende eines Elementes
und Text eingelesen. Diese Ereignisse veranlassen den Parser im zugehörigen
ContentHandler die entsprechenden Methoden aufzurufen.
public
public
public
public
public
void
void
void
void
void
startDocument();
endDocument();
startElement(...);
endElement(...);
characters(...);
Wird die bereits mehrfach als Beispiel verwendete Datei Person.xml als Stream eingelesen
(<Person><Name>Max Mustermann</Name><Adresse>Hauptstr. 1, ...), so
werden nacheinander die folgenden Events geworfen: startDocument
–
startElement>Person – startElement>Name – characters>Max Mustermann
– endElement>Name – ...
6
Dadurch, dass die Informationen bereits beim Parse-Vorgang zu Verfügung gestellt werden
und nicht erst nachdem der XML-Baum im Speicher erstellt wurde, ist SAX im Allgemeinen
schneller als DOM und braucht weniger Speicher. Besonders bei großen XML-Dateien, die
evtl. noch Binärdaten, wie Bilder, enthalten, ist die Verwendung von SAX sehr zu empfehlen.
Der Nachteil ist jedoch, dass Knoten-Informationen, die zu Beginn des Parse-Vorgangs
entstehen und im weiteren Verlauf des Parsens noch benötigt werden, in Variablen
zwischengespeichert werden müssen.
1.4.3 JAXP
Derzeit gibt es eine Vielzahl an open source XML-Parsern: JDOM, DOM4J und Xerces-J –
um nur einige zu nennen. Alle unterstützen sowohl DOM-, als auch SAX-Parsing – zumal
DOM-Parser im Hintergrund sowieso meist SAX-Parser verwenden.
Jeder Parser hat sicher seine Daseinsberechtigung, sei es aufgrund besserer Performanz,
einfacher Bedienung oder größerem Funktionsumfang. Genau diese Gründe können jedoch
dazu führen, den Parser je nach Bedarf zu wechseln. Um nicht jedes Mal den gesamten
Quellcode anpassen zu müssen, ist es wünschenswert, eine Schnittstelle (API) zu haben, die
alle der Parser unterstützen.
JAXP steht für Java API for XML Processing und ist genau diese Schnittstelle, bestehend aus
Interfaces und abstrakten Klassen, die JAXP-konforme Parser implementieren müssen.
Werden die Parser nur über JAXP gesteuert, ist es möglich einen JAXP-konformen Parser
durch einen anderen zu ersetzen, ohne den Quellcode zu ändern. Die Verwendung des Parsers
muss dem JAXP Framework lediglich mitgeteilt werden. Dies geschieht z. B. mit dem Befehl
java -Djavax.xml.parsers.SAXParserFactory
= org.apache.xerces.jaxp.SAXParserFactoryImpl
In der Praxis ist ein Parsertausch oft dennoch schwierig, da der Funktionsumfang, also die
Funktionen, die zusätzlich zu JAXP vom Parser angeboten werden, meist als Kriterium für die
Parserwahl genommen wird und der andere Parser diese Funktion dann nicht (in der selben
Form) unterstützt.
JAXP und DOM
Mit dem folgenden Code wird die XML-Datei Person.xml mit einem DOM-Parser durch
Verwendung der JAXP-Schnittstelle eingelesen. Die Validierung, also die Beachtung des
XML Schemas Person.xsd, ist aktiviert.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
factory.setValidating(true);
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("Person.xml"));
7
JAXP und SAX
Mit dem folgenden Code wird die XML-Datei Person.xml mit einem SAX-Parser, durch
Verwendung der JAXP-Schnittstelle eingelesen.
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(true);
SAXParser saxParser = factory.newSAXParser();
saxParser.parse( new File("Person.xml"), new DefaultHandler());
JAXP und XSLT
XSLT steht für eXtensible Stylesheet Language for Transformations und ist eine XMLbasierte Sprache, mit der XML-Dateien in andere textbasierte Dateien umgewandelt werden
können. Als Eingabe wird immer XML erwartet, die Ausgabe kann ein beliebiger Text sein
(z. B. auch XML). In einer XSLT-Datei (oder XSL-Stylesheet), ebenfalls eine XML-Datei,
werden die Umwandlungsregeln festgelegt. Der Transformer ändert die Quell-XML-Datei
entsprechend der Regeln des Stylesheets zu einem neuen Text.
Im Quell-XML-Dokument muss eine Referenz auf ein Stylesheet angegeben sein. Dies erfolgt
mit der folgenden Zeile.
<?xml-stylesheet type="text/xsl" href="xyz.xsl"?>
Wird kein Stylesheet angegeben, ist das Ergebnis gleich der Quelle. Das ist z. B. dann
sinnvoll, wenn ein im Speicher befindlicher DOM-Tree (auch SAX-Events oder Sreams sind
möglich) in eine (XML-) Datei im Filesystem transformiert werden soll.
JAXP konforme Parser müssen ebenfalls einen Transformer bereitstellen. Das folgende CodeBeispiel zeigt, wie mit JAPX ein Transformer erstellt und der Transform-Vorgang ausgeführt
wird.
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.transform(source,result);
8
2 WSDL
2.1 Was ist WSDL
WSDL steht für Web Service Description Language. WSDL-Dokumente sind XMLDokumente, die die Schnittstelle eines Web Service beschreiben. Das heißt, ein WSDLDokument beinhaltet Informationen darüber, wo der Service im Web zu finden ist, welche
Operationen (Methoden) er zu Verfügung stellt und wie auf diese Operationen zugegriffen
werden kann. Es ist also sinnvoll eine WSDL-Datei öffentlich zugänglich zu machen. Dafür
gibt es drei Möglichkeiten:
Jeder Web Service bietet die Möglichkeit, seine Schnittstelle durch Angabe eines URLParameters (z. B. ?wsdl bei Axis) einzusehen.
Die Schnittstellenbeschreibungsdatei mit der Endung .wsdl kann im Web zu Verfügung
gestellt werden (z. B. in einem LDAP- oder FTP-Verzeichnis).
Ein Schnittstellenbeschreibungstemplate wird in Form eines tModel von einem UDDI(Universal Description, Discovery and Integration) Verzeichnisserver für einen oder mehrere
Services veröffentlicht. Ein tModel ist demnach eine WSDL-Beschreibung für eine Gruppe
von Web Services (eine Art Interface), die festlegt, was ein Web Service dieser Gruppe
mindestens bereitstellen muss.
2.2 Aufbau von WSDL-Dokumenten
WSDL liegt zurzeit in der Version 2.0 vor. Diese Version ist sehr viel mächtiger als ihre
Vorgänger. Jedoch implementieren die wenigsten freien Tools zum jetzigen Zeitpunkt diese
Funktionalität. Deshalb wird in den Tutorials WSDL der Version 1.1 verwendet. Natürlich
kann auch solch eine WSDL-Datei sehr komplex werden – wir beschränken uns hier auf das
notwendigste.
WSDL 1.1 besteht in der Grundstruktur, neben dem Root-Element <definitions>, aus
sechs Hauptelementen (genaue Informationen können der Spezifikation entnommen werden
http://www.w3.org/TR/wsdl):
<types> – enthält Inline Schemas (sozusagen den Inhalt von XSD-Dateien innerhalb des
WSDL-XML-Dokuments)
<message> – eine abstrakte Definition des Inhalts der Nachrichten, die zwischen Web
Service und Web Service Client ausgetauscht werden
<portType> – eine Sammlung von Operationen (Web Service Methoden) einer oder
mehrerer Endpunkte
<binding> – beinhaltet Details zu Protokollinformationen (HTTP, SOAP, …) und zum
Nachrichteninhalt
<port> – besser Endpoint, repräsentiert eine bestimmte URL für ein Binding
<service> – eine Sammlung von zugehörigen Ports (Endpoints)
9
Eine korrekte WSDL-Datei, hier für einen Web Service Calculator mit der Methode add,
kann demnach folgendermaßen aussehen.
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
targetNamespace="http://Calculator/"
xmlns:ns="http://Calculator/"
xmlns:typesns="http://Calculator/Types"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xsd:schema targetNamespace="http://Calculator/Types">
<xsd:complexType name="addRequestType">
<xsd:sequence>
<xsd:element name="a" type="xsd:long"/>
<xsd:element name="b" type="xsd:long"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="addResponseType">
<xsd:sequence>
<xsd:element name="addReturn" type="xsd:long"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="addRequestMessagePart" type="typesns:addRequestType"/>
<xsd:element name="addResponseMessagePart" type="typesns:addResponseType"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="addRequestMessage">
<wsdl:part name="addRequestMessagePart" element="typesns:addRequestMessagePart"/>
</wsdl:message>
<wsdl:message name="addResponseMessage">
<wsdl:part name="addResponseMessagePart" element="typesns:addResponseMessagePart"/>
</wsdl:message>
<wsdl:portType name="Calculator">
<wsdl:operation name="add">
<wsdl:input name="addInputElement" message="ns:addRequestMessage"/>
<wsdl:output name="addOutputElement" message="ns:addResponseMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="CalculatorSoapBinding" type="ns:Calculator">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="add">
<soap:operation soapAction="http://Calculator/add"/>
<wsdl:input name="addInputElement">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="addOutputElement">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="CalculatorService">
<wsdl:port name="Calculator" binding="ns:CalculatorSoapBinding">
<soap:address location="http://www.my-domain.com/Calculator/services/Calculator"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
10
3 SOAP
3.1 Was ist SOAP
SOAP ist ein Protokoll zum Übertragen von XML-Nachrichten über das Netzwerk. SOAP ist
der Nachfolger von XML-RPC. Hier wird deutlich, dass es sich bei diesem Protokoll primär
um ein Protokoll für die Ausführung von Remote Procedure Calls handelt.
Meist wird für die Übertragung das HTTP-Protokoll als Transport-Protokoll verwendet.
Prinzipiell ist jedoch jedes Protokoll denkbar, das in der Lage ist ASCII-Zeichen als Payload
(z. B. in Form von MIME-Attachments) zu Übertragen. So wäre also auch SMTP möglich.
SOAP stand ursprünglich für Simple Object Access Protocol. Seit der Version 1.2 steht es nur
noch für SOAP, denn ‚Simple’ ist es nun nicht mehr.
3.2 Aufbau von SOAP
Eine SOAP-Nachricht besteht aus dem Root-Element <Envelope> und ähnlich wie ein
HTML-Dokument aus einem optionalen Header- und einem Body-Element. Das HeaderElement beinhaltet anwendungsspezifische Informationen, wie Informationen zu
Transaktionen, Sicherheit o. ä. Das Body-Element beinhaltet den eigentlichen RPC. Bei
einem korrekten Request-Response-Szenario, angewendet auf unser obiges Beispiel, könnten
folgende Nachrichten übertragen werden.
Request
<?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>
<addRequestMessagePart xmlns="http://Calculator/Types">
<a xmlns="">7</a>
<b xmlns="">5</b>
</addRequestMessagePart>
</soapenv:Body>
</soapenv:Envelope>
Response
<?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>
<addResponseMessagePart xmlns="http://Calculator/Types">
<addReturn xmlns="">12</addReturn>
</addResponseMessagePart>
</soapenv:Body>
</soapenv:Envelope>
11
4 Axis
Dieses Kapitel dient dazu, die spätere Projektstruktur nachvollziehen zu können. Wenn es
Probleme geben sollte, die Beispiele zu implementieren, ist das nicht schlimm, denn die
Implementierung wird in den Tutorials meist automatisch bzw. durch Wizards geschehen.
4.1 Was ist Axis
Axis steht für Apache eXtensible Interaction System und ist das Nachfolgeprojekt von
Apache SOAP. Die Axis Engine ist also eine Open Source Implementierung der W3C
Spezifikation SOAP.
4.2 Web Services mit Axis
Die Axis Engine fungiert als ein Servlet, das in einem Servlet-Container (z. B. Tomcat)
geschoben wird. In dieses Servlet können nun Web Services integriert werden. Es gibt
verschiedene Möglichkeiten Web Services mit Axis zu nutzen, die in den nächsten
Abschnitten näher betrachtet werden.
Die Installation von Axis ist relativ einfach. Nach dem Herunterladen des Archivs
Axis_1.X.jar wird der im Ordner WebApps des Archivs enthaltene Ordner axis in den Ordner
WebApps von Tomcat geschoben. Anschließend müssen die folgenden Dateien in der
Umgebungsvariable CLASSPATH in ihrer entsprechenden Version festgelegt werden:
axis.jar, jaxrpc.jar, saaj.jar, commons-logging.jar, commons-discovery.jar, wsdl4j.jar.
Nach der Installation kann der Tomcat gestartet werden und mit der URL http://localhost/axis/
wird die Axis-Startseite aufgerufen. Der Link Validation zeigt, ob alle nötigen Archive
verfügbar sind. Der Link List zeigt eine Liste der unter Axis deployten Web Services.
4.2.1 Web Services erstellen als Java Web Service (jws)
Die einfachste Variante zum Veröffentlichen von Web Service Methoden im Web ist die
Implementierung einer Java Web Service Klasse (.jws).
public class Calculator
{
public long add(long a, long b) {
return a+b;
}
}
Nach der Installation von Axis wird die Web Service Klasse Calculator.jws in den Ordner
<TOMCAT_HOME>\WebApps\axis
verschoben.
Unter
der
URL
http://localhost/axis/Calculator.jws kann der Service getestet werden (z. B. mit den
Parametern: ?method=add&a=5&b=7).
Diese Variante der Web Service Publikation bietet nur geringe Anpassungsmöglichkeiten. Es
werden zum Beispiel alle Methoden die public sind als Operationen angeboten. Das ist nicht
immer gewünscht.
12
4.2.2 Web Service erstellen mit WSDD
WSDD steht für Web Service Deployment Descriptor. Das Deployment dient der Installation
des Web Service auf dem SOAP-Router. Durch das Deployment können Eigenschaften
festgelegt werden, die der Web Service zur Laufzeit besitzen soll. Diese Eigenschaften
werden in einer XML-Datei, dem Web Service Deployment Descriptor (WSDD), festgelegt.
So kann zum Beispiel ein anderer als der Klassenname als Web Service Name festgelegt
werden (genauere Informationen können den Dokumentationen von Axis unter
http://ws.apache.org/axis/java/index.html entnommen werden).
Für das obige Beispiel kann ein solcher Deskriptor den folgenden Aufbau haben.
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="CalculatorService" provider="java:RPC">
<parameter name="className" value="calculator.Calculator"/>
<parameter name="allowedMethods" value="add"/>
</service>
</deployment>
Wenn es einen Deployment Deskriptor (deploy.wsdd) zur Installation eines Web Service gibt,
dann gibt es auch einen Undeployment Deskriptor (undeploy.wsdd), um einen Web Service
wieder vom Server zu entfernen.
<undeployment xmlns="http://xml.apache.org/axis/wsdd/">
<service name="CalculatorService" />
</undeployment>
Der Parameter className im Deployment Deskriptor zeigt, dass es eine Klasse
Calculator.class im Ordner (Package) calculator geben muss. Angelehnt an das Beispiel hat
die Klasse den folgenden Inhalt.
package calculator;
public class Calculator {
public long add(long a, long b) {
return a+b;
}
}
Alle kompilierten Klassen müssen bei Axis im Ordner WEB-INF\classes verfügbar sein.
Deshalb wird der Ordner calculator zusammen mit der Klasse Calculator.class und den
beiden Deskriptoren in den Ordner classes von Axis verschoben.
Zum Deployen (bzw. Undeployen) wird der Axis AdminClient verwendet. Mit dem
Konsolenaufruf
java org.apache.axis.client.AdminClient deploy.wsdd -p80
aus dem Ordner calculator heraus wird der Web Service auf den Server deployt.
13
Der Service ist nun in Axis in der Liste der deployten Web Services aufgelistet
(http://localhost/axis/servlet/AxisServlet)
und
kann
über
die
URL
http://localhost/axis/services/CalculatorService angesprochen werden.
4.2.3 Web Service erstellen als Web Applikation
Wenn eigene Web Services geschrieben werden, ist es unter Umständen wünschenswert,
diese von der Axis-Umgebung zu trennen – also ‚standalone’ zu betreiben. Das hat den
Vorteil, dass so erstellte Archive, unabhängig von einer Axis-Installation, auf jedem anderen
(Tomcat) Server lauffähig sind. In den Tutorials wird diese Variante verwendet.
Bei genauer Betrachtung der Axis Web Applikation fällt auf, dass die Ordner der Anwendung
einer bestimmten Struktur folgen. Der Root-Ordner ist der Name der Applikation (bzw. des
Projektes) – in diesem Fall axis. Im Ordner axis gibt es einen Unterordner WEB-INF, der
wiederum zwei Unterordner classes und lib besitzt. Im Ordner classes befinden sich die
Quelldateien der Web Services. Im Ordner lib die Web Bibliotheken, die für die Ausführung
der Services benötigt werden.
Werden eigene Web Applikationen erstellt, müssen diese ebenfalls diese Ordnerstruktur
aufweisen. Für den Web Service Calculator wäre das dann z. B. die folgende:
CalculatorWebApp\WEB-INF\(classess,lib). In den Ordner classes muss der Ordner
calculator mit der Klasse Calculator.class hineinkopiert werden, der weiter oben im Tutorial
bereits implementiert wurde. In den Ordner lib müssen sämtliche Bibliotheken aus dem
Ordner lib der axis-Anwendung hineinkopiert werden.
In den WEB-INF-Ordner müssen zusätzlich noch zwei Dateien: zum einen der Deployment
Deskriptor (allerdings muss der Dateiname zu server-config.wsdd geändert werden) und die
Datei web.xml, die Servlet Deklarations- und Mapping-Informationen zum Axis-Servlet
enthält. Die Datei web.xml kann ebenfalls aus dem Verzeichnis axis\WEB-INF kopiert
werden.
Der Web Service ist nun unter der folgenden
http://localhost/CalculatorWebApp/services/CalculatorService.
URL
zu
erreichen:
Im obigen Beispiel wurde eine ‚Exploded Web Application’ erstellt. Das bedeutet, dass es
sich um ein entpacktes WAR-Archiv handelt. Andersherum gesehen kann die erstellte
Ordnerstruktur natürlich auch in einem WAR-Archiv zusammengefasst werden. Ein WARArchiv ist hier eine Zip-Datei mit der Endung .war.
Ein Undeployment Deskriptor ist für das Web Archiv nicht nötig, da der Web Service bei
jedem Start von Tomcat (re)deployed wird und falls die Dateien des Service nicht mehr
verfügbar sind, wird er auch nicht deployt. Um also einen Service vom Server zu entfernen,
reicht es das Verzeichnis der ‚Exploded Web Application’ und ggf. das zugehörige WARArchiv aus dem Tomcat WebApps-Verzeichnis zu löschen.
In den Tutorials werden die Struktur und die Deskriptoren automatisch erzeugt, da Eclipse
entsprechende Dynamic Web Projects zu Verfügung stellt. Das Deployen erfolgt mit Hilfe
von Wizards, genau wie das Erstellen des WAR-Archivs. Der Programmierer braucht sich
also um die bisher genannten Konventionen wenig Gedanken zu machen.
14
4.3 Axis und WSDL
Axis ist in der Lage aus Java-Klassen eine WSDL-Datei und aus einer WSDL-Datei ein JavaKlassen-Gerüst zu generieren. Dafür werden die beiden Tools Java2WSDL und WSDL2Java
verwendet.
4.3.1 Java2WSDL
Java2WSDL wurde weiter oben bereits angewendet. Mit dem Parameter ?wsdl der Web
Service URL wurde die Web Service Beschreibungsdatei im Browser angezeigt.
Existieren bereits die Klassen eines Web Service bzw. ein Java-Interface, kann mit
Java2WSDL die zugehörige WSDL-Datei manuell erstellt werden. Dazu wird auf der
Konsole z. B. der folgende Befehl verwendet.
java org.apache.axis.wsdl.Java2WSDL
-l http://localhost/CalculatorWebApp/services/CalculatorService
-n http://calculator
calculator.Calculator
Dieser Aufruf generiert die Datei CalculatorService.wsdl. Der Parameter –l gibt
hierbei die URL an, unter der der Web Service später zu erreichen ist. Der Parameter –n gibt
den Target-Namespace für die WSDL-Beschreibung an. calculator.Calculator ist der
Klassenname.
4.3.2 WSDL2Java
Existiert bereits eine WSDL-Beschreibung, sei es aufgrund eines existierenden Web Services
bzw. in Form einer WSDL-Datei, so kann aus dieser Beschreibung ein Java-Klassengerüst
erstellt werden.
Beim Aufruf von WSDL2Java gibt es die Möglichkeit einen Client (eine Art SOAP-Proxy),
bzw. einen Server (den Web Service) zu erstellen. Dies geschieht durch die Angabe der
Parameter --client-side bzw. --server-side.
Zum Erstellen des Web Service Calculator aus dem obigen Beispiel wird auf der Konsole
der folgende Aufruf gestartet.
java org.apache.axis.wsdl.WSDL2Java
--server-side
--skeletonDeploy true
CalculatorService.wsdl
Im Ordner calculator (Package-Name) wurden einige Dateien erstellt, die nun etwas
genauer betrachtet werden.
Calculator – das Service-Interface mit allen abstrakten Methoden, die der Web Service zu
Verfügung stellt
CalculatorService – eine intern verwendete Klasse um konform zur JAX-RPC-
Spezifikation von SUN zu sein
CalculatorServiceSoapBindingSkeleton – befindet sich zwischen der Axis Engine
und der eigentlichen Web Service Implementierung
15
CalculatorServiceSoapBindingImpl – die eigentliche Implementierung der Web
Service Operationen (Web Service Methoden)
CalculatorServiceLocator – wird nur für den Client benötigt (nicht für den Server);
liefert die Service-Instanz
CalculatorServiceSoapBindingStub – wird nur vom Client verwendet; setzt Java Web
Service Anfragen auf SOAP-Requests um
Existieren komplexe Datentypen werden für diese außerdem gesonderte Klassen erstellt.
deploy.wsdd / undeploy.wsdd – Deskriptoren zum (un)deployen (siehe Kapitel 4.2.2)
Die Methode(n) der Klasse CalculatorServiceSoapBindingImpl
implementiert werden. Im obigen Beispiel wäre das die Methode add.
muss
noch
Bleibt die Frage: Warum so umständlich, wenn es auch einfach geht (siehe Kapitel 4.2)? Der
Hintergrund ist der, dass die Anwendungslogik vom Zugriff getrennt sein sollte. Der Zugriff
könnte statt über SOAP auch über HTTP- oder MIME-Bindings erfolgen. Die Funktionalität
wäre in allen Fällen dieselbe. Wie auch immer, bei der Generierung der Klassen aus der
WSDL-Beschreibung heraus wird immer diese Struktur eingehalten. Für das Erstellen der
Web Services in den Tutorials ist jedoch nur die Klasse XXXBindingImpl interessant, da
hier die eigentliche Funktionalität implementiert wird.
16
Herunterladen