We are going to keep our attention on service programs at this point because there are a couple more things that should be discussed. And we are going to start with binding directories.
Editor's Note: This article is excerpted from chapter 19 of 21st Century RPG: /Free, ILE, and MVC, by David Shirey.
Please see the previous article here: Service Program Compile Stuff.
At this point, I want to say something very important. Are you ready? I always like to warn people when something important is going to be said. Generally, it tends to be a bit of a surprise for most people. When I say it, at least. But, here we go. Over the next two chapters we are going to talk about two things: binding directories and binding language. What is important to know is that they are not really related. A binding directory is not a place where a bunch of binding language objects are stored. They share the word “binding,” but that is about all they share. But I can’t say anything more because it will spoil the surprise.
Binding directories involve the calling program and are solely designed to make it easier to write out the compile command for that calling program.
Binding language involves the service program and the sub-procedures that are exported from it.
OK. I feel better now having warned you. Ready to continue? We are going to start with the binding directories.
The first thing I should probably say is that binding directories are not required.
You can do service programs and all that without them, and, in fact, we have done service programs and all that and haven’t used them (see chapter 9). But, as we shall see, they can come in really handy once you have more than one service program, and my guess is eventually you will.
To understand where binding directories come into play, let’s return to our compile scenario for the program that calls a sub-procedure from a service program. And specifically, let’s remember that when we call the service program, we actually call the sub-procedure that we want to use, not the service program per se. So the question immediately surfaces as to how the system finds that sub-procedure. How does it know what service program to look into? In other words, how do we bind that service program to the calling program during the compile when we only know the sub-procedure name?
And the answer to that, as we saw in the last chapter, is when you do the CRTPGM on the calling program, you enter the name of the service program you want to bind to—that is, the one that contains the sub-procedure you are accessing. You do this in the BNDSRVPGM parameter of the CRTPGM command. And that’s it; no need for binding directories or any of that pretty boy stuff. When the system is ready to call a sub-procedure, it looks at the list of service programs in this BNDSRVPGM parm, starting with the first one entered, and looks for the sub-procedure we are trying to call. It gets picked up and executed, and the system just a keeps on a rollin’.
But what happens if you are accessing multiple sub-procedures from multiple service programs? Yes, you can put a plus sign in the BNDSRVPGM parm and get several slots in which to type service program IDs, but that could wear a bit thin if you had many service programs or if you were the type of person who makes typos. Remember, you would have to put all of them in every time you did a recompile of the calling program. Maybe that wouldn’t happen very often.
Maybe it would.
The purpose of the binding directory is simply to allow you to create a “list” of service programs that should be bound to this calling program and then allow you to key in that binding directory name (in the BNDDIR parm of the CRTPGM command) rather than a list of service programs (in the BNDSRVPGM parm). You end up entering less data with the compile (or H-spec), and it uses the binding directory as an intermediary in finding the name of the service program. CRTPGM is the only command that has a spot for binding directory. It is not in CRTRPGMOD or CRTBNDRPG.
The directory contains a list of the service programs that have specifically been added to the directory. It does not carry a copy of the program object (or source) itself, so there is no code or object duplication.
In addition to service programs, you can also just list modules, the output of CRTRPGMOD for programs that you want to bind into the calling program. We generally think of binding directories for service programs, but they do modules, too.
What is important to remember is that even though the binding directory is described here as a list, it is an object (*BNDDIR), not just a source file, and it is set up and maintained through a series of system commands that we will see in a minute. Binding directories are an object set up via system commands.
Big Directories or Small?
One thing you might be thinking right now is, should I just put all my service programs in one big binding directory, or should I have several smaller ones?
I have no clear answer on that. If you use a big directory, then even though a thousand service programs are listed there, the system will only pick up and bind the ones that you are actually accessing from your calling program. So you won’t have a size penalty.
On the other hand, if you have different parts of your system that are really different from each other and there is no overlap, then several directories might make a lot of sense from a separation point of view. There is room in the CRTPGM command for multiple binding directories, so you are limited only by your own common sense. I know. It’s a thin layer of protection, isn’t it?
Using an H-spec
Of course, even with the use of binding directories, it can get a little tedious filling out your compile command by hand. Fortunately, there is an H-spec that you can incorporate right in your program to take care of that for you.
Binding Directory Commands
A binding directory is not a source file list, but an object created and maintained by a set of commands.
First, the CRTBNDDIR (Create Binding Directory) command:
CRTBNDDIR BNDDIR (bnddir-name)
As you might expect, it creates the directory. This is it, sort of like the CRTLIB command, with no extra parms. Although now that I think of it, CRTLIB has a few extra parms, so never mind. It creates an object with a type *BNDDIR in a library. You don’t create this object with a compile, just with this command.
Second, the ADDBNDDIRE (Add Entries to the Binding Directory) command:
ADDBNDDIRE OBJ((obj1 obj-type1) (obj2 obj-type2) ...)
This adds service programs or other modules to a directory once it is set up. Only the name is added here, not the object. That is, it adds the name of a service program to your *BNDDIR object, but it does not include a copy of the service program object as well. The *SRVPGM object is picked up when you run the program that has this binding directory attached to it.
There is also a POSITION parm that lets you decide, if you are setting up a series of binding directories, where this one goes with respect to the others.
The default value is *LAST, but there is also *FIRST, *REPLACE,
*BEFORE, and *AFTER. For the *BEFORE and *AFTER parms, you can then specify the name of the binding directory you are making reference to.
Third, the RMVBNDDIRE (Remove Binding Directory) command:
RMVBNDDIRE OBJ((obj1 obj-type1) (obj2 obj-type2) ...)
This removes a binding directory from the object.
Fourth, the WRKBNDDIR (Work with Binding Directory) command:
WRKBNDDIR BNDDIR(bnddir-name, *ALL)
This provides you with a work command that, by using *ALL as the binding directory name, lets you see what binding directories are out there.
Fifth, the WRKBNDDIRE (Work with Binding Directory Entries) command:
The second “work with” command requires you to know the name of the directory you want to work with. But it takes you right into the functions you want to do, whereas with WRKBNDDIR you need two steps.
Depending on what information you have (whether or not you have the name), you can choose the command that is most useful.
To Binding Directory or Not
And the answer is, it’s up to you. They are not required; you can easily (sort of) just key the list of service programs you are binding your calling program to in the CRTPGM command every time you compile. And so maybe it depends on how often you change your calling programs. In a perfect world, that might not happen that often. On the other hand, the world, for most of us, is far from perfect.
All in all, I think it’s useful, especially if you use an H-spec to tie it in. It saves time, prevents keying errors, is easy to set up—there’s no real downside. Seems like a useful tool to me. But it’s up to you.