I Send Receive User Defined Soap Rest Messages Trs PDF
I Send Receive User Defined Soap Rest Messages Trs PDF
The integrated web services client for Integrated Language Environment (ILE) has been used
for years to send SOAP messages by generating stubs that hide the details about the SOAP
messaging protocol. However, it did not allow users to send user-defined payloads over the
Hypertext Transfer Protocol (HTTP) transport. This article discusses the enhancements in
the integrated web services client that allow you to bypass the stubs and send user-defined
requests.
Introduction
The program temporary fixes (PTFs) that are needed for each of the supported releases of
the IBM i operating system in order to use the APIs:
The integrated web services client for ILE has been used for years to send SOAP messages
by generating stubs that hide the details about the SOAP messaging protocol. Users would set
the fields in the stub-generated structures, invoke the web service operation, and receive the
response. And this has worked great.
But what if you want to bypass the stubs and just send a user-defined payload, such as an
Extensible Markup Language (XML) document that is not generated by the stubs? Or maybe you
want to send a JavaScript Object Notation (JSON) payload as a Representational State Transfer
(REST) request, for which stub generation currently does not provide support. What to do then?
The answer to the questions is the integrated web services client. The client library has been
enhanced with new application program interfaces (APIs) that enable users to send user-defined
payloads. This article provides information on the APIs and some examples of API usages written
in ILE RPG.
For RPG programming, the APIs and constants are defined in the include file:
/QIBM/ProdData/OS/WebServices/V1/client/include/Axis.rpgleinc
The following table summarizes the transport APIs. You can find more details about the transport
API functions in the Integrated Web Services Client for ILE programming guide on the integrated
web services website (see Related topics).
axiscTransportGetLastErrorCode() Get transport error code from the last unsuccessful transport operation.
axiscTransportGetLastError() Get transport error string from the last unsuccessful transport operation.
The typical flow of events when using the transport APIs is as follows:
1. Use the axiscTransportCreate()function to create a transport object. The URL to the web
service is specified in the call to the function.
2. Set any transport properties (for example, connect timeout, HTTP method, HTTP
headers, whether payload needs to be converted to UTF-8, and so on) using the
axiscTransportSetProperty() function.
3. Send data (if any) using the axiscTransportSend() function. Data is buffered until the
axiscTransportFlush() function is called. The data is automatically converted to UTF-8
unless the AXISC_PROPERTY_CONVERT_PAYLOAD transport property is set to "false" (in
which case the data is sent as is).
4. Send the request to the client by invoking the axiscTransportFlush() function.
5. Receive the response to the request by calling the axiscTransportReceive() function. This
API must be called even if no data is returned in order to consume the HTTP response
to the request, which includes the HTTP response headers and status code. The data is
automatically converted from UTF-8 to the job coded character set identifier (CCSID) unless
the AXISC_PROPERTY_CONVERT_PAYLOAD transport property is set to "false" (in which
case the data is returned as is).
6. Destroy the transport object by calling the axiscTransportDestroy() function.
Send and receive user-defined SOAP and REST messages from Page 2 of 11
RPG
ibm.com/developerWorks/ developerWorks®
Let us now take a look at a sample client that uses the APIs to perform a REST request.
Method DELETE
Method POST
409 Conflict
Method GET
Send and receive user-defined SOAP and REST messages from Page 3 of 11
RPG
developerWorks® ibm.com/developerWorks/
The source code for the client is available in the Download section. So without further ado, let us
go over the code as it uses the new client APIs. Figure 2 shows the beginning of the code.
7.2: SI58137
7.1: SI58136
Looking at Figure 2, you can find that the client code is using the ILE RPG compiler support for
free-form code from column 1 to the end of line. This is indicated by specifying **FREE in column
1 of the first line (1). The other thing to notice is the /COPY statement (2) that is used to include the
various client API function prototypes and related constants.
The code below is the start of the logic that initiates a delete action of a student registration record.
Send and receive user-defined SOAP and REST messages from Page 4 of 11
RPG
ibm.com/developerWorks/ developerWorks®
You can uncomment the line (3) that contains the function call to enable trace. If you do
uncomment, the trace file will be created in file /tmp/axistransport.log. Recall from Table 2 that
in order to delete a resource, the format of the URI must be /context-root/students/{id}. In this
example, we are removing the resource (student registration) with identification of 823M934LA (4).
A transport object is created (5) by calling the axiscTransportCreate() API and the HTTP method
to be used on the HTTP request is set to DELETE (6) by calling the axiscTransportSetProperty()
API. That is it. There is no payload to be sent with the request. The request is send to the server
by the call to the subroutine flushAndReceiveData()(7). More information about this routine
is provided later in the article, but basically the subroutine sends the request and handles the
response to the request.
The code in Figure 4 shows the logic to create a new student registration record.
Send and receive user-defined SOAP and REST messages from Page 5 of 11
RPG
developerWorks® ibm.com/developerWorks/
The axiscTransportReset() API (8) is invoked with the URI that is needed to create a new student
registration record. Because JSON data is to be sent, the axiscTransportSetProperty() API is
invoked to set the content type (9) of the HTTP request to application/json, followed by the setting
of the HTTP method to POST using the same API. The payload is a JSON formatted request
containing the new student registration record (10). The data is stored in the transport object by
the call to the axiscTransportSend() API call (11). The request is send to the server by the call to
the subroutine, flushAndReceiveData()(12).
The next step is to retrieve all the student registration records, as shown in Figure 5.
The URI used when creating a new student registration record is used when retrieving the student
registration records, and therefore, there is no need to reset the transport object. To retrieve
the student registration records, the HTTP method, GET, must be used (13). Again, a payload
is not required to be sent with the request. The request is send to the server by the call to the
Send and receive user-defined SOAP and REST messages from Page 6 of 11
RPG
ibm.com/developerWorks/ developerWorks®
subroutine, flushAndReceiveData()(14). Finally, the transport object is destroyed by the call to the
axiscTransportDestroy() API (15).
Now, let us take a look at the helper subroutines used. Figure 6 shows the PRINT() subroutine.
The subroutine uses the C runtime printf() function that prints to standard output (stdout). So
any data passed to the PRINT() subroutine is written to standard output.
Figure 7 shows the checkError() subroutine. The checkError() subroutine is called if an error
occurs when calling a transport API:
Send and receive user-defined SOAP and REST messages from Page 7 of 11
RPG
developerWorks® ibm.com/developerWorks/
The subroutine writes the error code and the associated error message (16) to the standard
output. If the error code indicates that an unexpected HTTP status code (17) was returned by the
server, the HTTP status code is retrieved and written to the standard output.
Figure 8 shows the flushAndReceiveData() subroutine. This subroutine is called to send an HTTP
request and receive an HTTP response.
The call to the axiscTransportFlush() API (18) is done to initiate the sending of the HTTP
request. The call to the axiscTransportReceive() API (19) is done to receive the HTTP response
to the request. As long as there is data, we loop on the axiscTransportReceive() API (20) call
until there is no data to be consumed.
After the program is created, start a QShell session (using the QSH CL command) and invoke the
program by issuing the following command:
Send and receive user-defined SOAP and REST messages from Page 8 of 11
RPG
ibm.com/developerWorks/ developerWorks®
If you have the web service deployed and running on your system and everything runs
successfully, you should see something similar to what is shown in Figure 9.
The delete operation was successful and an HTTP status code of 204 indicates success with
no content being returned by the server. The creation of a new student registration record was
successful and an HTTP status code of 201 indicates the creation of a new resource. Finally, the
retrieval of all the registration records was successful indicated by HTTP status code of 200 (OK).
You can see the newly created student registration record in the data.
Summary
The new APIs allow you to send user-defined payloads over the HTTP transport. This support
enables you to send REST requests or even SOAP requests while controlling exactly what is sent.
The APIs will handle the details of the HTTP protocol while allowing you to handle the important
details, which is the payload sent and received. We're continually trying to improve the integrated
web services experience, and we'd love to hear from you.
Send and receive user-defined SOAP and REST messages from Page 9 of 11
RPG
developerWorks® ibm.com/developerWorks/
Downloadable resources
Description Name Size
Code sample IBMi.RESTCLIENT.Src.zip 2.65 KB
Send and receive user-defined SOAP and REST messages from Page 10 of 11
RPG
ibm.com/developerWorks/ developerWorks®
Related topic
• For information about the integrated web services support on IBM i see the product home
page.
Send and receive user-defined SOAP and REST messages from Page 11 of 11
RPG