Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (Deutsch) » SQL Anywhere Server - Programmierung » SQL Anywhere Datenzugriff-APIs » SQL Anywhere-Webdienste

 

SOAP-Header verwenden

In diesem Abschnitt wird der einfache Webdienst, der in SOAP-Dienste verwenden erstellt wurde, erweitert, um SOAP-Header zu verarbeiten.

Wenn Sie die Schritte in den vorherigen Abschnitten ausgeführt haben, können Sie die Schritte 1 bis 4 überspringen und direkt zu Schritt 5 gehen.

♦  So erstellen Sie einen Webdienstserver
  1. Erstellen Sie eine Datenbank.

    dbinit ftc
  2. Starten Sie einen Server mit dieser Datenbank.

    dbsrv11 -xs http(port=8082) -n ftc ftc.db
  3. Stellen Sie mit Interactive SQL eine Verbindung zum Server her.

    dbisql -c "UID=DBA;PWD=sql;ENG=ftc"
  4. Erstellen Sie mit Interactive SQL einen Webdienst.

    CREATE SERVICE FtoCService
    TYPE 'SOAP'
    FORMAT 'XML'
    AUTHORIZATION OFF
    USER DBA
    AS CALL FToCConvertor( :temperature );
  5. Definieren Sie die gespeicherte Prozedur, die dieser Dienst aufrufen soll, um die Berechnungen auszuführen, die für die Konvertierung einer Temperatur von Fahrenheit in Celsius erforderlich sind. Im Unterschied zum Beispiel aus dem vorherigen Abschnitt umfasst dieses Beispiel zustätzliche Anweisungen zur Verarbeitung eines speziellen SOAP-Headers. Wenn Sie bereits das Beispiel aus dem vorherigen Abschnitt durchgearbeitet haben, ändern Sie die CREATE-Anweisung unten in ALTER, da Sie nun die gespeicherte Prozedur ändern.

    CREATE PROCEDURE FToCConvertor( temperature FLOAT )
    BEGIN
      DECLARE hd_key LONG VARCHAR;
      DECLARE hd_entry LONG VARCHAR;
      DECLARE alias LONG VARCHAR;
      DECLARE first_name LONG VARCHAR;
      DECLARE last_name LONG VARCHAR;
      DECLARE xpath LONG VARCHAR;
      DECLARE authinfo LONG VARCHAR;
      DECLARE namespace LONG VARCHAR;
      DECLARE mustUnderstand LONG VARCHAR; 
    header_loop:
      LOOP
        SET hd_key = NEXT_SOAP_HEADER( hd_key );
        IF hd_key IS NULL THEN
          -- no more header entries
          LEAVE header_loop;
        END IF;
        IF hd_key = 'Authentication' THEN
          SET hd_entry = SOAP_HEADER( hd_key );
          SET xpath = '/*:' || hd_key || '/*:userName';
          SET namespace = SOAP_HEADER( hd_key, 1, 
                                   '@namespace' );
          SET mustUnderstand = SOAP_HEADER( hd_key, 1, 
                                   'mustUnderstand' );
          BEGIN
            -- parse the XML returned in the SOAP header 
            DECLARE crsr CURSOR FOR 
              SELECT * 
              FROM OPENXML( hd_entry, xpath )
                WITH ( alias LONG VARCHAR '@*:alias',
                first_name LONG VARCHAR '*:first/text()',
                last_name LONG VARCHAR '*:last/text()' );
            OPEN crsr;
            FETCH crsr INTO alias, first_name, last_name;
            CLOSE crsr;
          END;
          -- build a response header
          -- based on the pieces from the request header
          SET authinfo = 
            XMLELEMENT( 'Authentication',
              XMLATTRIBUTES(
                namespace as xmlns,
                alias,
                mustUnderstand ),
                XMLELEMENT( 'first', first_name ),
                XMLELEMENT( 'last', last_name ) );
          CALL SA_SET_SOAP_HEADER( 'authinfo', authinfo );
        END IF;
      END LOOP header_loop;
      SELECT ROUND((temperature - 32.0) * 5.0 / 9.0, 5) 
      AS answer;
    END;

