Donnerstag, 1. November 2018

VFP, das Web und der ganze ReST - 6 - kleine Denkpause gefällig? / VFP, the web and all the ReST - 6 - in need of a reflection period?

6. Kleine Denkpause gefällig? / in need of a reflection period?


Nachdem nun die Übertragung an den Webservice initiiert wurde bleibt uns als nächstes nur eines: Warten...

Das hört sich schlimmer an als es tatsächlich ist. Rufen wir uns an dieser Stelle mal das uralte Grundprinzip der EDV ins Gedächtnis zurück: EVA

    E ingabe
    V erarbeitung
    A usgabe

Als Entwickler haben wir uns dieses Prinzip vermutlich schon so verinnerlicht, dass wir es gar nicht mehr bewusst zur Kenntnis nehmen 😊.

Unser oXmlHttp.Send() ist die Eingabe die der Server entgegen nimmt.

In dem Augenblick in dem die Daten beim Zielserver ankommen beginnt dort die Verarbeitung. Diese kennt jedoch verschiedene Stufen.

Wie der aktuelle Stand der Dinge beim Server aussieht, darüber gibt uns die oXmlHttp.Status Eigenschaft Auskunft. Sie liefert uns alle möglichen Werte darüber, was bei der Verarbeitung so alles passiert ist. Aber ungeachtet der vielen verschiedenen Werte interessiert uns für die weitere Verarbeitung bzw. für den Empfang der Daten nur ein einziger Status.

Sobald wir den Wert 200 geliefert bekommen bedeutet dies, dass der Webservice Daten zur Ausgabe bereithält. Alle anderen Statuswerte ermöglichen uns eine gezielte Reaktion auf Probleme, die bei der Kommunikation zum und vom Server auftreten könnten.

Auf dieser Seite findet Ihr eine umfangreiche Liste der möglichen Werte:

https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms767625(v%3Dvs.85)

Wie bereits geschrieben bedeutet der Status 200 dass die Verarbeitung erfolgreich abgeschlossen wurde und nun das Ergebnis abgerufen werden kann.
Uns interessiert jedoch nicht, was der Service gerade so anstellt. Uns interessiert nur, ob unsere Anfrage angekommen ist, ob sie zur Verarbeitung angenommen wurde, ob die Verarbeitung noch läuft und ob die Verarbeitung abgeschlossen ist.  Beim letzten Punkt steht dann auch hoffentlich ein Status 200 bereit.

Hierbei müssen wir uns darüber im klaren sein, dass eine abgeschlossene Verarbeitung nicht automatisch auch eine erfolgreiche Verarbeitung bedeutet.

Zunächst benötigen wir also eine kleine Schleife die immer wieder beim Service anfragt ob er mit der Verarbeitung fertig ist. Für diese Schleife greifen wir auf eine andere Eigenschaft des oXmlHttp-Objektes zu, den oXmlHttp.ReadyState. Diese Eigenschaft reduziert sich auf den eigentlichen Stand der Verarbeitung nach dem EVA Prinzip.

  • Wurde eine Verbindung zum Server hergestellt
  • wurden die Daten erfolgreich an den Webservice übermittelt
  • werden die übermittelten Daten verarbeitet
  • ist die Verarbeitung abgeschlossen und kann die Antwort abgerufen werden.
Siehe hierzu auch:

https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms761388(v%3dvs.85)

Wird der letzte dieser vier Punkte gemeldet, dann ist es Zeit in Erfahrung zu bringen, ob bei der Verarbeitung alles glatt gelaufen ist und wir tatsächlich Daten abrufen können.

In der Praxis sieht es also so aus, dass wir in einer Schleife den .ReadyState = 4 prüfen und anschließend den .Status = 200 und erst wenn beide Eigenschaften uns sozusagen ihr GO gegeben haben, dann können wir auch wirklich Daten vom Webservice abrufen.

DECLARE Sleep IN Win32API INTEGER nMilliseconds
DO WHILE .T.
    DO CASE 
    CASE oXmlHttp.ReadyState = 0
        =myFormObj.StatusOutput( [(0) request not initialized] )
    CASE oXmlHttp.ReadyState = 1
        =myFormObj.StatusOutput( [(1) server connection established] )
    CASE oXmlHttp.ReadyState = 2
        =myFormObj.StatusOutput( [(2) request received] )
    CASE oXmlHttp.ReadyState = 3
        =myFormObj.StatusOutput( [(3) processing request] )
    CASE oXmlHttp.ReadyState = 4
        =myFormObj.StatusOutput( [(4) request finished and response is ready] )
        EXIT
    ENDCASE 
    =sleep(200)
ENDDO 
CLEAR DLLS [Sleep]
IF oXmlHttp.status != 200
    *// Something went wrong, so this is the time to call a routine
    *// that visualizes the state from oXmlHttp.status
    =GiveFeedback( oXmlHttp.status )
