PASOE i serwisy WebHandler cz. I
Deweloperzy aplikacji webowych z wykorzystaniem serwera PASOE mają od wersji 11.6.3 nową możliwość tworzenia serwisów typu Data Object. Są to tzw. WebHandlery, które działają z wykorzystaniem warstwy transportowej WEB (Data Object WebHandler Service).
WebHandler zapewnia bardziej wydajną i prostszą warstwę komunikacyjną niż REST. Jest napisany w ABL, łatwiej dopasować go do własnych potrzeb i ma ulepszone możliwości debugowania. Podstawową zaletą WebHandlera jest to, że daje programistom pełną kontrolę nad przychodzącymi i wychodzącymi danymi.
Warstwa WEB obsługuje żądania (requests) i odpowiedzi (responses), które używają standardowych czasowników HTTP (verbs). Obejmuje to interakcje z klientami, takimi jak WebSpeed i OpenHTTP.
Jeśli chcesz zmienić domyślny adres URL, możesz dodać dodatkowe WebHandlery i zmapować je na różne adresy URL lub zmienić odwzorowania domyślnych WebHandlerów.
Dodatkowe WebHandlery można dodać w pliku openedge.properties dla instancji OEPAS i zmapować je na określone adresy URL. Na przykład:
defaultHandler=OpenEdge.Web.CompatibilityHandler
webhandler1=MyHandler:/mycustomer
webhandler2=MyHandler:/mycustomer/{custid}
OpenEdge.Web.CompatibilityHandler zapewnia kompatybilność z aplikacjami WebSpeed SpeedScript i CGI Wrapper. Jest to domyślny handler używany w instancji w środowisku programistycznym.
Tworzenie tych serwisów zilustruję dwoma przykładami zaczerpniętymi z bazy wiedzy.
Zaczynamy od założenia, że mamy instancję serwera PASOE z podłączoną bazą danych sports2000.
Tworzymy nowy projekt OpenEdge. Nadajemy mu nazwę np. webh1, wybieramy typ Server i zaznaczamy warstwę transportową WEB.

Klikamy Next, sprawdzając czy do projektu jest podłączona instancją serwera aplikacji, a w ostatnim kroku upewniamy się, że jest przyłączona nasza baza danych.

Kreator tworzy od razu klasę WebHandlera, w tym przypadku webh1Handler.cls, zawierającą 3 metody: HandleNotAllowedMethod, HandleNotImplemented oraz HandleGet. Dwie pierwsze są związane z wychwytywaniem błędów. HandleGet to główna metoda, w której można przetwarzać dane otrzymane z odpowiedzi (response).
Stworzymy teraz obiekt danych. W Project Explorerze zaznaczamy nazwę projektu i prawym klikiem myszy wybieramy New -> Business Entity.

Podajemy nazwę customerBE, klikamy Next i wybieramy z bazy tabelę customer.

