Web Serwisy SOAP i serwer aplikacji PAS cz.I

Tak się złożyło, że ostatnio kilkakrotnie byłem pytany przez klientów o  wystawianie web serwisów typu SOAP. Takie serwisy określane są czasem jako te “stare” w stosunku do serwisów typu REST. Są większym obciążeniem dla sieci (format danych XML) ale od wielu lat umożliwiają integrację/wymianę danych między różnymi systemami. Wspierane są też przez tradycyjny OpenEdge AppServer.

Pytanie, na które teraz należy odpowiedzieć to, czy nowy serwer aplikacji PASOE, lub jak kto woli PAS (Progress Application Server for OpenEdge) obsługuje także serwisy SOAP.

Żeby odpowiedzieć na to pytanie przyjrzyjmy się najpierw właściwościom pliku dla lokalnej instancji serwera w katalogu roboczym …\oepas1\conf\openedge.properties. W pliku tym znajdziemy wpisy:

[oepas1.ROOT.SOAP],

[oepas1.ROOT.REST],

[oepas1.ROOT.WEB],

[oepas1.ROOT.APSV].

Są to cztery warstwy transportowe; dla każdej zainstalowany i skonfigurowany jest adapter. Żeby wiedzieć czy dany adapter jest włączony trzeba sprawdzić ustawienie adapterEnabled; jeśli 1 to włączony. Pamiętajmy, że te ustawienia lepiej zmieniać poleceniem z linii komend niż bezpośrednio w pliku, a więc np.:
oeprop oepas1.ROOT.SOAP.adapterEnabled=1

Innym miejscem gdzie możemy sprawdzić powyższe ustawienia jest OpenEdge Explorer. Należy otworzyć widok w instancji serwera dla aplikacji webowej ABL ROOT (ABL WebApp: ROOT).

OK, ale jak w ogóle przygotować kod aplikacji do wystawienia za pomocą serwisu SOAP? Pierwszy etap jest dokładnie taki sam jak dla klasycznego AppServera. Ponieważ nie wszyscy korzystali dotychczas z tej metody omówimy ją na prostym przykładzie.

Mamy 2 oddzielne procedury, które chcemy wyświetlić w postaci web serwisów. Pierwsza FindCustomerByName.p zwraca numer rekordu Customer dla zadanej wartości Name.

DEFINE INPUT PARAMETER NAME AS CHARACTER.
DEFINE INPUT-OUTPUT PARAMETER CustomerNumber AS INTEGER.

FIND FIRST Customer WHERE Customer.NAME = NAME NO-ERROR.
IF AVAILABLE Customer THEN
    CustomerNumber = Customer.CustNum.
ELSE
    CustomerNumber = ?.

Druga procedura GetOrderDetails.p zwraca tablicę tymczasową zawierającą dane zamówień dla wybranego rekordu Customer.

DEFINE INPUT PARAMETER thisCust AS INTEGER NO-UNDO.

DEFINE TEMP-TABLE OrderDetails
    FIELD OrderNum LIKE Order.OrderNum
    FIELD SalesRep LIKE Order.SalesRep
    FIELD OrderDate LIKE Order.OrderDate
    FIELD ShipDate LIKE Order.ShipDate
    FIELD TotalDollars AS DECIMAL
    FIELD OrderStatus LIKE Order.OrderStatus.
    
DEFINE OUTPUT PARAMETER TABLE FOR OrderDetails.

FUNCTION GetTotalDollars RETURNS DECIMAL PRIVATE
  (OrderNum AS INTEGER)  FORWARD.

FIND FIRST Customer WHERE Customer.CustNum = thisCust NO-ERROR.
IF NOT AVAILABLE Customer THEN RETURN ERROR. 

EMPTY TEMP-TABLE OrderDetails.

FOR EACH Order WHERE Order.CustNum = thisCust:
    CREATE OrderDetails.
        ASSIGN 
            OrderDetails.OrderNum = Order.OrderNum
            OrderDetails.SalesRep = Order.SalesRep
            OrderDetails.OrderDate = Order.OrderDate
            OrderDetails.ShipDate = Order.ShipDate
            OrderDetails.OrderStatus = Order.OrderStatus.

        OrderDetails.TotalDollars = GetTotalDollars(Order.OrderNum).
END.

FUNCTION GetTotalDollars RETURNS DECIMAL PRIVATE
  (OrderNum AS INTEGER) :

    DEFINE VARIABLE TotalDollars AS DECIMAL NO-UNDO INITIAL 0.0.

    FOR EACH OrderLine WHERE OrderLine.OrderNum = OrderNum:
        TotalDollars = TotalDollars + OrderLine.ExtendedPrice.
    END.
    RETURN TotalDollars.
END FUNCTION.

Obie procedury kompilujemy do postaci r-kodu.
Teraz otwieramy narzędzie Proxy Generator. Służy ono do generowania plików tzw. proxy do integracji z interfejsem Javy i .NET, a także do definiowania web serwisów SOAP.
Definiowanie serwisów jest bardzo proste. Tworzymy nowy projekt np. CustOrder i podajemy ścieżkę do r-kodów.

Następnie w menu Procedure -> Add dodajemy 2 r-kody jako procedury Non-persistent.

Teraz przechodzimy do ustawień: Options -> Preferences. Ustawiamy Client type: Web Service oraz Output directory gdzie zostaną zapisane wygenerowane pliki. Pozostałe ustawienia są wykorzystywane dla klasycznego AppServera i zostaną zignorowane przez serwer PASOE. Przypominam, że dla nowego serwera aplikacji nie trzeba instalować i konfigurować JSE, adaptera WSA ponieważ te elementy są już wbudowane w produkt.

Teraz wybieramy opcję Generate i OK. W wybranym katalogu pojawiły się pliki CustOrder.wsm oraz CustOrder.wsdl (oraz log).
O tym jak wykorzystać te pliki i jak wdrożyć web serwis w serwerze aplikacji PASOE napiszę następnym razem.