Building a Web Page that uses the Web Service
As you can see in Figure 3 a portfolio consists of several stocks that
are stored in portfolio table with a customer id that is to be tracked (in
this case simply with a Session id attached to a cookie for the demo's
sake). The application backend needs to retrieve a live quote for each one
of the stocks in the portfolio. As I mentioned previously making repeated
SOAP calls to the server to retrieve each quote individually is not a
great idea from a performance point of view, so rather than making one
SOAP call per stock I decided to add another method to my Web Service that
receives an XML input with a list of stocks, and an XML output that
returns several objects – one for each stock – in a single XML document.
I'll use wwXML for the packaging of those objects.
Figure 7 – This SOAP Stock Portfolio example retrieves stock quotes
via SOAP and demonstrates server to server and browser to server SOAP
communication.
Add the following method to the Web Service:
************************************************************************
* StockService :: GetStockQuotes
****************************************
*** Function: Returns a set of Stock Quotes based on an
XML input
*** string <quotes><symbol>IBM</symbol><symbol>MSFT</symbol><quote>
*** Assume: Pulls data from
msn.moneycentral.com
*** Pass: lcSymbol -
MSFT, IBM etc.
*** Return: Object
************************************************************************
FUNCTION GetStockQuotes(lcXMLSymbols as String) as String
LOCAL oDOM, lcXML, x, loQuotes, loQuote
IF EMPTY(lcXMLSymbols)
RETURN ""
ENDIF
oDOM = CREATEOBJECT("Microsoft.XMLDOM")
oDOM.LoadXML(lcXMLSymbols)
IF !EMPTY(oDOM.ParseError.Reason)
RETURN ""
ENDIF
loQuotes = oDOM.selectnodes("/quotes/symbol")
IF ISNULL(loQuotes)
RETURN ""
ENDIF
loXML = CREATEOBJECT("wwXML")
lcXML = ""
FOR x = 0 to loQuotes.Length -1
lcSymbol = loQuotes.item(x).Text
loQuote = THIS.GetStockQuote(lcSymbol)
IF ISNULL(loQuote)
LOOP
ENDIF
lcQuoteXML = loXML.CreateObjectXML(
loQuote,"quote" )
lcXML = lcxML + STRTRAN(lcQuoteXML, ;
"<quote>",[<quote symbol="]+lcSymbol+[">])
ENDFOR
lcXML = [<?xml version="1.0"?>] + CHR(13) + CHR(10) + ;
[<stockquotes>] + ;
lcXML + ;
[</stockquotes>]
RETURN lcXML
ENDFUNC
The method receives an input XML string that retrieves XML in the
following format:
<quotes>
<symbol>MSFT</symbol>
<symbol>IBM</symbol>
</quotes>
The symbols are retrieved using the XMLDOM parser. The for loop runs
through all of the Symbol nodes in the XML document.
For each symbol, a call to GetStockQuote() is made which goes out to
the NASDAQ site and retrieves a single quote as an object. This object is
turned into an XML fragment with wwXML::CreateObjectXML() which is
concatenated with the other symbol retrievals to create a large XML
document.
You can review the full source code of about 100 lines of code and the
HTML script page used to display the page by clicking on the Show Code
links on the bottom of the page. The Web Service relevant piece of code in
the Web server processing occurs in the following block:
*** Now Refresh the profile
IF llRefresh
*** Select all items for this user
SELECT * from Portfolio ;
where UserId = lcUserId ;
INTO Cursor TQuery
oSOAP = CREATEOBJECT("wwSOAP")
*** Create stock quote request in XML format
*** This will be our SOAP parameter
lcXML = ;
[<?xml version="1.0"?>] + CRLF +;
[<quotes>] + CRLF
SCAN
lcxml = lcxml + ;
[<symbol>] + symbol + [</symbol>]
+ CRLF
ENDSCAN
lcXML = lcXML + [</quotes>] +CRLF
*** SOAP CALL RIGHT HERE ***
*** Make the SOAP call and retrieve XML result
oSOAP.cServerUrl = ;
"http://www.west-wind.com/wconnect/soap/stockservice.wwsoap"
oSOAP.AddParameter("lcXMLSymbols",lcXML)
lvResult = oSOAP.CallMethod("GetStockQuotes")
IF oSOAP.lError
THIS.errormsg("SOAP
Error",oSOAP.cErrorMsg)
RETURN
ENDIF
*** Parse the XML result
loQuote = CREATEOBJECT("Quote")
oDOM = CREATEOBJECT("Microsoft.XMLDOM")
oDOM.LoadXML(lvResult)
IF !EMPTY(oDOM.parseerror.reason)
THIS.errormsg("XML Result
Error",oDOM.parseerror.reason)
RETURN
ENDIF
*** Loop through all of the quotes and update
*** the user's portfolio
LOCATE
SCAN
*** Load each symbol into an
object
lcSymbol = TRIM(Symbol)
loSymbol =
oDOM.selectSingleNode( ;
"/stockquotes/quote[@symbol='" + lcSymbol+ "']")
IF ISNULL(loSymbol)
LOOP
ENDIF
loXML = CREATEOBJECT("wwXML")
loQuote =
loXML.ParseXMLToObject(loSymbol,loQuote)
IF !ISNULL(loQuote)
SELECT
Portfolio
LOCATE FOR
UserId = lcUserId AND SYMBOL = lcSymbol
REPLACE
Descript with loQuote.cCompany,;
updated with loQuote.tUpdated,;
price with loQuote.nLast
ENDIF
ENDSCAN
pcMessage = "Portfolio refreshed at: " + TIME() +
" PST"
ENDIF
*** End of refreshing profile
The code starts by building an XML string that contains all the
symbols to retrieve from the portfolio. That string is then used in the
SOAP call as a parameter to the GetStockQuotes() method call. Notice that
the actual SOAP call in this example is 3 lines of code plus error
checking. Once the call returns it should have returned to us an XML
string that contains a set of quote objects for each of the symbols in the
portfolio.
The result string looks something like this:
<?xml version="1.0"?>
<stockquotes><quote symbol="INTC">
<ccompany>Intel Corporation</ccompany>
<csymbol>INTC</csymbol>
<nhigh>44.38</nhigh>
<nlast>44.13</nlast>
<nlow>42.69</nlow>
<nnetchange>1.06</nnetchange>
<nopen>43.06</nopen>
<nperatio>29.42</nperatio>
<tupdated>2000-10-23T10:20:59</tupdated>
</quote>
<quote symbol="MSFT">
<ccompany>Microsoft Corporation</ccompany>
<csymbol>MSFT</csymbol>
<nhigh>66.25</nhigh>
<nlast>64.13</nlast>
<nlow>64</nlow>
<nnetchange>-1.06</nnetchange>
<nopen>65.19</nopen>
<nperatio>37.50</nperatio>
<tupdated>2000-10-23T10:21:00</tupdated>
</quote>
</stockquotes>
[ 1 ]
[ 2 ]
[ 3 ]
[ 4 ]
[ 5 ]
[ 6 ]
[ 7 ]
[ 8 ]
[ 9 ]