Tworzenie projektów w OE Developer Studio 11.7.2

Podczas kilku wcześniejszych artykułów pokazywałem jak utworzyć różne proste projekty w OpenEdge Developer Studio. Służyły one np. do wystawienia serwisów REST z wykorzystaniem obiektów JSDO i automatycznym generowaniem klas lub bardziej złożone z ręcznym mapowaniem parametrów. Przykłady te dotyczyły nowego serwera PASOE choć można było wykorzystać także klasyczny AppServer.

Takie tworzenie projektów odbywa się poprzez tzw. wizardy, których zadaniem jest “poprowadzenie za rękę” dewelopera, aby ułatwić mu życie. Jeśli idzie o intuicyjność wizardów, np. dla projektów typu OpenEdge, których jest kilka rodzajów, to pozostawiały one nieco do życzenia i bez znajomości zdobytej np. poprzez webinary lub dokukmentację łatwo można było popełnić błąd.

W ostatnich wersjach OpenEdge proces ten został poprawiony a jego klarowność jest zdecydowanie lepsza.

Tworząc nowy projekt typu OpenEdge od razu pojawia się okno (poniżej), w którym rodzaje projektów są pogrupowane w 3 grupy: Server, Client, General. Wybierając grupę i typ projektu w polu Description pojawia się krótki opis.


W grupie Server można zdecydować czy wykorzystany będzie serwer PASOE czy klasyczny AppServer.

Dla PASOE można dalej wybrać warstwę transportową: APSV, REST lub WEB.
Pierwsze dwie warstwy były omawiane na tym blogu. APSV służy do obsługi procedur ABL poprzez HTTP.
REST to projekt, w którym możemy wykorzystać wywołania RESTful API i ręcznie mapować wybrane pola. Jeśli zaznaczymy Create a DataObject Service, będzie to projekt z automatycznym mapowaniem struktur ProDataSet do JSDO.

WEB służy do utworzenia projektu z wykorzystaniem wywołań RESTful API przez klasę WebHandler. Ten rodzaj nie był jeszcze omawiany na blogu.

Jeśli zamiast PASOE wybierzemy klasyczny AppServer to będziemy miali do wyboru 2 rodzaje: APSV i REST.

Grupa Client to przede wszystkim projekty związane z budowaniem aplikacji desktopowej, może to być aplikacja GUI for .NET, z wykorzystaniem AppBuildera lub znakowa (ChUI). Można także budować interfejs webowy WEB UI lub klasyczny WebSpeed.

Grupa General, to podstawowy projekt oraz pozostałe z grupy OpenEdge, np. Dynamics lub (omawiany na Pizza & Beer) ABLUnit do przeprowadzania testów ABL. Można wreszcie stworzyć projekt Custom z konfiguracją dopasowaną do własnych potrzeb.

Procedury ABL i serwer aplikacji PAS cz.II

Kontynuując omawianie różnych zagadnień związanych z uruchamianiem aplikacji ABL na serwerze PAS zobaczmy jak osiągnąć połączenie w różnych trybach pracy, charakterystycznych dla klasycznego AppSerwera, co może być istotne podczas procesu migracji aplikacji.

W poprzedniej części zobaczyliśmy jak przyłączyć się do serwera PAS w modelu session-free i session-managed. Wybór modelu należy do klienta, a nie serwera aplikacji, którego pojedyncza instancja potrafi obsłużyć jednocześnie oba modele.

Dla session-free nie potrzebne są żadne zmiany w aplikacji poza samą instrukcją przyłączenia.

Dla session-managed mamy w AppSerwerze 3 tryby pracy:

  • state-reset
  • state-aware
  • stateless

Tryby te związane są z zarządzaniem kontekstem między żądaniami i wprowadzono je dla ułatwienia procesu programowania.

Przywiązanie procesu agenta do określonej sesji klienta powoduje zachowanie kontekstu, ale zmniejsza skalowalność. Różne tryby pracy dają więc programoście możliwość wyboru. Istotne jest, że tryby te w klasycznym AppSerwerze wybiera się podczas jego startu i nie mogą być zmienione jak długo serwer pracuje.

