Aufrufbare Interfaces aufrufen

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Clients für Web-Services schreiben


Damit ein aufrufbares Interface aufgerufen werden kann, müssen in der Client-Anwendung alle Definitionen der aufrufbaren Interfaces und der Remotable-Klassen vorliegen, in denen komplexe Typen implementiert werden.

Wenn der Server in Delphi oder C++Builder geschrieben wurde, können Sie anstelle der Dateien, die durch das Importieren einer WSDL-Datei generiert werden, die Units verwenden, die auch von der Server-Anwendung zum Definieren und Registrieren dieser Interfaces und Klassen herangezogen werden. Stellen Sie dabei sicher, dass die Unit beim Registrieren aufrufbarer Interfaces dieselbe Namespace-URI und denselben SOAP-Aktions-Header verwendet. Diese Werte können explizit im Quelltext zur Registrierung des Interface angegeben oder aber automatisch generiert werden. Wenn sie automatisch generiert werden, muss die Unit, welche das Interface definiert, sowohl im Client als auch im Server denselben Namen tragen, und in beiden muss die globale Variable AppNameSpacePrefix den gleichen Wert aufweisen.

Nachdem Sie über die Definition des aufrufbaren Interface verfügen, gibt es zwei Möglichkeiten, eine aufrufbare Instanz zu erhalten:

  • Wenn Sie ein WSDL-Dokument importiert haben, generiert das Importprogramm automatisch eine globale Funktion, welche das Interface zurückgibt, das Sie anschließend aufrufen können.
  • Sie können ein externes Interface-Objekt verwenden.

Ein aufrufbares Interface von der generierten Funktion anfordern

Das WSDL-Importprogramm generiert automatisch eine Funktion, von der Sie die importierten aufrufbaren Interfaces anfordern können. Wenn Sie beispielsweise ein WSDL-Dokument importiert haben, das ein aufrufbares Interface namens IServerInterface definiert, würde die generierte Unit die folgende globale Funktion enthalten:

function GetIServerInterface(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IServerInterface;
 
_di_IServerInterface GetIServerInterface(bool UseWSDL, AnsiString Addr, THTTPRIO* HTTPRIO);

Die generierte Funktion verarbeitet drei Parameter: UseWSDL, Addr und HTTPRio. UseWSDL zeigt an, ob die Adresse des Servers in einem WSDL-Dokument gesucht werden soll (True) oder ob die Client-Anwendung die URL des Servers bereitstellt (False).

Wenn UseWSDL den Wert False besitzt, repräsentiert Addr die URL für den Web-Service. Hat UseWSDL den Wert True, dann bezeichnet Addr die URL eines WSDL-Dokuments, die den aufgerufenen Web-Service beschreibt. Wenn Sie für diesen Parameter einen leeren String übergeben, wird standardmäßig das von Ihnen importierte Dokument durchsucht. Dieser zweite Ansatz ist der bessere, wenn Sie mit der Möglichkeit rechnen, dass sich die URL des Web-Service oder einzelne Informationen wie der Namespace oder der SOAP-Action-Header ändern. Bei Verwendung des zweiten Verfahrens werden die Informationen dynamisch jeweils dann abgerufen, wenn Ihre Anwendung den Methodenaufruf durchführt.

Hinweis: Aus Gründen der Performance ist es besser, eine URL anstelle eines WSDL-Parameters zu verwenden. Bei WSDL muss die SOAP-Laufzeit ein HTTP GET für den WSDL-Parameter vor Aufruf einer Web-Service-Operation ausführen. Der Parameter HTTPRio legt das Remote-Interface-Objekt fest, das zum Ermitteln des Interface verwendet werden soll. Wenn Sie den Wert NULL für den Parameter HTTPRio festlegen, erstellt die Methode eine neue THTTPRio-Instanz. Sie können die THTTPRio-Instanz angeben, wenn Sie mit dem Objektinspektor das Objekt und die Behandlungsereignisse anpassen möchten.</span>

Hinweis: Die generierte Funktion verwendet zur Implementierung des aufrufbaren Interface ein internes Remote-Interface-Objekt. Wenn Sie diese Funktion verwenden und feststellen, dass Sie auf das zugrundeliegende externe Interface-Objekt zugreifen müssen, können Sie von dem aufrufbaren Interface ein IRIOAccess-Interface anfordern und anschließend mit dessen Hilfe auf das externes Interface-Objekt zugreifen:

 var
   Interf: IServerInterface;
   RIOAccess: IRIOAccess;
   X: THTTPRIO;
 begin
   Intrf := GetIServerInterface(True,
           'http://MyServices.org/scripts/AppServer.dll/wsdl');
   RIOAccess := Intrf as IRIOAccess;
   X := RIOAccess.RIO as THTTPRIO;
 
 _di_EchoUnboundedSoap service = GetEchoUnboundedSoap();
   _di_IRIOAccess rioAccess = service;
   TSOAPConvertOptions options = rioAccess->GetRIO()->Converter->GetOptions();

Ein externes Interface-Objekt verwenden

Falls Sie das aufrufbare Interface, das aufgerufen werden soll, nicht mithilfe der globalen Funktion ermitteln, dann können Sie eine Instanz von SoapHTTPClient.THTTPRio für das gewünschte Interface erstellen.

 X := THTTPRio.Create(nil);
 
 X = new THTTPRio(NULL);

Hinweis: Beachten Sie unbedingt, dass die THTTPRio-Instanz nicht explizit zerstört werden darf. Wurde die Instanz ohne einen Besitzer erstellt (wie in der obigen Code-Zeile), gibt sie sich automatisch selbst frei, sobald das zugehörige Interface freigegeben wird. Wurde sie mit einem Besitzer (Owner-Attribut) erstellt, ist der Besitzer für die Freigabe der THTTPRio-Instanz verantwortlich.

Nachdem Sie über das THTTPRio-Objekt verfügen, müssen Sie ihm die Informationen bereitstellen, die es zur Identifizierung des Server-Interface und Bestimmung der Adresse des Servers benötigt. Es gibt zwei Möglichkeiten, um diese Informationen zur Verfügung zu stellen:

Wenn Sie nicht erwarten, dass sich die URL für den Web-Service oder die erforderlichen Namespaces und SOAP-Action-Header ändern, genügt es, einfach die URL für den gewünschten Web-Service anzugeben. THTTPRio verwendet diese URL, um die Definition des Interface sowie die Namespace- und Header-Informationen basierend auf den in der Aufruf-Registrierung enthaltenen Informationen abzurufen. Sie geben die URL an, indem Sie die Eigenschaft URL auf die Adresse des Servers setzen.

 X.URL := 'http://www.myco.com/MyService.dll/SOAP/IServerInterface';

Wenn Sie die URL, den Namespace oder den SOAP-Action-Header dynamisch zur Laufzeit aus dem WSDL-Dokument abrufen möchten, können Sie die Eigenschaften WSDLLocation, Service und Port verwenden, durch welche die erforderlichen Information aus dem WSDL-Dokument extrahiert werden:

 X.WSDLLocation := 'Cryptography.wsdl';
 X.Service := 'Cryptography';
 X.Port := 'SoapEncodeDecode';

Nachdem Sie festgelegt haben, wie der Server zu suchen und das Interface zu identifizieren sind, können Sie vom THTTPRio-Objekt einen Interface-Zeiger für das aufrufbare Interface anfordern. Sie erhalten diesen Interface-Zeiger mithilfe des as-Operators. Wandeln Sie dazu einfach die THTTPRio-Instanz in das aufrufbare Interface um:


 InterfaceVariable := X as IEncodeDecode;
 Code := InterfaceVariable.EncodeValue(5);
 
 _di_IEncodeDecode InterfaceVariable;
 if (X->QueryInterface(InterfaceVariable) == S_OK)
 {
   Code = InterfaceVariable->EncodeValue(5);
 }

Dabei erstellt THTTPRio eine VTable für das entsprechende Interface dynamisch im Arbeitsspeicher, was Ihnen die Durchführung von Interface-Aufrufen ermöglicht.

THTTPRio ist auf die Aufruf-Registrierung angewiesen, wenn es darum geht, Informationen über das aufrufbare Interface einzuholen. Wenn die Client-Anwendung nicht über eine Aufruf-Registrierung verfügt oder wenn das aufrufbare Interface nicht registriert ist, kann THTTPRio im Speicher keine VTable aufbauen.

Warnung: Wenn Sie das von THTTPRio erhaltene Interface einer globalen Variablen zuweisen, müssen Sie diese Zuweisung auf nil ändern, bevor Sie die Anwendung beenden. Wenn beispielsweise InterfaceVariable im obigen Code-Beispiel keine Stack-Variable, sondern eine globale Variable darstellt, müssen Sie das Interface freigeben, damit das Objekt THTTPRio freigegeben wird. Normalerweise gehört dieser Code in die OnDestroy-Ereignisbehandlung des Formulars bzw. Datenmoduls:

 procedure TForm1.FormDestroy(Sender: TObject);
 begin
   InterfaceVariable := nil;
 end;
 void __fastcall TForm1::FormDestroy(TObject *Sender)
 {
   InterfaceVariable = NULL;
 }

Der Grund dafür, dass globale Interface-Variablen auf nil gesetzt werden müssen, besteht darin, dass THTTPRio seine VTable dynamisch im Speicher aufbaut. Diese VTable muss auch dann noch vorliegen, wenn das Interface freigegeben wird. Wenn Sie das Interface nicht gemeinsam mit dem Formular oder Datenmodul freigeben, erfolgt die Freigabe, wenn beim Herunterfahren die globale Variable freigegeben wird. Der von globalen Variablen belegte Speicher kann nach dem Formular oder Datenmodul freigegeben werden, in dem das THTTPRio-Objekt enthalten ist. In diesem Fall ist die VTable nicht verfügbar, wenn das Interface freigegeben wird.

Siehe auch