Skip to content. | Skip to navigation

Sections
Personal tools
You are here: Home Accelerate Articles U2 SOAP API client

U2 SOAP API client

The Rocket U2 UniData® and UniVerse® databases (U2) offer many APIs that can leverage your application investment from a closed environment to a fully integrated open environment (Internet). This article explores some of the U2 Extended BASIC APIs, namely SOAP, DOM, XPath, XMLDB, XMAP, and the XML DB mapping tool.

U2 SOAP API client using U2 extended basic APIs

Level: Introductory

Nik Kesic (nkesic@rs.com), Software Engineer, Rocket Software

11 Aug 2005


Introduction

In the past, the U2 databases allowed extended development with callBASIC/callc for UniData or GCI for UniVerse. Developing C applications for communication processes tended to be a specialized task, prone to error, and time consuming. To speed up the development of communication applications over TCP/IP, U2 engineers first implemented the BASIC Socket API. This allowed the developer to create client/server applications in the U2 database structure without resorting to the complexity of the C language. The natural extension to the SOCKET API was the CallHTTP API. This allowed the developer to create higher level applications communicating with Web servers over TCP/IP. As XML (a data format for structured document interchange between disparate systems) was steadily gaining popularity, the SOAP API was implemented to extend the CallHTTP API. This enabled the developer to very easily encapsulate an XML document with SOAP.

Task summary

Upon completing the four steps below, you will be able to populate a U2 database based on a ZIP code value. Example 1 performs a SOAP connection and submits a ZIP code to the public WSDL site, which returns a SOAP response containing connection status, connection headers, and an XML document. Example 2 expands the versatility of the APIs by using the XMLDOM API to extract the XML from the SOAP document and displays the contents. Example 3 prepares U2 to analyze an XML document and map the elements to a U2 table. Example 4 uses the U2 XMAP APIs to extract elements from the XMLDOM structure and populate the ZIPCODES U2 file.

 

 


Example 1: Using SOAP in a U2 environment

Compile and run the example below (UniData requires the -I compile flag). Name the program ZIPREQ1.

********************************************************************
* PROGRAM ZIPREQ1
*
* For UniData use the following include.
* $INCLUDE INCLUDE XML.H
*
* For UniVerse use the following include.
$INCLUDE UNIVERSE.INCLUDE XML.H
* 
* Example of Sending a SOAP request from BASIC 
*
* ZIPREQ1 - PROGRAM TO RETRIEVE A ZIP CODE - 
* using SOAP API (UniData 6.1.3-Umode, Universe 10.1.6-Ideal)
* created by Nik Kesic, U2 ATS, Dec 2, 2004
* Sample program only, not intended for commercial use
*
* Turn on logging
*
* RESULT=protocolLogging("ZIPCODE.log","ON",10)
* CRT "Logging started = ":RESULT
*
****
*
* You may be required to connect via a Proxy. If so insure you
* uncomment the lines below. If you are unsure that you need a 
* proxy, verify you web browser proxy settings.
* Tools>Internet Options…>Connections>Lan Settings…>Proxy server
* and populate the variables below:
*
*Ret = setHTTPDefault("PROXY_NAME", "Name or IP")
*IF Ret <> 0 THEN 
*  STOP "Error in setHTTPDefault PROXY_NAME: " : Ret 
*END 
*Ret = setHTTPDefault("PROXY_PORT", "port number")
*IF Ret <> 0 THEN 
*  STOP "Error in setHTTPDefault PROXY_PORT: " : Ret 
*END 
****
PROMPT ""
CRT
DISPLAY "U2 SOAP/XML DOM/XMAP EXAMPLE"
CRT
Xfile=""
xmlString=""
XMLMap="&XML&/ZIPCODES.map"
*
* For UniData use 
* XMLMap="_XML_/ZIPCODES.map"
*
PRINT "Enter Zipcode : ":
INPUT ZIPCODE
*
ZIPX = ""
ZIPX :='<?xml version="1.0" encoding="UTF-8"?>'
ZIPX :='<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'
ZIPX :="  <soap:Body>"
ZIPX :='<GetInfoByZIP xmlns="http://www.webserviceX.NET">'
ZIPX :="<USZip>":ZIPCODE:"</USZip>"
ZIPX :="    </GetInfoByZIP>"
ZIPX :="  </soap:Body>"
ZIPX :="</soap:Envelope>"
*
URL = "http://www.webservicex.net/uszip.asmx?WSDL" 
SoapAction = "http://www.webserviceX.NET/GetInfoByZIP"
Timeout = 30000 
* Create the Request 
Ret = SoapCreateRequest(URL , SoapAction , SoapReq)
IF Ret <> 0 THEN 
  STOP "Error in SoapCreateRequest: " : Ret 