Jeśli więc będziemy potrzebować wszystkie trzy tryby jednocześnie, należy uruchomić trzy procesy AppServera. W serwerze PAS wystarczy jeden proces, a sposób pracy określa jedynie kod programu klienckiego.

Przypomnijmy, że dla serwera PAS połączenie z wybraną sesją ABL może być warunkowo związane/zwolnione poprzez ustawienie atrybutu SESSION:SERVER-CONNECTION-BOUND-REQUEST.

Zdefiniujmy teraz dwie procedury:
bound.p

/* bound.p  */
.....
SESSION:SERVER-CONNECTION-BOUND-REQUEST = TRUE.

oraz unbound.p

/* unbound.p  */
.....
SESSION:SERVER-CONNECTION-BOUND-REQUEST = FALSE.
QUIT.

Pierwsza procedura (patrz poprzedni artykuł) wiąże sesję klienta ABL z sesją PAS, drugą ją zwalnia.
Przejdżmy teraz do ustawień serwera PAS w OE Explorer -> Startup Parameters and Environment. Możemy podać tu nazwy procedur dla różnych operacji. Podobne ustawienia są możliwe na klasycznych AppSerwerze.

Dla trybu state-reset wystarczy podać nazwy tych procedur dla Connect i Disconnect jak na powyższym rysunku. Komenda QUIT powoduje zresetowanie sesji ABL. Jeśli procedury te zawierają inne Wasze instrukcje, to instrukcja wiążąca powinna być na początku w bound.p a procedura zwalniająca i QUIT na końcu unbound.p.

Dla trybu state-aware postępujemy analogicznie, tylko że w procedurze unbound.p NIE umieszczamy instrukcji QUIT.

Dla trybu stateless nie trzeba robić żadnych zmian ponieważ wiązanie i zwalnianie sesji może wystąpić w różnych miejscach logiki biznesowej i zależy od dewelopera aplikacji.

Load Balancing. Jeśli posiadamy produkt Name Server Load Balancer, to może konfigurować balansowanie obciążeniem klasycznego AppSerwera. Polega to z grubsza na dodaniu logicznej nazwy serwisu w kilku instancjach AppSerwera i określeniu procentu obciążenia w polu Weight.

Serwer aplikacji PAS nie łączy się jednak przez Name Server i nie da się tego tutaj tak zrobić. Load balancing dla PASOE można skonfigurować korzystając ze standardów HTTP takich jak: Apache proxy host load balancing, Tomcat load balancing, Amazon load balancing. Zainteresowanych tym tematem odsyłam do dokumentacji: Progress® Application Server for OpenEdge®: Administration Guide.

Procedury ABL i serwer aplikacji PAS cz.I

Od kilku miesięcy informujemy o nowych możliwościach serwera aplikacji PAS. Pytanie co z uruchamianiem procedur ABL, które działały do tej pory na klasycznym AppSerwerze? Czy trzeba je modyfikować? Czy migracja jest trudna dla przeciętnego programisty? Na te i podobne pytania postaram się odpowiedzieć w tym i następnym artykule.

Zacznijmy od uruchomienia instancji serwera aplikacji PAS o nazwie oepas1 (podobnie jak w poprzednich artykułach).
Przypominam, że PAS jest podłączony do bazy sportsdb, a w PROPATH znajduje się podkatalog openedge, do którego skopiujemy procedury abl (patrz poniżej).

Do uruchamiania procedur openedge potrzebny jest aktywny adapter, obsługujący warstwę transportową apsv. Sprawdzamy czy jest on aktywny w OpenEdge Explorerze lub wpisując w przeglądarce url: localhost:[port]/apsv. Jak widać poniżej adapter jest aktywny.


Teraz możemy uruchomić na kliencie program podłączający się do serwera aplikacji i uruchamiający tę samą procedurę FindCustomerByName, którą uruchamialiśmy dla web serwisów SOAP.
Najpierw zrobimy to dla modelu SESSION-FREE.

/* SESSION-FREE  */

