Wednesday, May 18, 2022

New way in RPG to monitor for errors

on-excp in monitor group

In RPG we have been able to monitor for errors, using a Monitor group, for years. Until IBM i 7.5 and 7.4 TR6 we could only monitor for program and file status codes. I have always preferred CL’s MONMSG that allowed me to monitor by message id instead.

As part of the new release, or new TR for 7.4, there is a new RPG operation code, ON-EXCP, that can be used within a Monitor group to monitor for a specific error message or messages. The syntax is very similar to that of the ON-ERROR operation code:

monitor ;
  Something
on-excp 'CPF1234' : 'RNX1234' : 'RNQ1234' ;
  Do something else to mitigate the error
endmon ;

I am going to give some examples below so you can understand how ON-EXCP works. Here is my RPG program’s source code:

01  *free
02  ctl-opt option(*srcstmt) dftactgrp(*no) ;

03  dcl-f TESTFILE usage(*update) usropn ;

04  open TESTFILE ;
05  close TESTFILE ;

06  read TESTFILE ;

Line 1: Of course, this code is in totally free RPG.

Line 2: My favorite control options.

Line 3: The definition for the file I will be using in these examples. The file is defined to allow updates, and by default for input too. As the USROPN is present it means I will be opening and closing the file.

Lines 4 and 5: Why would I open and close the file on the next line? I need to do this so that the program will compile.

Line 6: No-one will be surprised that when I try to read a closed file I get an error:

RNQ1211
I/O operation was applied to closed file TESTFILE

I can stop the program from erroring using a Monitor group. Therefore, I replace line 6 with the code below:

06  monitor ;
07    read TESTFILE ;
08  on-error 1211 ;
09    dsply ('1211: File not open') ;
10  endmon ;

Line 6: The start of my Monitor group.

Line 7: The statement that will be monitored. This could be multiple statements, in my simple example I only need to monitor one line.

Lines 8 and 9: This is the ON-ERROR block that will handle the error. If the message is handled by this block the Display operation code will display a message.

After compiling the change program, when I run it I see the message from the Display operation code.

DSPLY  1211: File not open

That is the way I have handled this kind of error for the past few years. Now with the new ON-EXCP operation code I can monitor for the equivalent error message:

06  monitor ;
07    read TESTFILE ;
08  on-excp 'RNX1211' ;
09    dsply ('RNX1211: File not open') ;
10  endmon ;

Line 8: The ON-EXCP allows me to monitor for the error message equivalent of the file status 1211, RNX1211.

When this change is compiled and executed I see the following message:

DSPLY  RNX1211: File not open

ON-EXCP has an extender (C). If present this will only handle the error that occurs within the current procedure, or program.

Let me create a subprocedure that I will add to my program:

50  dcl-proc Procedure1 ;
51    update TESTFILER ;
52  end-proc ;

The update, line 51, will fail as the file, which was defined at the "global" level, is closed.

Below is the code I added to the main part of my program:

11  monitor ;
12    Procedure1() ;
13  on-excp 'RNX1211' ;
14    dsply ('RNX1211: Error in procedure') ;
15  on-error 202 ;
16    dsply ('Handled by 202') ;
17  on-error ;
18    dsply ('Catch all') ;
19  endmon ;

Line 12: The call to the subprocedure.

As this Monitor group contains both ON-EXCP and ON-ERROR the ON-EXCP blocks must come before the ON-ERROR blocks.

Lines 13 and 14: Is the ON-EXCP block to handle a RNX1211 error.

Lines 15 and 16: The first ON-ERROR block is for program status 202, which is for call to subprocedure or program failed.

Lines 17 and 18: The ON-ERROR has no status code, therefore, it is only executed if none of the above is true. I call this a "catch all" condition, like the OTHER in a RPG SELECT group.

When compiled and called the program returns the message from the ON-EXCP block:

DSPLY  RNX1211: Error in procedure

I change line 13 to add the C extender. The C does not have to be in upper case, I just did so to make easier for you to find.

11  monitor ;
12    Procedure1() ;
13  on-excp(C) 'RNX1121' ;
14    dsply ('Error from procedure not handled') ;
15  on-error 202 ;
16    dsply ('Handled by 202') ;
17  on-error ;
18    dsply ('Catch all')
19  endmon ;

After compiling the program again, when I run it the message from the ON-ERROR block, lines 15 and 16 is displayed:

DSPLY  202: Handled

The C extender in the ON-EXCP kept the handling just within the main body of the program. It did not handle the error from the subprocedure, as that is not part of the current procedure (main body).

I do really like this, and will be using it in my day-to-day work. One disappointment is that if I specify the error message in the ON-EXPCP like this:

11  monitor ;
12    Procedure1() ;
13  on-excp 'RNX1200' ;

It does not handle all of the messages RNX1200 – RNX1299, as it would do with the MONMSG command in CL.

MONMSG     MSGID(RNX1200)

 

You can learn more about the ON-EXCP command from the IBM website here.

 

This article was written for IBM i 7.5 and 7.4 TR6.

1 comment:

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.