Web Services Hello World Example
April 23, 2021 at 7:12 PMWe will closely examine a very simplistic web service line by line here.
Line 1
: This example is coded in totally free RPG (**FREE).
Line 3
: Depending on how we compile the program we can add some compile options here. For such
a simple program it is ok to put the compile options into the source code. By doing that we can
create the program in one step by using the compile command CRTBNDRPG
.
On every serious project I would stay away from putting the compile options in the source code. You don’t want to change the source code if you just want to change a simple compile parameter (like the debug views) because a change in the program would mean you would have to test the whole program / workflow again even though nothing really changed. Use a build tool for building the project (f. e. make or any real change management system). Another very important pro for putting the compile options not in the code is when you want to change a compile option for the whole project. Then you would have to change it in every source. But with the compile options outside the source you can change it in one place for the whole application.
The binding directory (bnddir
) in the compile options tells the compiler where to look for all
the procedures not included in the source code, f. e. the procedures from the ILEastic service
program.
We also declared that the compiler should make this whole module thread safe and allow concurrent access (multiple threads) to everything in this module (variables, procedure, …).
Line 5
: This include statement includes all necessary stuff from the ILEastic copybook into
our source code like prototypes, constants and data structure templates.
Line 9
: The first thing we do here is to go into a local main procedure. We do this to avoid
using global variables. Now the config
variable is scoped to the main
procedure and is no
global variable. Whenever you can avoid using global variables, do it. Though for some things
the compiler still expects global declarations, f. e. compile time arrays and data areas.
As we are immediately branching into the main procedure we could have used the main
keyword
in the control options. That would work but by using the main
keyword we are also forfeiting
the default RPG error handler and I like to have it. So by immediately calling the main
procedure we can have best of both worlds.
Line 16
: Here we configure on which port the web service will be listening on (which will be
the port the HTTP client will use in the HTTP call when calling our web service).
Line 17
: With *ANY
the web service is listening on every network device. We can bind the
service to a specific network device so that it is only available on a specific network by
using the IP address instead of *ANY
.
Line 19
: In ILEastic HTTP calls are routed to endpoints (in our case the sayHello
procedure).
With il_addRoute
we specify which URL is routed to which procedure(s). We are also limiting the
routing to our endpoint for just HTTP GET request (HTTP method GET).
Line 21
: So far nothing really has happened/started. We need to call il_listen
to actually
start the web service and listen for HTTP requests.
Line 26 - 29
: This is the procedure interface for our endpoint procedure. ILEastic expects
exactly this procedure interface for every endpoint and passes the data structures for request
and response to it.
There is no return value in this procedure interface. The data is sent to the HTTP client by
using il_responseWrite
. Every call to il_responseWrite
sends one HTTP chunk to the HTTP
client. You can call il_responseWrite
as often as you like. The data is sent as chunks and
the HTTP client on the other side of the request will put the chunks together.
Line 31
: We are setting the “Content-Type” of the response to “text/plain” so the HTTP
client knows what the sent data is meant to be, in our case : plain text. There are many
different MIME Types (also known as Media Types) which describes different kinds of data.
You can also define your own Media Types. That makes sense if you want to differentiate
between different data representations (f. e. normal format vs extended format).
Line 32
: With il_responseWrite
we are actually sending data to the client. Notice that
we are sending data in chunks but never say when we are finished with sending data. That is
because ILEastic does that for us. After it called our endpoint procedure it sends a
“finishing chunk” to the HTTP client.
… and that’s it!