Mit einer Kombination der Funktionen NEXT_SOAP_HEADER und SOAP_HEADER können Sie Header in SOAP-Anforderungen erhalten. Die Funktion NEXT_SOAP_HEADER wird in den SOAP-Headern wiederholt, die in eine Anforderung einbezogen sind, und gibt den nächsten SOAP-Headernamen zurück. Sie mit NULL aufzurufen führt dazu, dass sie den Namen des ersten Headers zurückgibt. Nachfolgende Header werden abgerufen, indem der Funktion NEXT_SOAP_HEADER der Name des vorigen Headers weitergegeben wird. Diese Funktion gibt NULL zurück, wenn sie mit dem Namen des letzten Headers aufgerufen wird. Der SQL-Code, der die SOAP-Header-Abfrage in diesem Beispiel ausführt, sieht folgendermaßen aus. Er verlässt die Schleife, wenn NULL zurückgegeben wird.

SET hd_key = NEXT_SOAP_HEADER( hd_key );
    IF hd_key IS NULL THEN
      -- no more header entries
      LEAVE header_loop;
    END IF;

Wenn diese Funktion mehrfach aufgerufen wird, werden alle Headerbereiche genau einmal zurückgegeben, jedoch nicht unbedingt in der Reihenfolge, in der sie in der SOAP-Anfrage erscheinen.

Die Funktion SOAP_HEADER gibt den Wert des benannten SOAP-Header-Felds zurück oder NULL, wenn sie nicht von einem SOAP-Dienst aufgerufen wurde. Sie wird verwendet, wenn eine SOAP-Anforderung über einen Webdienst verarbeitet wird. Wenn ein Header für einen angegebenen Feldnamen nicht existiert, ist der Rückgabewert NULL.

Das Beispiel sucht nach einem SOAP-Header namens "Authentication". Wenn dieser Header gefunden wird, werden der Wert für den gesamten SOAP-Header sowie die Werte der Attribute @namespace und mustUnderstand extrahiert. Der Wert des SOAP-Headers könnte z.B. wie die folgende XML-Zeichenfolge aussehen:

<Authentication xmlns="SecretAgent" mustUnderstand="1">
  <userName alias="99">
    <first>Susan</first>
    <last>Hilton</last>
  </userName>
</Authentication>

Für diesen Header hat das Attribut @namespace den folgenden Wert: SecretAgent

Das Attribut mustUnderstand hat in diesem Beispiel den Wert:1

