The Genero Web Services package (GWS) allows a BDL program to access Web services found on the Internet. GWS supports the WSDL 1.1 specification of March 15, 2002. This example illustrates a client application that accesses the Add operation in the GWS Web Service MyCalculator. See: Tutorial: Writing a GWS Server Application for additional information about the Service.
See also: The fglwsdl Tool
To access a remote Web service, you must get the WSDL information from the service provider. Sample services can be found through UDDI registries or on other sites such as XMethods (http://www.xmethods.net).
You can use the fglwsdl tool provided by the Genero Web Services package to obtain the necessary WSDL information. The following example obtains the WSDL information for the GWS Service MyCalculator created by the Server tutorial:
fglwsdl -o Example2Client http://localhost:8090/MyCalculator?WSDL
This generates the following files:
Note: The MyCalculator GWS Service must be running on the specified port in order to provide the WSDL information.
The following definitions were generated in the globals file, Example2Client.inc:
Input and Output records
DEFINE Add RECORD ATTRIBUTE( XMLName="Add" , XMLNamespace="http://tempuri.org/webservices" ) a INTEGER ATTRIBUTE( XMLName="a", XMLNamespace="" ), b INTEGER ATTRIBUTE( XMLName="b", XMLNamespace="" ) END RECORD DEFINE AddResponse RECORD ATTRIBUTE( XMLName="AddResponse", XMLNamespace="http://tempuri.org/webservices" ) r INTEGER ATTRIBUTE(XMLName="r",XMLNamespace="" ) END RECORD
Since BDL functions cannot have complex structures as parameters, the data types are defined as global or modular variables.
Function prototypes for the Operations
This globals file contains the prototype of two functions for the Add operation.
The Add function uses input and output parameters, and returns the status and result. This function can only be used if the input and output parameters are not complex structures such as arrays or records. Using this function, developers do not access the global records directly.
The Add_g function can be used with the global input and output records. Before calling this function, you must set the values in the variables of the global input record.
Operation: Add # # FUNCTION: Add_g() # RETURNING: soapStatus # INPUT: GLOBAL Add # OUTPUT: GLOBAL AddResponse # # FUNCTION: Add(p_a, p_b) # RETURNING: soapStatus ,p_r
See The fglwsdl tool (WSDL and XSD) and Client stub and handlers for more details regarding the fglwsdl tool, its output and the generated functions.
The methods associated with creating and publishing a Web Service are contained in the classes that make up the Genero Web Services Library (com). If you use any of these methods in your client application, you must import the library. Since this example application sets the timeout period that the client will wait for the Service to respond, include the following line at the top of the module:
IMPORT com
If your generates .inc file uses xml class data types, you need to add IMPORT xml.
Use a GLOBALS statement to specify the generated globals file.
GLOBALS "Example2Client.inc"
Provide values for the input and output messages of the operation, and call one of the generated functions. Since the input and output messages are simple integers, we can call the Add function.
MAIN DEFINE op1 INTEGER DEFINE op2 INTEGER DEFINE result INTEGER DEFINE wsstatus INTEGER LET op1 = 1 LET op2 = 2 CALL Add(op1, op2) RETURNING wsstatus, result IF wsstatus = 0 THEN DISPLAY "Result: ", result ELSE -- Use the global wsError record DISPLAY "Error: ", wsError.description END IF END MAIN
Alternatively, we can use the global input and output records directly, calling the Add_g function:
MAIN DEFINE wsstatus INTEGER LET Add.a = 1 LET Add.b = 2 LET wsstatus = Add_g() IF wsstatus != 0 THEN-- Use the glocal wsError record DISPLAY "Error :", wsError.Description ELSE
DISPLAY "Result: ", AddResponse.r END IF END MAIN
These examples are very basic versions of the code. For complete examples, see the code samples provided with the package in demo/WebServices.
To protect against remote server failure or unavailability, you can set a timeout value that indicates how long you are willing to wait for the server to respond to your request. Use the SetOption() method of the WebServiceEngine class to set the the "readwritetimeout" option.
For example, to wait no more than 10 seconds:
CALL com.WebServiceEngine.SetOption( "readwritetimeout", 10 )A timeout value of -1 means "wait forever". This is the default value.
When a GWS Service operation returns a status that is non-zero, you can get a more detailed error description from the global record wsError:
Field Name | Description |
wsError.code | Short error message |
wsError.codeNS | Namespace of the error code |
wsError.description | Long error message |
wsError.action | Internal "SOAP action" |
The library file WSHelper.42m, included in the $FGLDIR/lib directory of the Genero Web Services package, should be linked into every client or server program. Assuming the example client code shown above is in a module named clientmain.4gl, you can compile and link the client program as follows:
fglcomp clientmain.4gl Example2Client.4gl fgllink -o myclient.42r clientmain.42m Example2Client.42m WSHelper.42mBack to the top