Blog
PowerUp

Links

« Communication is Key, Even in IT | Main | i Colleagues Learn New Skills Through Hands-On LUG Activity »

March 21, 2012

Comments


You can even implement the "finally" clause in Java using API QMHSNDSM (Send Scope Message).

Too bad RPG doesn't support all this. Error handling is paramount with business apps.

Thanks for the advice jacobus, I'll check it out later to improve it ;)

In the quest towards modern applications, decoupling your logic is key for achieving flexibility and maintainability.

This technique is much better than sending back an "error code" in a parameter and hopping that the calling program checks it after the call. I don't like to create components that need to be aware of who is going to use them or that deppend on external documentation, because I have found that it creates tight coupling.

This technique allows me to create ILERPG methods (aka.procedures) that would "throw" an exception messages so I can be sure that the calling program is aware of the exception and obligated to handle it accordingly.

I'm also signing @jacobus' wish list and hope to soon see this features as native functions of ILERPG.

Nice article!

Oh but RPGLE (using ILE aren't you?) does support error handling much better than any other platform. Here's Why...
As a 40+ year veteran of the RPG and IBM i formerly known as System 3, System 36, System 38, AS/400...Been doing this for years.

Everything in the IBM i OS is in service programs. The RPG (ILE) programmer can use these same components by calling an API.
The API is the connection to the service programs that the IBM i uses to do just about everything.

You also need some error handling within each procedure that you create to call the API.
You do this by supplying an API Error structure as part of the API call to QWVRCSTK.
I am adding code below, but don't know how it will turn out, and it is only partial excerpts from the source members.
I can send the source files if you want.
PS.. Be better if this site had a way of attaching the code. It was pretty tedius pasting then editing the code entries. Still could not get them to show up, be my guest to edit the code sections.

The prototype to the API QWVRCSTK (this is in a separate source member and is copied in by the compiler thusley
D/include iAPISrvI,RtvCSkEV1P Retrieve call stack entry parm Ds and prototype
This is only the part that shows the prototype definition, there is much more in the source such as the formats and the detail data structure formats of the various types of data returned by the API.

D*** here is the prototype definition
D*------------------------------------
D iAPIRtvCallStackV1...
D PR Extpgm('QWVRCSTK')
D CStkReceiver...
D Like(CStk0100V1) //receiver variable
D CStkReceiverLength...
D Like(iAPI.ReceiverLength) //length receiver var
D CStkReceiverFormat...
D Like(iAPI.ReceiverFormat) //receiver var format
D CStKJobId...
D Like(JIDF0100V1) //Job identifier info
D CStkJobIdFormat...
D Like(iAPI.JobIdFormat) //Job ID format name
D CStkAPIErrorData...
D Like(ErrC0200V1) //API error return
D*------------------------------------

here is what the call looks like

// retrieve the call stack
iAPIRtvCallStackV1
( CStk0100V1 // call stack receiver structure:
xnReceiverLength // length of receiver (Stk0100V1):
xcReceiverFormat // format name of receiver structure:
JIDF0100V1 // job ID information structure;
xcJobIdFormat // format name for the Job ID structure:
ErrC0200V1 ); // API errors structure

Here is what that error structure looks like
D*------------------------------------
------------------------------------------------
D ErrC0200V1...
D DS Qualified
D Key...
D 9B 0 key indicates format
D BytesProvided...
D Like(iAPI.BytesProvided) bytes provided here
D BytesAvailable...
D Like(iAPI.BytesAvailable) rtrn bytes available
D MessageID...
D Like(Gr.MessageID) message identifier
D Reserved...
D 1A error reserved byte
D CCSId...
D 9B 0 CCSID exception data
D*------------------------------------
------------------------------------------------

There are status codes named constants that are returned to the caller of the API

blank - information complete
I - information retrieved but incomplete
N - no information could be retrieved

the simple test to see if an API error occurred is coded in a subroutine (include source member) like this


//========================================================
Begsr ErrCV10200APIErrorTest;

If ErrC0200V1.BytesAvailable > *Zeros; // some error information was returned
iAPIResult = iAPI_Result_Error; // errors occurred
Else;
iAPIResult = iAPI_Result_Successful; // no errors, API call was successful
EndIf;

//========================================================
The iAPI_Result_Error and the _Successful are named constants (from included source)


I have tons more of the API processing code (procedures and service programs).
Plus groupings of the procedures in service programs.
I have a service program just for the error handling. Remember we want to only have one set of code to maintain.


Here is an export from a service program that componentizes (did i spell that right) the API calls


StrPgmExp
PgmLvl(*Current) +
LvlChk(*Yes) +
Signature('V1_2010.04.01')
/* ('1234567890123456') */
Export Symbol(ChgLibListToJobDInlLibLV1)
Export Symbol(CrtUserSpaceV1)
Export Symbol(LstDataBaseMembersV1)
Export Symbol(LstDataBaseRelationsMemberV1
Export Symbol(RtvLibListFromSupGroupsV1)
Export Symbol(RtvNextDataBaseMemberV1)
Export Symbol(RtvNextDataBaseRelationsMemberV1)
Export Symbol(RtvCallStackEntryV1)
Export Symbol(RtvDbFileOverrideV1)
Export Symbol(RtvJobDescriptionV1)
Export Symbol(RtvObjectDescriptionV1)
Export Symbol(RtvUserInformationV1)
Export Symbol(RtvSystemValueV1
)
EndPgmExp
Each of the above uses and IBM i API to do the job.

Oops, I forgot to mention the monitor only is good for catching errors that you might expect to happen. But what about the errors that are not included in the monitor.
Try coding a subroutine called *PSSR. This is automatically run if an error occurrs that is not handled by a monotor. This has been the standard of error handling in RPG for oh I don't know how many years ago that was.

Hi Thomas...Thanks for the feedback, I really appreciate it. Can you please send me a copy of your code? I think that creating an API that covers the things that you point out in your comment and merging it with what I already have, will result in a very robust solution.

Sorry for the inconveniences with the source code, this is my first post, so I didn´t know the way this site will handle it...

Thomas:
Oh but RPGLE (using ILE aren't you?) does support error handling much better than any other platform


You mean i/OS, the operating system, not RPG, the language.

Indeed, i/OS is very robust, and provides a native exception handling mechanism lightyears ahead of what you have in in Unix, Win etc.

Too bad RPG doesn't support this, although it is meant for building robust business applications. You have to implement the solution yourself.

Too bad.

In the "other" world it's the other way around. A rather crude and primitive OS (compared with i/OS), but advanced languages with proper support for error handling.

Here is an example using a utility

http://www.perficient.com/Solutions-and-Services/Business-Integration-SOA/Reusable-Utility-Services

The comments to this entry are closed.