DEFINE VARIABLE hServer AS HANDLE NO-UNDO.
DEFINE VARIABLE lReturn AS LOGICAL NO-UNDO.
DEFINE VARIABLE CustomerNumber AS CHARACTER NO-UNDO.

CREATE SERVER hServer.
lReturn = hServer:CONNECT("-URL http://localhost:8810/apsv
  -sessionModel Session-free"). 

IF NOT lReturn THEN DO:
  DELETE OBJECT hServer NO-ERROR.
  RETURN ERROR "Failed to connect to the ABL web application: " + RETURN-VALUE.
END.

RUN FindCustomerByName ON hServer (INPUT "Lift Tours", INPUT-OUTPUT CustomerNumber).

MESSAGE CustomerNumber
    VIEW-AS ALERT-BOX INFORMATION BUTTONS OK.

lReturn = hServer:DISCONNECT().
DELETE OBJECT hServer NO-ERROR. 

Kod podłączenia i uruchomienia procedury jest bardzo podobny jak dla klasycznego AppServera.

W OpenEdge Explorerze w widoku Sessions widać otwartą sesję ze stanem Unbound (Bound=false), czyli sesja agenta nie jest powiązana z klientem.


Kod dla podłączenia w modelu SESSION-MANAGED różni się tylko dla metody CONNECT. Jego działanie jest identyczne jak w powyższym przykładzie.

/* SESSION-MANAGED */

DEFINE VARIABLE hServer AS HANDLE  NO-UNDO.
DEFINE VARIABLE lReturn AS LOGICAL NO-UNDO.
DEFINE VARIABLE CustomerNumber AS CHARACTER NO-UNDO.

CREATE SERVER hServer.
lReturn = hServer:CONNECT
  ("-URL http://localhost:8810/apsv","","").

IF NOT lReturn THEN DO:
  DELETE OBJECT hServer NO-ERROR.
  RETURN ERROR "Failed to connect to the ABL web application: " + RETURN-VALUE.
END.

RUN FindCustomerByName ON hServer (INPUT "Lift Tours", INPUT-OUTPUT CustomerNumber).

MESSAGE CustomerNumber
    VIEW-AS ALERT-BOX INFORMATION BUTTONS OK.

lReturn = hServer:DISCONNECT().
DELETE OBJECT hServer NO-ERROR. 

Ponieważ uruchomiłem 3 takie same programy na kliencie, to w widoku Agents mam co prawda dalej tylko jednego agenta, ale 3 jego sesje.


Żeby powiązać daną sesję agenta z klientem stosujemy tę samą sztuczkę jak w przypadku klasycznego AppSerwera: w procedurze uruchamianej na serwerze aplikacji dodajemy komendę:

SESSION:SERVER-CONNECTION-BOUND-REQUEST = TRUE.

Powiązanie stosuje się aby łatwiej zarządzać kontekstem, gdyż ta sama sesja agenta może obsłużyć kilka/wiele żądań pomiędzy aplikacją kliencką a daną sesją. Zwolnienie sesji odbywa się zazwyczaj przez uruchomienie tej samej komendy z wartością FALSE.  Poniżej, w widoku Sessions widać 3 sesje ze stanem Bound (Bound=true).


Ciąg dalszy niebawem w drugiej cześci…

Web Serwisy SOAP i serwer aplikacji PAS cz.II

W poprzedniej części wygenerowaliśmy 2 pliki r-kodów, które chcemy wystawić jako web serwisy SOAP. Mamy także wygenerowane przy pomocy narzędzia Proxy Generator pliki CustOrder.wsm oraz CustOrder.wsdl.

Plik .wsdl posłuży nam do wygenerowania dokumentacji o zdefiniowanym web serwisie. W oknie komend wpisujemy polecenie:

bprowsdldoc custorder.wsdl ./output

W podkatalogu output znajdziemy nowe pliki .html, zawierające informacje o zdefiniowanych procedurach, funkcjach itp. Są także przykłady kodu do przyłączenia i uruchomienia wybranej metody. Poniżej znajdują się definicje dwóch procedur z listą parametrów. Proszę zauważyć, że został automatycznie dodany parametr result.

Aby wdrożyć nowy web serwis musimy mieć instancję serwera PASOE. Posłużę sie tutaj tą samą instancją z przyłączoną bazą sports2000, jak opisałem w artykule o serwisach REST.

Kopiuję 2 r-kody do podkatalogu openedge w ścieżce PROPATH dla serwera aplikacji, a następnie uruchamiam komendę:

C:\WrkOpenEdge117\oepas1\bin\deploySOAP.bat custorder.wsm ROOT


Web serwis jest już wdrożony. Restartuję serwer aplikacji i przystępuję do testów. Najpierw FindCustomerByName.

DEFINE VARIABLE NAME AS CHARACTER NO-UNDO.
DEFINE VARIABLE CustomerNumber AS INTEGER NO-UNDO.
DEFINE VARIABLE result AS CHARACTER NO-UNDO.
    
DEFINE VARIABLE hWebService AS HANDLE NO-UNDO.
//DEFINE VARIABLE CustomerOrderObj AS HANDLE NO-UNDO.
DEFINE VARIABLE hPortType AS HANDLE NO-UNDO.

DEFINE VARIABLE lReturn AS LOGICAL NO-UNDO.

CREATE SERVER hWebService.

lReturn = hWebService:CONNECT("-WSDL 'http://192.168.1.21:8810/soap/wsdl?targetURI=CustOrder' 
                               -Port CustOrderObj").

RUN CustOrderObj SET hPortType ON SERVER hWebService.

RUN FindCustomerByName IN hPortType(INPUT "Lift Tours", INPUT-OUTPUT CustomerNumber, OUTPUT result).

MESSAGE CustomerNumber
    VIEW-AS ALERT-BOX INFORMATION BUTTONS OK.

W wyniku dostajemy nr klienta dla zadanej nazwy.

Test dla GetOrderDetails wygląda podobnie.

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 VARIABLE hWebService AS HANDLE NO-UNDO.
DEFINE VARIABLE CustomerOrderObj AS HANDLE NO-UNDO.
DEFINE VARIABLE hPortType AS HANDLE NO-UNDO.
DEFINE VARIABLE result AS CHARACTER NO-UNDO.
DEFINE VARIABLE lReturn AS LOGICAL     NO-UNDO.

CREATE SERVER hWebService.

lReturn = hWebService:CONNECT("-WSDL 'http://192.168.1.21:8810/soap/wsdl?targetURI=CustOrder' 
                               -Port CustOrderObj").

RUN CustOrderObj SET hPortType ON SERVER hWebService.

RUN GetOrderDetails IN hPortType(INPUT 3, OUTPUT RESULT, OUTPUT TABLE OrderDetails).


FOR EACH OrderDetails:
   DISPLAY OrderDetails.
END.

I wynik…

Pragnę zwrócić tutaj uwagę na dwie sprawy. Po pierwsze dla serwisów SOAP nie trzeba było definiować specjalnego projektu w OE Dev Studio. Po drugie nie trzeba było instalować i konfigurować Java Servlet Engine, Web Servera i WS adaptera, bo PASOE wszystko to już zawiera. To ogromne zaleta i ułatwienie pracy.
Życzę udanych projektów!

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.

Wystawianie serwisów REST z aplikacji ABL cz.II

Po dłuższej przerwie wracamy do zagadnienia związanego z udostępnieniem serwisu typu REST, który został zdefiniowany tutaj.

Taki zdefiniowany serwis trzeba wyeksportować. W tym celu klikamy prawym przyciskiem myszy na nazwę serwisu i wybieramy Export. Eksportowanie można zrobić na 2 sposoby: jako plik WAR lub ZIP. W pierwszym przypadku jest to oddzielny kompletny serwis, w drugim, serwis będzie doinstalowany do domyślnego serwisu ROOT  (Export services incrementally). Tutaj wybieram tę drugą metodę.


Proces wdrożenia przeprowadzimy na innej maszynie, na bazie danych sportsdb (kopia bazy sports2000).

Do wdrożenia potrzebny będzie plik klasy (customer.r) oraz oczywiście definicji serwisu (CustomerServ.zip).

Na nowej maszynie mamy instalację OpenEdge 11.7 z katalogiem roboczym C:\WrkOpenEdge117 i domyślną instalacją PAS: oepas1.

Najpierw w katalogu C:\WrkOpenEdge117\oepas1\openedge umieszczamy plik customer.r. Katalog ten znajduje się na liście PROPATH serwera aplikacji. W parametrach startowych agenta podajemy nazwę bazy, tutaj: -db sportsdb -ld sports2000. Parametr -ld (logiczna nazwa bazy) jest konieczny, ponieważ plik customer.r był skompilowany dla bazy sports2000. Zarówno PROPATH jak i parametry przyłączenia bazy można zobaczyć na poniższym obrazie.

Teraz nawigujemy do katalogu C:\WrkOpenEdge117\oepas1\webapps
gdzie umieszczamy plik CustomerServ.zip.

Uruchamiamy proenv i upewniamy się, że jesteśmy w powyższym katalogu. Podajemy komendę, która wdroży serwis przyrostowy dla ROOTa:

C:\WrkOpenEdge117\oepas1\bin\deployREST.bat CustomerServ.zip ROOT

Po zrestartowaniu serwera aplikacji serwis REST jest gotowy. Możemy go teraz przetestować. W tym celu w przeglądarce Chrome otwieramy Advanced REST client. Aplikacja jest typu application/json. Podajmy żądanie GET dla pobrania wybranego rekordu (metoda ReadCustomer): localhost:8810/rest/CustomerServService/Customers/5

Odpowiedź widać poniżej: rekord o nr 5 został pobrany i wyświetlony.

Podobnie sprawdzamy działanie metody ReadAllCustomers.

Wyświetlone są wszystkie rekordy.

Serwis działa poprawnie.

Następnym razem omówię trochę zapomniane web serwisy typu SOAP, ale wywoływane przez nowy serwer aplikacji PASOE.

Wystawianie serwisów REST z aplikacji ABL cz.I

We wcześniejszych wpisach opisałem sposób tworzenia serwisów uruchamianych na serwerze aplikacji PAS (obecna nazwa to Application Server for OpenEdge), korzystających z danych strukturalnych JSDO.

Pora teraz na bardziej praktyczny przykład, opisujący wystawienie własnych serwisów REST ze zdefiniowaniem wystawianych zasobów i ich mapowaniem. W porównaniu do wcześniejszej metody będzie więcej czynności do wykonania ale dostaniemy znacznie większe pole manewru.

Na początek mamy projekt CustomerServ typu OpenEdge i prostą aplikację – klasę ABL Customer.cls z metodami dla zasobu Customer: ReadCustomer, ReadAllCustoomers, UpdateCustomer.


Ważne jest aby te metody były state-free, tzn. nie przekazywały kontekstu między wywołaniami.

Teraz prawy klik myszy na nazwie klasy Customer.cls -> Progress OpenEdge -> Define Service Interface.

Wybieramy Definition mode: REST i zaznaczamy wszystkie metody klasy, NEXT.

Do pliku klasy zostaną wstawione adnotacje. Nic tu nie zmieniamy. Finnish.

Widzimy, że pod Defined Services został zdefiniowany serwis CustomerServService oraz został dodany katalog PASOEContent dla serwera aplikacji.

Po prawej stronie otwiera się REST Resource URI Editor. Jeśli go nie ma to: prawy klik myszy Defined Service -> CustomerServService i wybieramy Edit.

Z operacjami na danych związane są tzw. czasowniki HTTP (HTTP verbs):

POST: operacja CREATE – tworzy nowy rekord

GET (domyślny): operacja RETRIEVE – zwraca rekord na bazie podanego ID

PUT: operacja UPDATE – aktualizuje istniejący rekord

DELETE: operacja DELETE – usuwa istniejący rekord.

Dodajemy 2 zasoby: /Customer (dla wszystkich rekordów Customer) oraz /Customer/{custNum}.

Dla zasobu /Customer kojarzymy verb GET z metodą ReadAllCustomers. Dla /Customer/{custNum} kojarzymy verb GET z metodą ReadCustomer, a PUT z UpdateCustomer.

Teraz trzeba zmapować parametry dla każdej operacji pomiędzy parametrami wejścia HTTP request a parametrami wejścia ABL oraz parametrami wyjścia ABL a parametrami HTTP response.

Najpierw mapujemy operacje dla ReadAllCustomers GET: input Complete URL w HTTP Request do URI  w Interface Parameters; Query String Parameters w HTTP Request do num w Interface Parameters.
Teraz output: ttAllCustomers w Interface Parameters do Body w HTTP Response.

Dla ReadCustomer GET mapujemy: input – Path Parameters custNum w HTTP Request do custNum w Interface Parameters.
Output: CustomerRecord w Interface Parameters do Body w HTTP Response.

Na koniec dla UpdateCustomer PUT mapujemy: input – Path Parameters custNum w HTTP Request do custNum w Interface Parameters oraz Body w HTTP Request do CustomerRecord w Interface Parameters.
Output: CustomerRecord w Interface Parameters do Body w HTTP Response.

Zakończyliśmy definiowanie serwisu REST.

 

Instalacja OpenEdge w nowej wersji

Większość z Was wie, że model licencjonowania PSDN (Progress Software Developer Network) został zastąpiony przez Progress OpenEdge Developers Kit.

Zmiana wiąże się z rozszerzeniem dostępu do produktów Telerik, Corticon oraz wybranych usług. Model OEDK zawiera 5 licencji: Classroom (darmowa), Basic, Corporate, Premier, Innovator. Np. od licencji Corporate dostępne są wszystkie nowe szkolenia online. Porównanie 5 licencji możecie znaleźć tutaj.

Instalacja OpenEdge została uproszczona za pomocą tzw. plików instalacyjnych. Nie trzeba już wpisywać numerów licencji i kodów – wystarczy tylko wybrać z listy instalowane produkty.
I teraz wielu z Was zapewne zaprotestuje: przecież już od OE 10.1C można było instalować bez “wklepywania” tych kodów! Rzeczywiście od tamtej wersji można było zapisać plik licencyjny w formacie html i podczas instalacji wczytać License Addendum File. Jednakże była także opcja instalacji przez ręczne wpisywanie S/N oraz kodów wybranych produktów. Myślę, że wiele osób w ogóle nie stosowało opcji z Licenses Addendum File. Obecnie generowanie plików instalacyjnych (aktywacyjnych) jest obowiązkowe.

Po kolei: po zalogowaniu się do swojego konta ESD wybieramy opcję Manage OEDK Activation Files. Tu trzeba nadmienić, że Activation Files to to samo co Installation Files. Informacja, jaką dostajemy automatycznie emailem odnosi się do Installation Files, co może być w pierwszej chwili mylące.

Po wybraniu powyższych informacji i nadaniu nazwy Reference zaznaczamy które produkty będziemy instalować. Takich plików aktywacyjnych można wygenerować kilka dla różnych produktów, co jest bardzo użyteczne.

Zawartość utworzonych plików można przeglądać.

Podczas instalacji wystarczy wczytać konkretny plik i lista produktów pojawia się automatycznie.

Jak rozpocząć tworzenie interfejsu .NET w OE Dev. Studio

Tworzenie interfejsu .NET to dość szerokie pojęcie. Ja chciałbym tutaj napisać o początkach wykorzystania form .NET w narzędziu OpenEdge Developer Studio przy zastosowaniu języka ABL.
Technologia łączenia języka progressowego i technologii obiektowych pojawiła się w OE10.1, czyli ładnych kilka lat temu.
W dalszym ciągu jednakże wiele osób nie wie jak rozpocząć pracę z tworzeniem takiego interfejsu.

Bardzo pomocne będą tutaj filmy i towarzyszące im dokumenty pdf, stworzone przez Johna Sadda. Opracowania Johna są jasne i czytelne. Ze względu na to, że były stworzone kilka lat temu, mogą zawierać pewne drobne nieaktualności.

John jest twórcą materiałów dot. wielu zagadnień związanych z OpenEdge, do których adres znajdziecie w sekcji Adresy w sieci -> OpenEdge Educational Videos.
Te, które nas najbardziej teraz interesują, znajdziecie tutaj.

Rozpocznijmy od utworzenia nowego projektu typu OpenEdge w konfiguracji GUI for .NET.

Od razu utworzona jest klasa – plik Form1.cls oraz procedura, która może uruchamiać tę klasę – plik RunForm1.p.

Jest to o tyle fajne, że wiele osób nie wiedziało dotąd jak uruchomić klasę z poziomu procedury. Teraz dostaje od razu gotowe rozwiązanie. Jeśli chcemy utworzyć nową klasę formy wybieramy File -> New -> ABL Form.

Plik można otworzyć jako kod ABL lub jego wizualna postać (wybieramy View Design, lub OpenEdge Visual Designer).

Na razie forma to puste okno. W widoku Toolbox widzimy dwa zestawy kontrolek: Microsoft Controls i OpenEdge Controls. Z tego drugiego wybieramy źródło danych: bindingSource. Przy założeniu, że jesteśmy podłączeni do bazy danych, definiujemy źródło danych jako kilka pól z tablicy Customer.

Teraz do okna wstawiamy kontrolkę DataGridView i zaznaczamy zdefiniowane przed chwilą źródło danych.

Aby dane były wyświetlane trzeba dodać fragment kodu ABL w konstruktorze formy (patrz poniżej).

OK, dane są już prawidłowo wyświetlane.

Gorąco polecam obejrzeć prezentacje Johna Sadda, gdyż dokładnie objaśnia on poszczególne kroki, z zagłębieniem się w szczegóły dotyczące kodu ABL.

Do tego tematu powrócimy na blogu.

Serwisy REST – porównanie różnych typów

W kilku wcześniejszych artykułach opisałem, krok po kroku, tworzenie serwisu typu REST, wykorzystującego obiekty JSDO.

Wiem od niektórych z Was, że z tymi serwisami wiążą się pewne niejasności. Nic w tym dziwnego, to nie są progressowe technologie i wiążą się o stworzone niedawno standardy.

Kilka osób pytało mnie np. o różnice między tworzeniem serwisu REST na bazie projektów: Data Object, ABL Web App czy REST (rysunek poniżej).

Pierwsze dwa typy projektów służą do tworzenia serwisów Data Object. W Progress Developer Studio for EpenEdge zaimplementowano dwa typy projektów ze względu na dwa rodzaje AppServerów, z którymi współpracują.
Projekt Data Object jest wykorzystywany do tworzenia serwisów przy użyciu klasycznego AppServera, a ABL Web App z Pacific AppServer. Do wersji OpenEdge 11.5 włącznie zamiast tych dwóch projektów był dostępny tylko projekt Mobile.

W obu projektach (Data Object, ABL Web App) można utworzyć Business Entity – obiekt danych np. Customer czy Order, z którym tworzona jest klasa obiektu oraz obiekty JSDO. Klasa zawiera gotowe metody realizujące różne funkcje na danych (Create, Read, Update, Delete). Tworzony jest także plik . json, który można użyć definiując obiekty w środowisku Rollbase czy Telerik. Jest to prosta, szybka metoda, nie wymagająca szczegółowej wiedzy dewelopera nt serwisów REST.

Inne podejście jest reprezentowane w projekcie typu REST. Projekt ten wybierają deweloperzy  gdy aplikacja wymaga bezpośredniego dostępu do kontekstu HTTP (request/response), nagłówka, cookies itp. Daje to dodatkowe możliwości ale wymaga o wiele więcej pracy. Trzeba samemu “zamapować” każdą procedurę, klasę i parametr; dodać notacje itd.

Np. dodać nowe zasoby, parametry oraz przypisać im określone czasowniki (verb) możemy w narzędziu REST Resource URI Editor.

1 2 3 4 5