END 
* Submit the Request 
SETREQUEST.STATUS = soapSetRequestContent(SoapReq, ZIPX,1)
* PRINT "Request Content Status = ":SETREQUEST.STATUS
Ret = SoapSubmitRequest(SoapReq, Timeout, RespHeaders, RespData, SoapStatus)
IF Ret <> 0 THEN 
  CRT "Error in SoapSubmitRequest: " : Ret 
  STATUS=getSocketErrorMessage(Ret, errMsg)
  CRT errMsg
  STOP
END 
*
PRINT "Response status : " : SoapStatus 
* PRINT "Response headers: " : RespHeaders 
* PRINT "Response data : " : RespData 
*
*********************************************************
 
Note
Protocol logging was intentionally commented out, but experiment with this flag turned on and view the log file created. If uncommented, the protocolLogging function will create a log file in the current database account:

 


* RESULT=protocolLogging("ZIPCODE.log","ON",10)
* CRT "Logging started = ":RESULT

Uncomment the last PRINT statement (RespData) in the program to view the actual SOAP document returned:

* PRINT "Response data : " : RespData
 

If your connection is successful, you should see the following:

Enter Zipcode : 80014
Response status : 200²OK
 

The RespHeaders variable contains the response SOAP headers, which may be useful:

Enter Zipcode : 80014
* PRINT "Response headers: " : RespHeaders



 


Example 2: Using DOM in a U2 environment

Continuing from Example 1, this section expands the versatility of the APIs by using the XML DOM API to extract the XML document from the received SOAP response. The strength of the XML family of BASIC APIs is the ease the BASIC programmer has extracting XML document elements.

Defining Code Functions
This example will use the following BASIC functions:

  • XDOMOpen – This function loads an XML document and builds a DOM tree in memory.
  • XDOMLocate – This function locates the starting point of the specified node string in the DOM tree and creates a locate handle.
  • XDOMLocateNode – This function locates the first child in the locate node handle.
  • XDOMWrite – This function writes the DOM structure to a string or a file.

Prerequisites:

  • All the requirements from Example 1

Compile and run the example below (UniData requires the –I compile flag). Attach the code below to the end of ZIPREQ1 and rename the program ZIPREQ2.

 

Listing 2. ZIPREQ2

 

********************************************************************
* Now open the SOAP response as a DOM
*
* Make sure xml string has a line feed at the end
* 
RespData=RespData:CHAR(10)
*
* Parse XML document and build DOM structure in memory
Status = XDOMOpen(RespData, XML.FROM.STRING, DOMH)
If Status <>  XML.SUCCESS Then
         * We hit an error
  Print 'Error with XDOMOpen().'
*  Gosub PrintError
  Stop
End
** Position at a specific node
Status = XDOMLocate(DOMH,'//NewDataSet','',domHandle)
If Status <>  XML.SUCCESS Then
         * We hit an error
  Print 'Error from XDOMLocate().'
*  Gosub PrintError
  Stop
End
Status = XDOMLocateNode(domHandle, XDOM.CHILD, XDOM.FIRST.CHILD,
XDOM.ELEMENT.NODE, sibHandle)
Status = XDOMWrite(domHandle, xmlString, XML.TO.STRING)
*
*
Print xmlString 
END
*
********************************************************************

 

If your connection is successful, you should see the following:

Enter Zipcode : 80014
Response status : 200²OK 
<Table><CITY>Aurora</CITY><STATE>CO</STATE><ZIP>80014</ZIP> 
<AREA_CODE>303</AREA_CODE>
<TIME_ZONE>M</TIME_ZONE></Table>

 


 

Back to top

 

 

Example 3: Preparing the U2 environment

This example prepares U2 to analyze an XML document and map the elements to a U2 Table. The XMLDB Mapping Tool creates relationships between XML elements and U2 dictionary attributes. The Web site used in this example does not supply an XSD XML schema. For true integration and simplicity beyond this paper, it is important to always obtain an XML schema of the XML data you want to receive, so that the mapping of element/attributes is painless.

The mapping example below guides you through the steps of creating a schema, changing the ROOT node name to NewDataSet and the child node to Table, and a U2 database map file using the XMLDB tool. The change made to the XSD file insures compliance with the XML received from the Web site.

Prerequisites:

  • All the requirements from Examples 1 and 2
  • Installation of the XMLDB Mapping Tool from the U2 Clients CD

Create a file and dictionary called ZIPCODES. Populate the ZIPCODES dictionary to reflect the following.

 

Listing 3. ZIPCODES Dictionary

 

               Type 
Field......... Field. Field........ Conversion.. Column......... Output Depth 
Name.......... Number Definition... Code........ Heading........ Format Assoc..

