Release 10.1A: OpenEdge Development:
Web Services

> ## StockQuotes sample walk-through

> `StockQuotes.p` follows these steps to prepare, call, and process the output from a quote request (source code edited and formatted for clarity):

> 1. Prompts for the stock symbol(s) to populate the XML document entered using the Enter Stock Symbols prompt:

>     DEFINE VARIABLE fillin-1 AS CHARACTER FORMAT "x(40)".
>     DEFINE VARIABLE text-1 AS CHARACTER FORMAT "x(50)" VIEW-AS TEXT.
>     DEFINE VARIABLE fillin-2 AS CHARACTER
>         VIEW-AS EDITOR LARGE SIZE 63 BY 15 SCROLLBAR-VERTICAL LABEL "".
>     DEFINE VARIABLE text-2 AS CHARACTER FORMAT "x(80)" VIEW-AS TEXT.
>     DEFINE BUTTON bgetQuote LABEL "getQuote" SIZE 14 BY 1.
>     DEFINE FRAME fTemp
>         text-1 AT ROW 1.5 COLUMN 2
>         fillin-1 AT ROW 1.25 COLUMN 25
>         text-2 AT ROW 3 COLUMN 2
>         bgetQuote AT ROW 4.5 COLUMN 30
>         fillin-2 AT ROW 6 COLUMN 5
>         WITH NO-LABELS SIZE 82 BY 22 THREE-D.
>     .
>     .
>     .
>     FILLIN-1:SCREEN-VALUE = "PRGS".
>     text-1:SCREEN-VALUE = "Enter Stock Symbols".
>     text-2:SCREEN-VALUE = "To get multiple quotes enter Ticker symbols
>     seperated by , (eg. PRGS,GE)".
>     ENABLE ALL WITH FRAME fTemp.

> 2. Creates a Web service object in the 4GL:

>     DEFINE VARIABLE hWS AS HANDLE.
>     .
>     .
>     .
>     CREATE SERVER hWS.

> 3. Connects to the Web service (which has only one valid service and port):

>     hWS:CONNECT("-WSDL
>                   http://www.swanandmokashi.com/HomePage/WebServices/StockQ
>     uotes.asmx?wsdl).
>     IF NOT hWS:CONNECTED() THEN
>         MESSAGE "SERVER NOT CONNECTED" VIEW-AS ALERT-BOX.

> 4. Sets the handle to the port type in the WSDL where the Web service operation is defined and waits for the user to invoke the request:

>     DEFINE VARIABLE hPortType AS HANDLE.
>     .
>     .
>     .
>     RUN StockQuotesSoap SET hPortType ON SERVER hWS.
>     IF NOT VALID-HANDLE(hPortType) THEN
>         MESSAGE "hPortType invalid: " VALID-HANDLE(hPortType)
>             VIEW-AS ALERT-BOX.
>     WAIT-FOR CLOSE OF CURRENT-WINDOW.

> 5. When the user clicks the getQuote button, `StockQuotes.p`:

> 1. Constructs the XML document that is input to the Web service operation. The document is created in this form:

>     <s0:GetStockQuotes xmlns:s0="http://swanandmokashi.com/">
>             <s0:QuoteTicker>stock-symbol(s)</s0:QuoteTicker>
>     </s0:GetStockQuotes>

> This is the code, which also saves the document as a `LONGCHAR`:

>     DEFINE VARIABLE lcSymbol AS LONGCHAR
>         VIEW-AS EDITOR LARGE SIZE 60 BY 20.
>     DEFINE VARIABLE lcQuote AS LONGCHAR
>         VIEW-AS EDITOR LARGE SIZE 60 BY 20.
>     DEFINE VARIABLE hDoc AS HANDLE.
>     DEFINE VARIABLE hRoot AS HANDLE.
>     DEFINE VARIABLE hChild AS HANDLE.
>     DEFINE VARIABLE hNextChild AS HANDLE.
>     DEFINE VARIABLE hNextNode AS HANDLE.
>     DEFINE VARIABLE hTextNode AS HANDLE.
>     .
>     .
>     .
>     ON CHOOSE of bgetQuote
>     DO:
>       .
>       .
>       .
>       CREATE X-DOCUMENT hDoc.
>       CREATE X-NODEREF hRoot.
>       CREATE X-NODEREF hChild.
>       CREATE X-NODEREF hNextChild.
>       CREATE X-NODEREF hNextNode.
>       CREATE x-noderef hTextNode.
>       hDoc:CREATE-NODE-NAMESPACE(hRoot, "http://swanandmokashi.com/",
>                                  "s0:GetStockQuotes", "element").
>       hRoot:SET-ATTRIBUTE("xmlns:s0", "http://swanandmokashi.com/").
>       hDoc:APPEND-CHILD(hRoot).
>       hDoc:CREATE-NODE-NAMESPACE(hChild, "http://swanandmokashi.com/",
>                                  "s0:QuoteTicker", "element").
>       hRoot:APPEND-CHILD(hChild).
>       hDoc:CREATE-NODE(hTextNode, ?, "text").
>       hTextNode:NODE-VALUE = FILLIN-1:SCREEN-VALUE.
>       hChild:APPEND-CHILD(hTextNode).
>       hDoc:SAVE("longchar", lcSymbol).
>       .
>       .
>       .

