Open Source on IBM i

Web Services Setup with ILEastic

I have written some articles about writing web services with ILEastic and it is really as simple as already shown. And most of the time it is not any easier in other languages. You have to do/check/consider the same things regardless of the programming language.

But what I didn't cover so far was how to deploy and run the web service once we have finished developing it. Deployment is really easy and it doesn't take a lot to cover that because with ILEastic your web service program will be a native IBM i object in the QSYS file system. You only need to put the compiled object in the library where you want to have your own objects.

Setting up the web service to run when the system starts is another thing. And there are probably many ways to skin the cat. I want to show you a simple one (not necessarily the best one).

Subsystem

I typically want to have my web services all in a separate subsystem. So we create a brand new subsystem for them.

CRTSBSD SBSD(MY_OBJ/WS) POOLS((1 *BASE)) TEXT('Web Services')

That only creates a description of the subsystem. You can start it with the STRSBS command.

Class

This class has nothing to do with a programming construct or concept. A class defines how many resources a job can get, like processor time, memory and number of threads. Remember that ILEastic is a multi-threaded web framework so we need to be able to create multiple threads in a job.

CRTCLS CLS(MY_OBJ/WS) TEXT('Web Services')

Job Queue

As jobs are entering a subsystem through a job queue we will need to create at least one job queue and attach that to the subsystem. You can attach more than one job queue to a subsystem.

CRTJOBQ JOBQ(MY_OBJ/WS) TEXT('Web Services')

We need yet to attach the job queue to the subsystem.

ADDJOBQE SBSD(MY_OBJ/WS) JOBQ(MY_OBJ/WS) MAXACT(*NOMAX)

Job Description

The job description defines the environment of a job during its runtime in the system. Things like printer, logs, library list, multi-threading capability, which user profile is used for running the job and also which program is called initially at job start.

CRTJOBD JOBD(MY_OBJ/WS_HELLO) JOBQ(MY_OBJ/WS) USER(WS) RQSDTA('CALL PGM(HELLOWS)') 
    INLLIBL(MY_OBJ SHARED ILEASTIC) ALWMLTTHD(*YES) TEXT('Web Services : Hello World')

Every job runs under a certain user profile. If it is an interactive job then the user has logged himself into the system. A submitted job uses the same user profile as the original job which has done the submit. But if a job is autostarted when the subsystem is started there is no job from where to inherit the user profile. So you need to specify a user profile in the job description and don't use the default value *RQD.

Note: When you are already using iPKG for installing 3rd party open source software you will probably want to add the IPKG library to the library list of the job description.

Autostart Job

The web service should automatically start when the subsystem is started. This can be achieved with autostart jobs. You need to specify which job description should be used with the autostart job. This also determines which web service (program) is started on job start, see request data of the job description.

ADDAJE SBSD(MY_OBJ/WS) JOB(WS_HELLO) JOBD(MY_OBJ/WS_HELLO)

We can see now that we need a job description for every web service we want to automatically start at subsystem start.

Routing Entry

If you now start your new subsystem you will see that there is nothing to see. No jobs are running in your subsystem. That is because every job is routed internally in the subsystem to a program which executes the request data of the job (from the job description). Depending on the routing you can specify that a job in the subsystem has different resource limits by assigning a certain class object (remember the previously created class object).

The request data is just text for the subsystem on which to route to a specifiy program with certain resource limits (class).

To make things easy we use the QCMD program to excute our request data (which is a simple CALL) and use the previously create class object for every started job.

ADDRTGE SBSD(MY_OBJ/WS) SEQNBR(9999) CMPVAL(*ANY) PGM(QCMD) CLS(MY_OBJ/WS) MAXACT(100)

If no routing entry matches the request data of a job then the job is just dropped. I have yet to figure out where to find any log entry about the dropped job.

Restart Web Services

Restarting a web service is really simple because you just need to kill the old job submit a new one with the corresponding job description and that's it.

SBMJOB JOBD(MY_OBJ/WS_HELLO) USER(*JOBD) RQSDTA(*JOBD) CURLIB(*CRTDFT) INLLIBL(*JOBD)

Now you can start your subsystem and have your web service say hello to the world! :)

Happy setting up!

Mihael

Tags : RPG