|
|
![]() |
|
|
Add Oomph to Your Commands with Validity Checking Programs by Kevin Vandever [The code for this article is available for download.]
How many of you out there have written your own CL commands? A lot of you? Great! You know, then, that one of the tricky parts of a command is the validation of parameters. How do you keep the user from entering junk into your commands? The best way to accomplish this validation, in my opinion, is to write a validity-checking program. Sounds impressive, eh? Well, come on in and learn, not only how to write one, but some additional uses for them as well. One Feature, Many Functions Notice that I said "the best way" and not "the only way" to validate your command parameters. That's because there is more than one way. You can use the command source itself to validate the parameters. This works very well if you know all the possible values up front. You can then list those values inside the source of your command, and they will be used to validate against what the user enters into the parameter when he runs the command. For example, in my homegrown command, DSPDTAQ, I want to validate the data queue and library entered by the user. I will use a validity-checking program to do that; however, if I simply wanted to ensure that a value was entered in the parameter, I could do so right in the command source code and not use a validity-checking program. If you look at the DSPDTAQD source code, you will notice that I have defined the minimum number of values as 1 for the QUEUE parameter. There's no need for an extra program, because I can require that the user enter something in this parameter right in the source code. This also comes in handy for parameters where all the values are known. If I had added an OUTPUT parameter to allow the user to specify whether the results should be displayed on the screen or in an output file, I could add the valid values of * (to signify the screen) and *OUTFILE in the VALUES entry of that parameter, which would ensure that the user entered one of those two values in the OUTPUT parameter. OK, enough with how not to use a validity checking program. If you don't know the values up front, as is usually the case, you will need to program the validation yourself. Still, you don't need a validity-checking program to accomplish this. You could use the program that is processed when the command is called. For example, in my DSPDTAQ command, I could validate the parameters with the same program that actually gets the data queue information, but there are a couple of reasons why I should use a separate program--yes, finally a validity-checking program. For one, I like to keep my validation separate from my business rules, so that both can be reused in other places. If I separate the validation logic, I may be able to call it from another program or use it as a validity-checker in other commands. This would be harder to do if it were bundled with the business logic. Also, a validity-checking program can do more than validate parameters. I used one with the DLTSPLF (Delete Spool File) command once to catch someone who was deleting reports but was denying doing so. The company didn't have any auditing turned on, so I wrote a validity-checking program and applied it to the DLTSPLF command, so that whenever someone deleted a spool file, an entry was written to a data queue that contained the user ID as well as the spooled file information. We soon caught our culprit and dealt with him appropriately. Now you may not need to do something so heroic. Ha! The point is that there are other uses for a validity-checking program outside of validating data. Back to my DSPDTAQD example, I decided to write a validity-checking program to validate the data queue and library entered by the user. You notice that there is no logic in the command source code that validates unknown values. It can't be done. So where is the logic? And what exactly does a validity-checking program look like? Sample Parameter Validation Program DSPDTAQDVC is a normal looking CL program that I will use as my validity-checking program. Before I talk about the program itself, I want to explain how to link a command with a validity-checking program. It's easy. There is a parameter in Create Command (CRTCMD) that allows you to enter the name of a validity-checking program. The parameter name is "validity checking program," so you shouldn't miss it. The program need not be created when you compile your command, but it had better be there when you run the command or the command will end abnormally. My program accepts one parameter. Your program can accept as many parameters as you have in your command, but since I only have one, I only need one. What? You say I have two parameters? Aha! It's really only one. If you look back at the DSPDTAQD source code, you will notice that there is only one PARM entry, QUEUE, and it has a type of QUAL, which means that it will be qualified by something later on in the code. That something is going to be a library. It may look like two parameters, but it's only one. So when you define the variable in your program, you must make room for both the data queue name and the qualified library. That's why I have declared it 20 bytes long. Like I said before, there is nothing magic here. I use the CHKOBJ command to validate if the data queue and library combination exists. Then, depending on which CPF message I get, I send an appropriate message back to the command. If CPF9801 is trapped, that means that the data queue doesn't exist in the specified library. If CPF9810 is trapped, that means that the library doesn't exist. In either case, I will send the appropriate message to the user via the Send Program Message (SNDPGMMSG) command. If I don't trap any messages, the parameters are considered valid and the command moves on its merry way. You could add more validation if you wanted to, but these two errors are the only two I really concern myself with for this command. The first MONMSG block sends an error message telling the user that the data queue doesn't exist in the specified library. I set up a pretty cool message in the application's message file that allows two substitution parameters: one for the data queue and one for the library. That way, I can make my error message look smarter. The second MONMSG block will handle invalid library errors and send the appropriate error message back to the command. A couple of notes on the substitution parameters. If you decide to add a message to a message file that contains substitution parameters, you have to account for the 4-byte character reserved parameter that exists within the message. For example, I created a message like the following: Data Queue &2 in library &3 is not found. When I defined the two substitution parameters, I had to first define the reserved parm as a 4-byte character field. You can number your parms how you like (although I like to start with &2, so that I remember that the first substitution parm is reserved), but when inserting values into those parameters as a part of the SNDPGMMSG command, you must account for it. Take a look at my validity-checking source code, and you will see that I set up two parameters, MSG1 and MSG2. These parameters will hold the values that will fill the substitution parameters in my message. As you can see in MSG1, I concatenated 0000 to the queue name and library. The first four bytes will then satisfy that reserved parameter. If you don't account for it, you will not get the results you desire when displaying your message. One last thing to note is that I used the SNDPGMMSG command twice in each MONMSG block. This has to be done if you want your messages to display while the user is still in the command. The first SNDPGMMSG sends the appropriate error message to the program's message queue; the second SNDPGMMSG is an escape message that will tell the program that error messages have been found. This will only work if the second message sent is CPF0002. This is a special message that subsequently sends a CPF0001 message to the program to alert it that there are messages. If you don't include the second SNDPGMMSG, you will still get the error messages but the user will have to display his job log to see them. And if you use something other than CPF0002 as your second message, your program will end abnormally. Validate Away! Armed with this new tool, you can now easily validate the parameters of your homegrown commands, as well as add some cool features to IBM or third-party commands. I covered a lot of information, but take some time to look at the code I provided and apply it, or something like it, to your commands. For those of you who think this is a very cool idea, but you're not that familiar with commands, fear not, I feel a back-to-basics article coming along in a future issue that will discuss how to create your own iSeries commands.
|
Editors
Contact the Editors |
|
Last Updated: 11/7/02 Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved. |