> 2. Invokes the `GetStockQuotes` operation in the Web service by making a procedure call:

>     DEFINE VARIABLE lcQuote AS LONGCHAR
>         VIEW-AS EDITOR LARGE SIZE 60 BY 20.
>     .
>     .
>     .
>     ON CHOOSE of bgetQuote
>     DO:
>       .
>       .
>       .
>       RUN GetStockQuotes IN hPortType (INPUT lcSymbol, OUTPUT lcQuote)
>           NO-ERROR.

> 3. Checks for errors and manages the information for any that occur (see the "Common procedure for SOAP fault handling" section):

>     DEFINE VARIABLE err AS LOGICAL.
>     .
>     .
>     .
>     ON CHOOSE of bgetQuote
>     DO:
>       .
>       .
>       .
>       RUN GetStockQuotes IN hPortType (INPUT lcSymbol, OUTPUT lcQuote)
>           NO-ERROR.
>       RUN ErrorInfo (OUTPUT err).
>      .
>      .
>      .

> 4. If there are no errors, loads the XML document that was passed back as a `LONGCHAR` `OUTPUT` parameter:

>     ON CHOOSE of bgetQuote
>     DO:
>       .
>       .
>       .
>       IF NOT err THEN
>       DO:
>          hDoc:LOAD("longchar", lcQuote, FALSE).
>          .
>          .
>          .

> 5. The Web service returns the output XML document with the following structure (shown for a single quote example, PRGS):

>     <GetStockQuotesResponse xmlns="http://swanandmokashi.com/"
>         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>         xmlns:xml="http://www.w3.org/XML/1998/namespace"
>         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>         <GetStockQuotesResult>
>             <Quote>
>                 <CompanyName>PROGRESS SOFT</CompanyName>
>                 <StockTicker>PRGS</StockTicker>
>                 <StockQuote>21.41</StockQuote>
>                 <LastUpdated>4:00pm</LastUpdated>
>                 <Change>+0.86</Change>
>                 <OpenPrice>N/A</OpenPrice>
>                 <DayHighPrice>21.60</DayHighPrice>
>                 <DayLowPrice>20.41</DayLowPrice>
>                 <Volume>160721</Volume>
>                 <MarketCap>740.4M</MarketCap>
>                 <YearRange>11.50 - 24.06</YearRange>
>             </Quote>
>         </GetStockQuotesResult>
>     </GetStockQuotesResponse>

> The client then parses this document to get the relevant information and put it into a `CHARACTER` variable for display:

>     DEFINE VARIABLE cResult AS CHARACTER INITIAL "". . . .
>     ON CHOOSE of bgetQuote
>     DO:
>       .
>       .
>       .
>       IF NOT err THEN
>       DO:
>         hDoc:LOAD("longchar", lcQuote, FALSE).
>         hDoc:GET-DOCUMENT-ELEMENT(hRoot).
>           /* hRoot = GetStockQuotesResponse */
>         IF hRoot:SUBTYPE = "ELEMENT" AND
>            hRoot:NAME = "GetStockQuotesResponse" THEN
>         DO:
>           hRoot:GET-CHILD(hChild, 1).
>             /* hChild = GetStockQuotesResult */
>           IF hChild:SUBTYPE = "ELEMENT" AND
>              hChild:NAME = "GetStockQuotesResult" THEN
>           DO i = 1 TO hChild:NUM-CHILDREN:
>             hChild:GET-CHILD(hNextChild, i).
>               /* hNextChild = Quote */
>             IF hNextChild:SUBTYPE = "ELEMENT" AND
>                hNextChild:NAME = "Quote" THEN
>             DO j = 1 TO hNextChild:NUM-CHILDREN:
>               hNextChild:GET-CHILD(hNextNode, j).
>               IF hNextNode:NAME = "CompanyName" THEN
>               DO:
>                 hNextNode:GET-CHILD(hTextNode, 1).
>                 IF hTextNode:SUBTYPE = "TEXT" THEN
>                   cResult = cResult + hNextNode:NAME + " = " +
>                             hTextNode:NODE-VALUE + "~n".
>               END.
>               .
>               .
>               .
>               IF hNextNode:NAME = "YearRange" THEN
>               DO:
>                 hNextNode:GET-CHILD(hTextNode, 1).
>                 IF hTextNode:SUBTYPE = "TEXT" THEN
>                   cResult = cResult + hNextNode:NAME + " = " +
>                             hTextNode:NODE-VALUE + "~n".
>               END.
>             END. /* hNextChild = Quote */
>           END. /* hChild = GetStockQuotesResult*/
>         END. /*  hRoot = GetStockQuotesResponse */
>       END. /* IF NOT err */
>     . . .
>     END. /* bgetQuote */

> 6. Displays the `CHARACTER` variable containing the data in an `EDITOR` widget:

>     ON CHOOSE of bgetQuote
>     DO:
>       .
>       .
>       .
>       fillin-2:SCREEN-VALUE = cResult.
>     END. /* bgetQuote */

> 6. Cleans up by running this code:

>     DELETE PROCEDURE hPortType.
>     hWS:DISCONNECT().
>     DELETE OBJECT hWS.

> Which:

> 1. Deletes the procedure object.
> 2. Disconnects from the Web service.
> 3. Deletes the Web service object.

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095