Overview 


  Tutorial:  Writing a Server and a Client

            
              Writing a Server

       
          Writing a Client

  

    Step 1:  Write a function 

    Step 2:  Publish the function

    Step 3:  Generate the WSDL file

    Step 4:  Start the Server

  

     Step 1:  Get the service WSDL file

     Step 2:  Generate the BDL client stub

     Step 3:  Call the Web service

     Step 4:  Handle server errors


Step 1 (Server): Write a function to be published in a service

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 DEFINE
02   add_input RECORD
03     a INTEGER,
04     b INTEGER
05   END RECORD,
06
07   add_output RECORD
08     r INTEGER
09   END RECORD
10
11 FUNCTION add()
12   LET add_output.r = add_input.a + add_input.b
13 END FUNCTION
 

Step 2 (Server): Publish the function

Namespaces

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/”.

Setting the namespace  - the fgl_ws_server_setNamespace() function

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.

Publishing the function -  the fgl_ws_server_publishFunction() function

To publish a function, call the function fgl_ws_server_publishFunction(). The parameters are:

  1.  The operation name as seen from the client side (case-sensitive)
  2.  The input message namespace
  3.  The name of the input variable
  4.  The output message namespace
  5.  The name of the output variable
  6.  The function name

 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 )

Step 3 (Server): Generate the WSDL file

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. 

Generating the WSDL using the fgl_ws_server_generateWSDL() function

Generate the WSDL file with the fgl_ws_server_generateWSDL() function. 

The parameters are:

  1. The name of the service
  2. The address of the server 

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.)

  1. 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:  

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)
 

Step 4 (Server): Starting the server

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 TRUE
03   CALL fgl_ws_server_process(-1) # Wait forever for the
04   RETURNING ret                   # next request      
05 END WHILE

Notes:

  1. The server port given in the fgl_ws_server_start() function must be the same as in the fgl_ws_server_generateWSDL() function. 

  1. 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")
  1. 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.



Step 1 (Client): Get the service WSDL File

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.

 


Step 2 (Client): Generate the BDL client stub to access the service

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.

 


Step 3 (Client): Calling the Web service

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 = 1
02 LET WebService_Calculator_CalculatorSoap_Add_in.b = 2
03
04 CALL WebService_Calculator_CalculatorSoap_Add_g()
05 RETURNING wsstatus
06
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.


Step 4 (Client): Handle server errors

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 )