@ID            D    0                            ZIPCODES        10L    S
ZIP            D    0                            Zip Code        10R    S
CITY           D    1                            City            20L    S
STATE          D    2                            State           15L    S
AREA_CODE      D    3                            Area Code       4R     S
TIME_ZONE      D    4                            Time Zone       3L     S

 

Perform the following from TCL:

From UniVerse:

>LIST ZIPCODES ZIP CITY STATE AREA_CODE TIME_ZONE TOXML ELEMENTS 
WITHSCHEMA TO "ZIPCODES"

 

From UniData:

:LIST ZIPCODES ZIP CITY STATE AREA_CODE TIME_ZONE TOXML ELEMENTS  
WITHSCHEMA TO ZIPCODES

 

Either database command creates two files (ZIPCODES.xml and ZIPCODES.xsd) in the _XML_ (UniData) or &XML& (UniVerse) directory, as shown below:

 

Listing 4. ZIPCODES.xml

 

<?xml version="1.0"?>
<ROOT
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="ZIPCODES.xsd">
</ROOT>

 

 

 

 

Listing 5. ZIPCODES.xsd

 

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:annotation>
  <xsd:documentation xml:lang="en">
    account: C:\IBM\ud71\Demo
    command: LIST ZIPCODES ZIP CITY STATE AREA_CODE TIME_ZONE TOXML
WITHSCHEMA TO ZIPCODES
  </xsd:documentation>
  </xsd:annotation>
  <xsd:element name="NewDataset">
  <xsd:complexType>
  <xsd:sequence maxOccurs='unbounded'>
    <xsd:element name="Table" maxOccurs="unbounded">
    <xsd:complexType>
      <xsd:attribute name="_ID" type="xsd:string"/>
      <xsd:attribute name="ZIP" type="xsd:string"/>
      <xsd:attribute name="CITY" type="xsd:string"/>
      <xsd:attribute name="STATE" type="xsd:string"/>
      <xsd:attribute name="AREA_CODE" type="xsd:string"/>
      <xsd:attribute name="TIME_ZONE" type="xsd:string"/>
    </xsd:complexType>
    </xsd:element>
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
</xsd:schema>

 

Because the public Web site does not supply an XSD XML schema file, the step below is necessary. The ROOT element node is not ROOT, but rather NewDataSet, and the child node is Table. The above XSD file was manually edited to reflect this.

Visit WebserviceX.net (see Resources), select the GetInfoByZip operation, and enter a US Zip code. The returned XML will display Table as the key node for returned data elements:

 

Listing 6. ZIPCODES.xml

 

<?xml version="1.0" encoding="utf-8"?>
<NewDataSet>
  <Table>
    <CITY>Aurora</CITY>
    <STATE>CO</STATE>
    <ZIP>80013</ZIP>
    <AREA_CODE>303</AREA_CODE>
    <TIME_ZONE>M</TIME_ZONE>
  </Table>
</NewDataSet>

 

Using the XMLDB tool, create an XMLDB XMAP file (ZIPCODES.map) using the ZIPCODES.xsd file and the U2 table ZIPCODES.

 

Figure 1. Add new Xmap file

 

Add new Xmap file

 

Select the parent account (Demo) and Map name of (ZIPCODES).

 

Figure 2. New RDB XML map file

 

New RDB XML map file

 

Specify U2 file (ZIPCODES).

 

Figure 3. Source U2 files

 

Source U2 files

 

Specify the schema file (ZIPCODES.xsd).

 

Figure 4. DTD or XSD file

 

DTD or XSD file.

 

Select the ROOT element.

 

Figure 5. Root element

 

Root element

 

The XML/DB Tools will now display.

 

Figure 6. ZIPCODES.map display

 

ZIPCODES.map display

 

Create relationships (mapping) between the ZIPCODES dictionary and schema.

 

Figure 7. Table schema mapping

 

Table schema mapping

 

Your ZIPCODES.map file must look like the following when completed (click on the Source tab):

 

Figure 8. The ZIPCODES.map file

 

The ZIPCODES.map file

 

 


 

Back to top

 

 

Example 4: Using XMAP in a U2 environment

This example concludes the “U2 SOAP API client parts 1, 2, and 3” examples. The U2 XMAP API is used to extract elements from the XDOM created string "xmlstring". This string is manipulated using XMAP functions to populate the ZIPCODES U2 file. Notice how the BASIC code below simplifies extracting data from XML element names using the XMAPReadNext function with information from the map file.

Defining Code Functions
This example will use the following BASIC functions:

  • XMAPopen – This function opens an XML document as a U2XMAP data set.
  • XMAPReadNext – This function retrieves the next record from the U2XMAP dataset and formats it as a record of the UniVerse file that is being mapped.
  • XMAPClose – This function closes the U2XMAP dataset handle and frees all related structures and memory.
  • XDOMClose – This function frees the DOM structure.

Prerequisites:

  • All the requirements of examples 1, 2, and 3

Compile and run the example below (UniData requires the –I compile flag). Attach the code below to the end of ZIPREQ2 and rename the program ZIPREQ3.

 

Listing 7. ZIPREQ3

 

**********************************************************
*
* Print xmlString ;* Comment out this statement when attaching the 
* END             ;* U2 SOCKET API part 4 BASIC code.
*
* Open XMAP dataset for reading
Status = XMAPOpen(xmlString, XML.FROM.STRING, XMLMap, XML.FROM.FILE, Xfile)
* PRINT Status
If Status <> XML.SUCCESS Then
         * We hit an error
  Print 'Error with XMAPOpen().'
  Gosub PrintError
  Stop
End
Open 'ZIPCODES' to F1 Else Stop 'Error opening file ZIPCODES.'
* Read records from XMAP dataset, write to ZIPCODES file
Record = ''
Loop
  Status = XMAPReadNext(Xfile, 'ZIPCODES', Record)
Until Status = XML.EOF Do
  If Status <> XML.SUCCESS Then
    Print 'XMAPReadNext() error.'
    Gosub PrintError
    Stop
  End
  ID = Record<1>
  Rec = FIELD(Record, @FM, 2, 999)
  Write Rec to F1, ID ON ERROR STOP 'Write to file ZIPCODES failed.'
  Print 'ID ':ID:' written to the ZIPCODES file.'
Repeat
If Status = XML.EOF Then
  Print 'EOF reached in document.'
End
* Close all handles before exiting
Status = XMAPClose(Xfile)
If Status <> XML.SUCCESS Then
         * We hit an error
  Gosub PrintError
  Stop
End
      Status = XDOMClose(domHandle)
      If Status <> XML.SUCCESS Then
         * We hit an error
         Print 'Error with XDOMClose().'
         Gosub PrintError
         Stop
      End
      Status = XDOMClose(DOMH)
      If Status <> XML.SUCCESS Then
         * We hit an error
         Print 'Error with XDOMClose().'
         Gosub PrintError
         Stop
      End
Close F1
Stop
*
* RESULT=protocolLogging("ZIPCODE.log","OFF",10)
* CRT "Logging started =  ":RESULT
*
PrintError: 
* Using XMLGetError() we can find out the very last error code and 
* its corresponding message. This allows us to display a descriptive
* reason for the problem.
Tmp = XMLGetError(Code,Msg)
Print
Print 'The error description and code:'
Print '------------------------------------------'
Print 'Error desc:' ; Print Msg
Print 'Error code: ':Code
Print '------------------------------------------'
Return
End

 

If your connection is successful, you should see the following:

Enter Zipcode : 80013
Response status : 200²OK
ID 80013 written to the ZIPCODES file.
EOF reached in document.

 

Perform the following command from TCL:

:CT ZIPCODES 80013
ZIPCODES:

80013:
Aurora
CO
303
M

 

 


 

Back to top

 

 

Conclusion

After completing the examples above, you should have a SOAP client application in U2 that can access a Zip code Web service of a remote non-U2 enabled system. The XML document received is then used to populate a U2 table. There are many functions in the Extended BASIC APIs which were not discussed that can extend the power of the application developer even more. U2 engineering continues to extend BASIC with what started out as the SOCKET API to other disciplines, making it easier for the application developer to create complex applications without the need to create complex, time consuming code.


 

Back to top

 

Resources

Learn

 

  • Visit WebserviceX.net, as outlined in Example 3, to get Table as the key node for returned data elements
  • Learn more about U2 by visiting the Rocket Software U2 Web site.
  • For UniData, the UniBasic Extensions, Version 7.2 manual describes the following extensions to UniBasic: UniBasic Socket API, Using CallHTTP, Using SSL with CallHTTP and the Socket Interface, and Using WebSphere MQ with UniData.
  • For UniVerse, the BASIC Extensions V 10.3 manual describes the following extensions to UniVerse BASIC: UniVerse BASIC Socket API, Using CallHTTP, Using SSL with CallHTTP and the Socket Interface, and Using WebSphere MQ with UniVerse.
  • "Zeroing in on UniData problems" (Technical Article, September 2004) assists with the problem determination process for someone administering or supporting UniData databases.

About the author

Nik Kesic photo

Nik Kesic works for the Rocket Software U2 Advanced Technical Support group in Denver Colorado. Nik provides consultancy, level 3 support, and training and has published articles on Web enablement using RedBack, Sockets, XML, SOAP, SSL, and Encryption.

 

Document Actions