W efekcie jest utworzona znana z poprzednich artykułów klasa customerBE.cls.
Do klasy tej będziemy odnosić się z WebHandlera, czyli pliku webh1Handler.cls. Teraz należy zmodyfikować metodę HandleGet aby miała postać tak jak w poniższej klasie webh1Handler.cls (można skopiować cały plik klasy).
Widać, że oprogramowanie metod wymaga znajomości programowania obiektowego i odpowiednich referencji, ale daje bardzo duże możliwości. W poniższym przykładzie w odpowiedzi HTTP pobierana jest zawartość tablicy ttCustomer (z obiektu customerBE) i wyświetlana poprzez obiekt JSON.
USING Progress.Lang.*.
USING OpenEdge.Web.WebResponseWriter.
USING OpenEdge.Net.HTTP.StatusCodeEnum.
USING OpenEdge.Web.WebHandler.
USING customerBE.*.
USING Progress.Json.ObjectModel.*.
BLOCK-LEVEL ON ERROR UNDO, THROW.
CLASS webh1Handler INHERITS WebHandler:
{"customerbe.i"}
/*------------------------------------------------------------------------------
Purpose: Handler for unsupported methods. The request being serviced and
an optional status code is returned. A zero or null value means
this method will deal with all errors.
Notes:
------------------------------------------------------------------------------*/
METHOD OVERRIDE PROTECTED INTEGER HandleNotAllowedMethod( INPUT poRequest AS OpenEdge.Web.IWebRequest ):
/* Throwing an error from this method results in a 500/Internal Server Error response.
The web handler will attempt to log this exception.
See the HandleGet method's comments on choosing a value to return from this method. */
UNDO, THROW NEW Progress.Lang.AppError("METHOD NOT IMPLEMENTED").
END METHOD.
/*------------------------------------------------------------------------------
Purpose: Handler for unknown methods. The request being serviced and an
optional status code is returned. A zero or null value means
this method will deal with all errors.
Notes:
------------------------------------------------------------------------------*/
METHOD OVERRIDE PROTECTED INTEGER HandleNotImplemented( INPUT poRequest AS OpenEdge.Web.IWebRequest ):
/* Throwing an error from this method results in a 500/Internal Server Error response.
The web handler will attempt to log this exception.
See the HandleGet method's comments on choosing a value to return from this method. */
UNDO, THROW NEW Progress.Lang.AppError("METHOD NOT IMPLEMENTED").
END METHOD.
/*------------------------------------------------------------------------------
Purpose: Default handler for the HTTP GET method. The request being
serviced and an optional status code is returned. A zero or
null value means this method will deal with all errors.
Notes:
------------------------------------------------------------------------------*/
METHOD OVERRIDE PROTECTED INTEGER HandleGet( INPUT poRequest AS OpenEdge.Web.IWebRequest ):
DEFINE VARIABLE oResponse AS OpenEdge.Net.HTTP.IHttpResponse NO-UNDO.
DEFINE VARIABLE oWriter AS OpenEdge.Web.WebResponseWriter NO-UNDO.
DEFINE VARIABLE oBody AS OpenEdge.Core.String NO-UNDO.
DEFINE VARIABLE beCustomer AS customerBE NO-UNDO.
DEFINE VARIABLE pcFilter AS CHAR NO-UNDO.
DEFINE VARIABLE lcJSON AS LONGCHAR NO-UNDO.
DEFINE VARIABLE jObj AS JsonObject.
DEFINE VARIABLE htt AS HANDLE.
jObj = NEW JsonObject().
/* Get data from the BE */
beCustomer = NEW customerBE().
beCustomer:ReadcustomerBE(INPUT pcfilter,OUTPUT DATASET dsCustomer).
htt = TEMP-TABLE ttCustomer:HANDLE.
htt:WRITE-JSON("JsonObject", jObj).
ASSIGN
oResponse = NEW OpenEdge.Web.WebResponse()
oResponse:StatusCode = INTEGER(StatusCodeEnum:OK)
.
/* This body object can be a string or something else (JsonObject for instance) */
lcJSON= jObj:GetJsonText().
ASSIGN
oBody = NEW OpenEdge.Core.String(lcJSON).
ASSIGN
oResponse:Entity = oBody
/* HTTP messages require a content type */
oResponse:ContentType = 'application/json':u
/* ContentLength is good too */
oResponse:ContentLength = oBody:Size
.
/* The WebResponseWriter ensures that the status line and
all headers are writted out before the message body/entity. */
ASSIGN
oWriter = NEW WebResponseWriter(oResponse).
oWriter:Open().
/* Finish writing the response message */
oWriter:Close().
/* A response of 0 means that this handler will build the entire response;
a non-zero value is mapped to a static handler in the webapp's /static/error folder.
The mappings are maintained in the webapps's WEB-INF/web.xml
A predefined set of HTTP status codes is provided in the OpenEdge.Net.HTTP.StatusCodeEnum
enumeration */
RETURN 0.
END METHOD.
END CLASS.
W przeglądarce wpisujemu URL dla naszej instancji PASOE np.: http://localhost:8810/webh1/web/webh1 (lub https://localhost:8811/webh1/web/webh1 dla bezpiecznego połączenia).
W efekcie dostajemy ekran podzielony na 3 przekładki:
JSON

Raw Data

Headers