ELSE
    *// everything went fine, so we can read the data
ENDIF

Bekommen wir den Status 200 gemeldet, dann beginnt der nächste Schritt, andernfalls sollten ein paar Informationen bzgl. der aufgetretenen Probleme ausgegeben werden.

Hierbei sind nicht alle Statuswerte zwingend auf Fehler zurückzuführen und müssen somit auch nicht explizit innerhalb der Feedbackroutine verarbeitet werden.

FUNCTION GiveFeedback as Boolean
LPARAMETERS vStatus as Integer

    DO CASE 
    CASE m.vStatus = 100
         lcInfo = [Continue]
    CASE m.vStatus = 101
         lcInfo = [Switching protocols]
         
    * // #######################################################
    * // this Block (201/202/203/204/205/206) might not be part
    * // of the error handling and could be used for further
    * // Web Service handling because of non-default data
    CASE m.vStatus = 201
         lcInfo = [Created]
    CASE m.vStatus = 202
         lcInfo = [Accepted]
    CASE m.vStatus = 203
         lcInfo = [Non-Authoritative Information]
    CASE m.vStatus = 204
         lcInfo = [No Content]
    CASE m.vStatus = 205
         lcInfo = [Reset Content]
    CASE m.vStatus = 206
         lcInfo = [Partial Content]
    * // #######################################################
         
    CASE m.vStatus = 300
         lcInfo = [Multiple Choices]
    CASE m.vStatus = 301
         lcInfo = [Moved Permanently]
    CASE m.vStatus = 302
         lcInfo = [Found]
    CASE m.vStatus = 303
         lcInfo = [See Other]
    CASE m.vStatus = 304
         lcInfo = [Not Modified]
    CASE m.vStatus = 305
         lcInfo = [Use Proxy]
    CASE m.vStatus = 307
         lcInfo = [Temporary Redirect]
    CASE m.vStatus = 400
         lcInfo = [Bad Request]
    CASE m.vStatus = 401
         lcInfo = [Unauthorized]
    CASE m.vStatus = 402
         lcInfo = [Payment Required]
    CASE m.vStatus = 403
         lcInfo = [Forbidden]
    CASE m.vStatus = 404
         lcInfo = [Not Found]
    CASE m.vStatus = 405
         lcInfo = [Method Not Allowed]
    CASE m.vStatus = 406
         lcInfo = [Not Acceptable]
    CASE m.vStatus = 407
         lcInfo = [Proxy Authentication Required]
    CASE m.vStatus = 408
         lcInfo = [Request Timeout]
    CASE m.vStatus = 409
         lcInfo = [Conflict]
    CASE m.vStatus = 410
         lcInfo = [Gone]
    CASE m.vStatus = 411
         lcInfo = [Length Required]
    CASE m.vStatus = 412
         lcInfo = [Precondition Failed]
    CASE m.vStatus = 413
         lcInfo = [Request Entity Too Large]
    CASE m.vStatus = 414
         lcInfo = [Request-URI Too Long]
    CASE m.vStatus = 415
         lcInfo = [Unsupported Media Type]
    CASE m.vStatus = 416
         lcInfo = [Requested Range Not Suitable]
    CASE m.vStatus = 417
         lcInfo = [Expectation Failed]
    CASE m.vStatus = 500
         lcInfo = [Internal Server Error]
    CASE m.vStatus = 501
         lcInfo = [Not Implemented]
    CASE m.vStatus = 502
         lcInfo = [Bad Gateway]
    CASE m.vStatus = 503
         lcInfo = [Service Unavailable]
    CASE m.vStatus = 504
         lcInfo = [Gateway Timeout]
    CASE m.vStatus = 505
         lcInfo = [HTTP Version Not Supported]
    ENDCASE 
    MESSAGEBOX( ;
        [A problem has occured with the webservice] + CHR( 13 ) + lcInfo , ;
        0+16+0, ;
        [Web Processing Problem] ;
        )
ENDFUNC 

Im nächsten Kapitel geht es dann mit dem Empfang der Daten weiter...


Links zu den restlichen Kapiteln:

Einführung / Introduction 

Teil 1: Abkürzungen und was sie bedeuten
           / Abbreviations and their meaning

Teil 2: Wer ReST sagt, sagt auch JSON
          / In for a ReST, in for a JSON

Teil 3: Leerzeichen und andere Entitäten
          / BLANKS and other entities

Teil 4: JSON und der goldene Konverter
          / JSON and the golden converter

Teil 5: Die Startvorbereitungen
          / preparations for launch

Teil 6: Kleine Denkpause gefällig?
          / in need of a reflection period?

Teil 7: Fertig machen zur Landung
          / preparing for landing


Keine Kommentare:

Kommentar veröffentlichen