Diese XML-Zeichenfolge wird mit der Funktion OPENXML syntaktisch analysiert. Hierzu wird eine XPath-Zeichenfolge mit dem Wert /*:Authentication/*:userName verwendet.

SELECT * 
FROM OPENXML( hd_entry, xpath )
  WITH ( alias LONG VARCHAR '@*:alias',
  first_name LONG VARCHAR '*:first/text()',
  last_name LONG VARCHAR '*:last/text()' );

Unter Verwendung des oben dargestellten SOAP-Headerwerts erstellt die SELECT-Anweisung wie folgt eine Ergebnismenge:

alias first_name last_name
99 Susan Hilton

Für diese Ergebnismenge wird ein Cursor deklariert und die drei Spaltenwerte werden in drei Variablen abgerufen. Sie haben nun alle gewünschten Informationen, die an den Webdienst übergeben wurden. Sie haben die Temperatur in Fahrenheit und einige zusätzliche Attribute, die dem Webdienst in einem SOAP-Header übergeben wurden. Diese Informationen können für verschiedene Vorgänge verwendet werden.

Sie können den Namen und den Alias suchen, die übergeben wurden, um festzustellen, ob die Person für die Verwendung des Webdienstes autorisiert ist. Diese Übung wird jedoch nicht in dem Beispiel gezeigt.

Der nächste Schritt in der gespeicherten Prozedur ist, eine Antwort im SOAP-Format zu erstellen. Sie können die XML-Antwort folgendermaßen erstellen:

SET authinfo = 
  XMLELEMENT( 'Authentication',
    XMLATTRIBUTES(
      namespace as xmlns,
      alias,
      mustUnderstand ),
      XMLELEMENT( 'first', first_name ),
      XMLELEMENT( 'last', last_name ) );

Damit wird die folgende XML-Zeichenfolge erstellt:

<Authentication xmlns="SecretAgent" alias="99" 
                            mustUnderstand="1">
  <first>Susan</first>
  <last>Hilton</last>
</Authentication>

Um die SOAP-Antwort an den Aufrufer zurückzugeben, wird die gespeicherte Prozedur SA_SET_SOAP_HEADER verwendet:

CALL SA_SET_SOAP_HEADER( 'authinfo', authinfo );

Wie im Beispiel des vorigen Abschnitts gezeigt wurde, ist der letzte Schritt die Berechnung, die von Fahrenheit in Celsius konvertiert.

Sie haben nun einen laufenden SQL Anywhere-Webdienstserver, der Temperaturen von Fahrenheit in Celsius wie im vorigen Abschnitt konvertieren kann. Der wichtigste Unterschied besteht darin, dass er auch einen SOAP-Header vom Aufrufer verarbeiten und eine SOAP-Antwort an den Aufrufer zurücksenden kann.

Damit wird jedoch nur die Hälfte der Aufgaben erfüllt. Der nächste Schritt ist, einen Beispiel-Client zu entwickeln, der SOAP-Anforderungen senden und SOAP-Antworten ermpfangen kann.

Wenn Sie die Schritte in den vorherigen Abschnitten ausgeführt haben, können Sie die Schritte 1 bis 3 überspringen und direkt zu Schritt 4 gehen.

♦  So senden und empfangen Sie SOAP-Header
  1. Erstellen Sie eine andere Datenbank, die mit einem zweiten Server verwendet werden soll.

    dbinit ftc_client
  2. Starten Sie den Personal Server mit dieser Datenbank.

    dbeng11 ftc_client.db
  3. Stellen Sie mit einer anderen Instanz von Interactive SQL eine Verbindung zu dem Personal Server her.

    dbisql -c "UID=DBA;PWD=sql;ENG=ftc_client"
  4. Erstellen Sie mit Interactive SQL eine gespeicherte Prozedur.

    CREATE PROCEDURE FtoC( temperature FLOAT,
        INOUT inoutheader LONG VARCHAR,
        IN inheader LONG VARCHAR )
      URL 'http://localhost:8082/FtoCService'
      TYPE 'SOAP:DOC'
      SOAPHEADER '!inoutheader!inheader';

    Die URL-Klausel wird verwendet, um den SOAP-Webdienst zu referenzieren. Die Zeichenfolge 'http://localhost:8082/FtoCService' legt die URI-Adresse des Webdiensts fest, der verwendet wird. Dies ist ein Verweis auf den Webserver, der Port 8082 abhört.

    Das Standardformat für eine Webdienstanforderung ist SOAP:RPC. Das gewählte Format in diesem Beispiel ist SOAP:DOC. Dies ist ähnlich SOAP:RPC, doch es ermöglicht eine größere Gruppe von Datentypen. SOAP-Anforderungen werden immer als XML-Dokumente gesendet. Die Methode zum Senden von SOAP-Anforderungen ist HTTP:POST.

    Die Ersatzvariablen in einer SQL Anywhere-Clientprozedur (inoutheader, inheader) müssen alphanummerisch sein. Wenn der Webdienstclient als Funktion deklariert wird, sind seine Parameter auf den IN-Modus beschränkt (sie können von der aufgerufenen Funktion nicht zugewiesen werden). Aus diesem Grund müssen OPENXML und andere Zeichenfolgenfunktionen verwendet werden, um die Informationen des SOAP-Antwort-Headers zu extrahieren.

  5. Sie brauchen einen Wrapper für die gespeicherte Prozedur FtoC, weshalb Sie eine zweite gespeicherte Prozedur erstellen müssen. Im Unterschied zum vorigen Abschnitt werden hier zusätzliche Anweisungen einbezogen, um einen speziellen SOAP-Header zu erstellen, ihn in einem Webdienstaufruf zu senden und eine Antwort vom Webserver zu verarbeiten. Wenn Sie bereits das Beispiel aus dem vorherigen Abschnitt durchgearbeitet haben, ändern Sie die CREATE-Anweisung unten in ALTER, da Sie nun die gespeicherte Prozedur ändern.

    CREATE PROCEDURE FahrenheitToCelsius( temperature FLOAT )
    BEGIN
      DECLARE io_header LONG VARCHAR;
      DECLARE in_header LONG VARCHAR;
      DECLARE result LONG VARCHAR;
      DECLARE err INTEGER;
      DECLARE crsr CURSOR FOR
        CALL FtoC( temperature, io_header, in_header );
      SET io_header =
        '<Authentication xmlns="SecretAgent" ' ||
                         'mustUnderstand="1">' ||
        '<userName alias="99">' ||
        '<first>Susan</first><last>Hilton</last>' ||
        '</userName>' ||
        '</Authentication>';
      SET in_header =
        '<Session xmlns="SomeSession">' ||
        '123456789' ||
        '</Session>';
    
      MESSAGE 'send, soapheader=' || io_header || in_header;
      OPEN crsr;
      FETCH crsr INTO result, err;
      CLOSE crsr;
      MESSAGE 'receive, soapheader=' || io_header;
      SELECT temperature, Celsius
      FROM OPENXML(result, '//tns:answer', 1, result)
             WITH ("Celsius" FLOAT 'text()');
    END;

    Diese gespeicherte Prozedur agiert als abdeckende Prozedur für den Aufruf des Webdiensts. Die gespeicherte Prozedur aus dem Beispiel des vorigen Abschnitts wurde erweitert. Sie erstellt zwei SOAP-Header. Der erste sieht folgendermaßen aus:

    <Authentication xmlns="SecretAgent" 
                                mustUnderstand="1">
      <userName alias="99">
        <first>Susan</first>
        <last>Hilton</last>
      </userName></Authentication>

    Der zweite sieht wie folgt aus:

    <Session xmlns="SomeSession">123456789</Session>

    Wenn der Cursor geöffnet wird, wird die SOAP-Anforderung an den Webdienst gesendet.

    <Authentication xmlns="SecretAgent" alias="99" 
                                mustUnderstand="1">
    <first>Susan</first>
    <last>Hilton</last>
    </Authentication>

    Die gespeicherte Prozedur FtoC gibt eine Ergebnismenge zurück, die von dieser gespeicherten Prozedur verarbeitet wird. Die Ergebnismenge sieht in etwa wie folgt aus.

    <tns:rowset xmlns:tns="http://localhost/ftc/FtoCService">
     <tns:row>
      <tns:answer>100</tns:answer>
     </tns:row>
    </tns:rowset>

    Die Funktion OPENXML wird verwendet, um die zurückgegebene XML-Zeichenfolge syntaktisch zu analysieren. Sie extrahiert den Wert, der den Wert in Celsius darstellt.

  6. Rufen Sie die gespeicherte Prozedur auf, um die Anforderung zu senden und die Antwort zu erhalten.

    CALL FahrenheitToCelsius(212);

    Die Temperatur in Fahrenheit und die Entsprechung in Celsius werden angezeigt.

    temperature Celsius
    212.0 100.0

Ein SQL Anywhere-Webdienst kann als Funktion oder als Prozedur deklariert werden. Eine Deklaration einer SQL Anywhere-Clientfunktion beschränkt alle Parameter effizient auf den IN-Modus (Parameter können von der aufgerufenen Funktion nicht zugewiesen werden). Beim Aufruf einer SQL Anywhere-Webdienstfunktion wird die unformatierte SOAP-Rahmenantwort zurückgegeben, während eine Prozedur eine Ergebnismenge zurückgibt.

Den create/alter procedure/function-Anweisungen wurde eine SOAPHEADER-Klausel hinzugefügt. Ein SOAP-Header kann als statische Konstante deklariert oder dynamisch mithilfe der Parameterersetzungsmethode festgelegt werden. Eine Webdienstclient-Funktion kann eine oder mehrere Ersetzungsparameter im IN-Modus definieren, während eine Webdienstclient-Prozedur auch einen einzelnen INOUT- oder OUT-Ersetzungsparameter definieren kann. Aus diesem Grund kann eine Webdienstclient-Prozedur den SOAP-Antwort-Header mit einem OUT-Ersetzungsparameter (oder INOUT-Ersetzungsparameter) zurückgeben. Eine Webdienstfunktion muss den SOAP-Antwortrahmen syntaktisch analysieren, um die Header-Einträge zu erhalten.

Das folgende Beispiel zeigt, wie ein Client das Senden von mehreren Headereinträgen mit Parametern und das Empfangen der Antwort-SOAP-Header-Daten angeben kann.

CREATE PROCEDURE SoapClient( 
    INOUT hd1 VARCHAR, 
    IN hd2 VARCHAR, 
    IN hd3 VARCHAR ) 
  URL 'localhost/some_endpoint' 
  SOAPHEADER '!hd1!hd2!hd3';
Hinweise
Einschränkungen