Die folgende praktische Einführung demonstriert, wie Sie auf Webdienste mit der Java API für XML-Webdienste (JAX-WS) zugreifen.
Wenn Sie die vorherige praktische Einführung durchgearbeitet haben, wurden einige dieser Schritte bereits durchgeführt.
Bevor Sie beginnen, benötigen Sie die JAX-WS-Tools von Sun. Wenn dieses Paket auf Ihren System nicht installiert ist, müssen
Sie die JAX-WS-Tools herunterladen und installieren. Um die JAX-WS-Tools herunterzuladen, gehen Sie zu http://java.sun.com/webservices/. Klicken Sie auf den Link für JAX-WS. Dies sollte Sie auf die Seite
Java-API für XML Webdienste bringen. Klicken Sie auf den Download Now-Link. Nachdem Sie das Softwarepaket heruntergeladen haben, installieren Sie es auf Ihrem System.
Dieses Beispiel wurde mit JAX-WS 2.1.3 für Windows entwickelt.
Für SQL Anywhere SOAP-Webdienste, auf die aus JAX-WS zugegriffen wird, muss das Format CONCRETE deklariert werden.
Führen Sie an der Eingabeaufforderung folgenden Befehl aus, um einen Personal Webserver zu starten. Ersetzen Sie Beispieldatenbank durch den tatsächlichen Speicherort der Beispieldatenbank. Die Option -xs http(port=80)
teilt dem Datenbankserver mit, HTTP-Anforderungen auf Port 80 anzunehmen. Wenn auf Port 80 bereits ein Webserver läuft, benutzen
Sie eine andere Portnummer, z.B. 8080, für diese praktische Einführung.
dbeng11 -xs http(port=80) Beispielverzeichnis\demo.db |
Starten Sie Interactive SQL und stellen Sie als DBA eine Verbindung mit der SQL Anywhere-Datenbank her. Führen Sie die folgenden Anweisungen aus:
Erstellen Sie eine gespeicherte Prozedur, die einige Spalten der Tabelle Employees auflistet.
CREATE PROCEDURE ListEmployees() RESULT ( EmployeeID INTEGER, Surname CHAR(20), GivenName CHAR(20), StartDate DATE, TerminationDate DATE ) BEGIN SELECT EmployeeID, Surname, GivenName, StartDate, TerminationDate FROM Employees; END; |
Legen Sie einen SOAP-Dienst fest, der diese gespeicherte Prozedur aufruft.
CREATE SERVICE "WS/EmployeeList2" TYPE 'SOAP' FORMAT 'CONCRETE' EXPLICIT ON DATATYPE OUT AUTHORIZATION OFF SECURE OFF USER DBA AS CALL ListEmployees(); |
Die EXPLICIT-Klausel kann nur mit einem SOAP- oder DISH-Dienst vom Typ CONCRETE verwendet werden. In diesem Beispiel gibt EXPLICIT ON an, dass der entsprechende DISH-Dienst ein XML-Schema generieren soll, das das generische EmployeeList2Dataset-Objekt beschreibt. Die Option betrifft nur das generierte WSDL-Dokument. In einer früheren praktischen Einführung zu JAX-WS wurde ein Beispiel beschrieben, das EXPLICIT OFF verwendet hat. Weitere Hinweise finden Sie unter Praktische Einführung: Zugriff auf Webdienste von JAX-WS.
DATATYPE OUT gibt an, dass explizite Datentypinformationen in der zurückgegebenen XML-Ergebnismenge generiert werden. Falls DATATYPE OFF angegeben worden wäre, würden alle Daten als "string" typisiert sein. Diese Option wirkt sich nicht auf das WSDL-Dokument aus, das generiert wird.
Da die Autorisierung deaktiviert ist, kann jeder diesen Dienst benutzen, ohne einen Benutzernamen mit Kennwort anzugeben. Die Befehle werden unter dem Benutzer DBA ausgeführt. Dieses Arrangement ist einfach, aber nicht sicher.
Erstellen Sie einen DISH-Dienst, der als Proxy für den SOAP-Dienst agiert und das WSDL-Dokument generiert.
CREATE SERVICE "WSDish" TYPE 'DISH' FORMAT 'CONCRETE' GROUP "WS" AUTHORIZATION OFF SECURE OFF USER DBA; |
Der SOAP- und der DISH-Dienst müssen beide das CONCRETE-Format haben. Da sich der EmployeeList2-Dienst in der WS-Gruppe befindet, ist auch eine GROUP-Klausel enthalten.
Sehen Sie sich das WSDL an, das der DISH-Dienst automatisch erstellt. Um das zu erreichen, öffnen Sie einen Webbrowser und
navigieren zur folgenden URL: http://localhost:80/demo/WSDish. Der DISH-Dienst generiert automatisch ein WSDL-Dokument, das im Browser-Fenster angezeigt wird.
Beachten Sie besonders das EmployeeList2Dataset-Objekt, das vorgelegt wird, weil das Format des Dienstes CONCRETE und EXPLICIT auf ON gesetzt ist. In einem späteren Schritt verwendet die wsimport-Anwendung diese Informationen, um eine SOAP 1.1-Clientschnittstelle für diesen Dienst zu generieren.
<s:complexType name="EmployeeList2Dataset">
<s:sequence>
<s:element name="rowset">
<s:complexType>
<s:sequence>
<s:element name="row" minOccurs="0" maxOccurs="unbounded">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="EmployeeID"
nillable="true" type="s:int" />
<s:element minOccurs="0" maxOccurs="1" name="Surname"
nillable="true" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="GivenName"
nillable="true" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="StartDate"
nillable="true" type="s:date" />
<s:element minOccurs="0" maxOccurs="1" name="TerminationDate"
nillable="true" type="s:date" />
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType> |
In diesem Beispiel sind die Java-API für XML-Webdienste und das Sun Java 1.6.0 JDK auf Laufwerk C: installiert. Legen Sie die PATH-Umgebungsvariable so fest, dass sie die JAX-WS-Binärdateien ebenso wie das JDK einbezieht. Die Binärdateien befinden sich in den folgenden Verzeichnissen:
c:\Sun\jaxws-ri\bin c:\Sun\SDK\jdk\bin |
An einer Eingabeaufforderung legen Sie Ihre CLASSPATH-Umgebungsvariable fest.
SET classpath=.;C:\Sun\jaxws-ri\lib\jaxb-api.jar ;C:\Sun\jaxws-ri\lib\jaxws-rt.jar |
Der nächste Schritt generiert die Schnittstelle, die zum Aufruf des Webdiensts erforderlich ist.
An derselben Eingabeaufforderung erstellen Sie ein neues Projektverzeichnis und machen dieses Verzeichnis zu Ihrem aktuellen Verzeichnis. Führen Sie den folgenden Befehl in diesem Verzeichnis aus.
wsimport -keep -Xendorsed "http://localhost:80/demo/WSDish" |
Das wsimport-Tool ruft das WSDL-Dokument von der angegebenen URL ab, generiert die Java-Dateien, die die Schnittstelle dafür festlegen, und kompiliert sie dann.
Die Option keep teilt wsimport mit, die .java-Dateien nicht zu löschen. Ohne diese Option werden diese Dateien gelöscht, nachdem die entsprechenden .class-Dateien generiert wurden. Das Aufbewahren dieser Dateien erleichert es, den Aufbau der Schnittstelle zu untersuchen.
Die Option Xendorsed ermöglicht es Ihnen, die JAX-WS 2.1 API mit JDK6 zu verwenden.
Sobald dieser Befehl abgeschlossen ist, finden Sie die neue Unterverzeichnisstruktur namens localhost\demo\ws vor, die die folgenden Java-Dateien sowie ihre kompilierten .class-Versionen enthält.
EmployeeList2.java EmployeeList2Dataset.java EmployeeList2Response.java FaultMessage.java ObjectFactory.java package-info.java WSDish.java WSDishSoapPort.java |
Speichern Sie den folgenden Java-Quellcode in SASoapDemo2.java. Vergewissern Sie sich, dass sich diese Datei in dem Verzeichnis befindet, das auch das von wsimport-Tool erstellte Unterverzeichnis localhost enthält.
// SASoapDemo2.java illustrates a web service client that // calls the WSDish service and prints out the data. import java.util.*; import javax.xml.ws.*; import org.w3c.dom.Element; import org.w3c.dom.Node; import javax.xml.datatype.*; import localhost.demo.ws.*; public class SASoapDemo2 { public static void main( String[] args ) { try { WSDish service = new WSDish(); Holder<EmployeeList2Dataset> response = new Holder<EmployeeList2Dataset>(); Holder<Integer> sqlcode = new Holder<Integer>(); WSDishSoapPort port = service.getWSDishSoap(); // This is the SOAP service call to EmployeeList2 port.employeeList2( response, sqlcode ); EmployeeList2Dataset result = response.value; EmployeeList2Dataset.Rowset rowset = result.getRowset(); List<EmployeeList2Dataset.Rowset.Row> rows = rowset.getRow(); String fieldType; String fieldName; String fieldValue; Integer fieldInt; XMLGregorianCalendar fieldDate; for ( int i = 0; i < rows.size(); i++ ) { EmployeeList2Dataset.Rowset.Row row = rows.get( i ); fieldType = row.getEmployeeID().getDeclaredType().getSimpleName(); fieldName = row.getEmployeeID().getName().getLocalPart(); fieldInt = row.getEmployeeID().getValue(); System.out.println( "(" + fieldType + ")" + fieldName + "=" + fieldInt ); fieldType = row.getSurname().getDeclaredType().getSimpleName(); fieldName = row.getSurname().getName().getLocalPart(); fieldValue = row.getSurname().getValue(); System.out.println( "(" + fieldType + ")" + fieldName + "=" + fieldValue ); fieldType = row.getGivenName().getDeclaredType().getSimpleName(); fieldName = row.getGivenName().getName().getLocalPart(); fieldValue = row.getGivenName().getValue(); System.out.println( "(" + fieldType + ")" + fieldName + "=" + fieldValue ); fieldType = row.getStartDate().getDeclaredType().getSimpleName(); fieldName = row.getStartDate().getName().getLocalPart(); fieldDate = row.getStartDate().getValue(); System.out.println( "(" + fieldType + ")" + fieldName + "=" + fieldDate ); if ( row.getTerminationDate() == null ) { fieldType = "unknown"; fieldName = "TerminationDate"; fieldDate = null; } else { fieldType = row.getTerminationDate().getDeclaredType().getSimpleName(); fieldName = row.getTerminationDate().getName().getLocalPart(); fieldDate = row.getTerminationDate().getValue(); } System.out.println( "(" + fieldType + ")" + fieldName + "=" + fieldDate ); System.out.println(); } } catch (Exception x) { x.printStackTrace(); } } } |
Wenn der Webserver mit einer anderen Portnummer, wie z.B. mit 8080, gestartet werden soll, müssen Sie die Quellenzeile import localhost
ähnlich wie folgt ändern:
import localhost._8080.demo.ws.*; |
Kompilieren Sie SASoapDemo2.java.
javac SASoapDemo2.java |
Führen Sie die kompilierte Klassendatei aus.
java SASoapDemo2 |
Wenn die Anwendung ihre Anforderung an den Webserver sendet, erhält sie als Antwort eine XML-Ergebnismenge, die aus EmployeeList2Result mit einer Zeilengruppe besteht, die mehrere Zeileneinträge enthält. Ebenfalls in der Antwort enthalten ist das sqlcode-Ergebnis der ausgeführten Abfrage. Ein Beispiel für die Antwort sieht folgendermaßen aus.
<tns:EmployeeList2Response> <tns:EmployeeList2Result xsi:type='tns:EmployeeList2Dataset'> <tns:rowset> <tns:row>...</tns:row> . . . <tns:row>...</tns:row> </tns:rowset> </tns:EmployeeList2Result> <tns:sqlcode>0</tns:sqlcode> </tns:EmployeeList2Response> |
Jede Zeile in der Zeilengruppe wird in dem nachstehend gezeigten Format gesendet.
<tns:row> <tns:EmployeeID xsi:type="xsd:int">1751</tns:EmployeeID> <tns:Surname xsi:type="xsd:string">Ahmed</tns:Surname> <tns:GivenName xsi:type="xsd:string">Alex</tns:GivenName> <tns:StartDate xsi:type="xsd:date">1994-07-12-04:00</tns:StartDate> <tns:TerminationDate xsi:type="xsd:date">2008-04-18-04:00 </tns:TerminationDate> </tns:row> |
Beachten Sie, dass der Spaltenname und der Datentyp enthalten sind.
Sie können die oben angezeigte Antwort verfolgen, indem Sie eine Proxy-Software verwenden, die das XML-Nachrichtenaufkommen protokolliert. Der Proxy steht zwischen Ihrer Clientanwendung und dem Webserver.
Die EmployeeList2-Ergebnismenge wird von der SASoapDemo2-Anwendung als (Typ)Spaltenname=Wert-Paare angezeigt. Es sollten einige Zeilen ähnlich den folgenden generiert und ausgegeben werden.
(Integer)EmployeeID=102 (String)Surname=Whitney (String)GivenName=Fran (XMLGregorianCalendar)StartDate=1984-08-28-04:00 (unknown)TerminationDate=null (Integer)EmployeeID=105 (String)Surname=Cobb (String)GivenName=Matthew (XMLGregorianCalendar)StartDate=1985-01-01-05:00 (unknown)TerminationDate=null . . . (Integer)EmployeeID=1740 (String)Surname=Nielsen (String)GivenName=Robert (XMLGregorianCalendar)StartDate=1994-06-24-04:00 (unknown)TerminationDate=null (Integer)EmployeeID=1751 (String)Surname=Ahmed (String)GivenName=Alex (XMLGregorianCalendar)StartDate=1994-07-12-04:00 (XMLGregorianCalendar)TerminationDate=2008-04-18-04:00 |
Beachten Sie, dass die TerminationDate-Spalte nur gesendet wird, wenn ihr Wert NULL ist. Die Java-Anwendung ist dafür konzipiert, zu erkennen, wenn die Spalte TerminationDate nicht vorhanden ist. Bei diesem Beispiel wurde die letzte Zeile in der Employees-Tabelle geändert, um ein Nicht-NULL-Beendigungsdatum festzulegen.
Beachten Sie auch, dass die Datumswerte einen Offset von der UTC-Zeit einbeziehen. Im obenstehenden Beispiel befindet sich der Server in der North American Eastern-Zeitzone. Dies ist 5 Stunden früher als UTC-Zeit (-05:00) bei Datumsangaben, wenn keine Sommerzeit gilt, und 4 Stunden früher als UTC-Zeit (-04:00) bei Datumsangaben, wenn Sommerzeit gilt.
Um das Verständnis der Java-Methoden, die in der SASoapDemo2-Anwendung zum Einsatz kommen, zu vertiefen, wird empfohlen, die
Dokumentation zur javax.xml.bind.JAXBElement-Klasse auf der java.sun.com-Website ( http://java.sun.com/javaee/5/docs/api/) zu studieren.
Kommentieren Sie diese Seite in DocCommentXchange. Senden Sie uns Feedback über diese Seite via E-Mail. |
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |