|
|
|
Step 1: Get the service WSDL file |
Functions to be published as Web services are classic BDL functions. They must satisfy some additional criteria:
For example, to publish a function that adds two integer numbers a and b, declare the function with its input and output messages as follows:
01
DEFINE02
add_input RECORD03
a INTEGER,04
b INTEGER05
END RECORD,06
07
add_output RECORD08
r INTEGER09
END RECORD10
11
FUNCTION add()12
LET add_output.r = add_input.a + add_input.b13
END FUNCTION
When publishing a function, you must define additional information for the XML serialization of the input and output messages, and for the definition of the operation in the WSDL file.
XML uses namespaces to group the element and attribute definitions, and to avoid conflicting names. In practice, a namespace must be a unique identifier (URI: Uniform Resource Identifier). If you do not know what to choose at the moment, take your company's web site domain name since this is guaranteed to be unique (example: "www.4js.com") and append any string. Another option is to use the temporary namespace "http://tempuri.org/" (for testing only).
Examples of valid namespaces for the Four J's Development Tools company:
We have to choose a namespace for the operation definition, the input message and the output message. In the following examples, we will take the same namespace for all three: “http://tempuri.org/”.
The operation namespace is common to all operations and is set with the fgl_ws_server_setNamespace() function:
01
CALL fgl_ws_server_setNamespace("http://tempuri.org/")
Setting this global namespace is mandatory and must be done prior to any other Web service function call.
To publish a function, call the function fgl_ws_server_publishFunction(). The parameters are:
In our "add" example, we will call:
01
CALL fgl_ws_server_publishFunction(02
"Add",03
"http://tempuri.org/ ", "add_input",04
"http://tempuri.org/ ", "add_output",05
"add"06
)
Once you have published the functions, the server is ready to run. You now must furnish a description (WSDL) of the services provided by your server, so the client applications know how to access your server.
Generate the WSDL file with the fgl_ws_server_generateWSDL() function.
The parameters are:
Examples: “http://127.0.0.1:8090” or “http://localhost:8090”
( 127.0.0.1 or localhost is the IP address of the machine on which the server will be run)
( 8090 is the TCP port number on which the server is listening. Any other available port number can be selected.)
The output file name
In our "add" example, we will call:
01
CALL fgl_ws_server_generateWSDL(02
"Calculator",03
"http://localhost:8090",04
"ws_calculator.wsdl"05
)06
RETURNING ret
Note: The level of detail in the generated WSDL file can be set using the fgl_ws_setOption() function.
Available options are:
wsdl_stringsize - put the size of the strings in the WSDL
wsdl_decimalsize - put the size of the decimals in the WSDL
The options are TRUE by default.
01
CALL fgl_ws_setOption("wsdl_arraysize", FALSE)02
CALL fgl_ws_setOption("wsdl_stringsize", FALSE)03
CALL fgl_ws_setOption("wsdl_decimalsize", FALSE)
At this point we are ready to start the server and process the incoming SOAP requests.
The fgl_ws_server_start() function initializes the server to listen on the specified port.
Incoming requests are processed one by one by the fgl_ws_server_process() function.
The main function of our "add" example will be:
01
CALL fgl_ws_server_start( "8090" )02
WHILE TRUE03
CALL fgl_ws_server_process(-1) # Wait forever for the04
RETURNING ret # next request05
END WHILE
The server port given in the fgl_ws_server_start() function must be the same as in the fgl_ws_server_generateWSDL() function.
When the application server manages the Web Services, the fgl_ws_server_start() function takes as an argument the location of the application server in the format server:port, where port is an offset from the port 6400.
Example (connecting to the application server listening on localhost on port number 6405):
01
CALL fgl_ws_server_start("localhost:5")
The environment variable FGLAPPSERVER, when defined, overrides the value passed to fgl_ws_server_start().
For more information, see the Genero Web Services API Reference and the Genero Application Server documentation.
The Genero Web Services Extension allows a BDL program to access any Web service found on the Internet. The Four J's Web services extension supports the WSDL 1.1 specification of March 15, 2002 and some previous specifications.
To access a remote Web service, you first must get the WSDL file from the service provider and save it locally on your disk. Sample services can be found though UDDI registries (http://www.uddi.org), or on other sites such as XMethods (http://www.xmethods.net). Using your Web browser you can navigate to a WSDL file and save it.
In order to access the Web service described in the WSDL, it is not necessary to write code on your own. The Web Services Extension provides a tool, fglwsdl, that enables you to generate the client stub functions that handle the access to the service.
To generate the Web service client stub from your WSDL, use fglwsdl. For the "calculator" example, the command line is:
fglwsdl ws_calculator.wsdl
It will generate the files:
ws_calculator.4gl
ws_calculator.inc
The fglwsdl command line options are:
Option | Description |
-n namePrefix | Changes the prefix of the generated BDL function and variable names. |
-o outputFileName | Root name of the output files. The output files will be: "outputFileName.inc" and "outputFileName.4gl" |
-S | Lists the service and port names (format: "service/port"). When this option is used all other options are ignored. |
-s service/port | Processes only the given SOAP service and port. Otherwise all SOAP services and ports are processed. |
-v | Verbose mode. |
-V | Displays version information. |
The .4gl and .inc files generated in Step 2 contain the functions to access the server. For each operation on the server there are two generated client functions:
Functions using global variables have their names ending with "_g". Before calling the function you have to set the values in the global input variable. After the function call, the output message is returned from the server in the global output variable.
Global variables are defined in the generated .inc file. To use them, just import their definition with the GLOBALS instruction.
For the "calculator" example:
GLOBALS "ws_calculator.inc"
To call the Add operation, you would write the following code:
01
LET WebService_Calculator_CalculatorSoap_Add_in.a = 102
LET WebService_Calculator_CalculatorSoap_Add_in.b = 203
04
CALL WebService_Calculator_CalculatorSoap_Add_g()05
RETURNING wsstatus06
07
DISPLAY WebService_Calculator_CalculatorSoap_Add_out.r
The second generated function with parameters and return values exists only when no complex types (ARRAYs, RECORDs) are present in the input and output messages.
In the "calculator" example, to call the Add operation, just call the following function:
01
CALL WebService_Calculator_CalculatorSoap_Add( 1, 2 )02
RETURNING wsstatus, r
For a complete example, see the code samples provided with the package.
All of the generated functions, such as WebService_Calculator_CalculatorSoap_Add() and WebService_Calculator_CalculatorSoap_Add_g() in the calculator example, return a status.
When this status is non-zero, you get a more detailed error description in the global record wserror:
wserror.code: Short error message
wserror.description: Long error message
wserror.action: Internal "SOAP action"
To protect against remote server failure or unavailability, you can also set a timeout value that indicates how long you are ready to wait until the server responds to your request. This can be achieved by setting the "http_invoketimeout" option with the fgl_ws_setOption() function. A timeout value of 0 means wait forever. This is the default value. For example, to wait no more than 10 seconds:
01
CALL fgl_ws_setOption( "http_invoketimeout", 10 )