Serving Modules
Service programs consist of one or more modules. By referencing a service program at the time a program is created, any module that is defined in your service program export list is available to your program for binding. As a result, you end up with a "buffet" of procedure choices without the added complexity of listing them each individually on the CRTPGM command. Any collection of *MODULE objects can be used to create a service program, including "main" modules, but even so, neither a service program nor any of its procedures can be called directly; instead, they must be bound by a program. A service program has an object-type of *SRVPGM, and, like a *PGM object, once it has been created the constituent *MODULE objects can be deleted.
Let's return to the original example, only now we have four modules to bind together in order to create the program. Our command now looks something like this:
CRTPGM PGM(MYLIB/MYPGM)
MODULE(MYLIB/ENTRYMOD MYLIB/PROC1 MYLIB/PROC2 MYLIB/PROC3)
As you can see, the command just gets longer and longer, but we are about to change that. Let's assume that PROC1, PROC2, and PROC3 are all subprocedures and that they are used extensively throughout our software. Instead of maintaining them individually like this for each command, you want to put them into a service program. Here is a command that will do so quickly: CRTSRVPGM SRVPGM(MYLIB/MYSRVPGM) MODULE(MYLIB/PROC1 MYLIB/PROC2 MYLIB/PROC3) EXPORT(*ALL)
You now have a *SRVPGM object called MYSRVPGM. By specifying EXPORT(*ALL), you are making all of the modules listed on the CRTSRVPGM command available to any program that references the service program at creation time. Before I continue I must point out that this is not how I recommend managing the objects in your service programs, but is invariably where everyone starts and is a crucial step toward understanding service program maintenance. You can view the module contents of the service program by running this command:
DSPSRVPGM SRVPGM(MYLIB/MYSRVPGM) DETAIL(*MODULE)
Run this command without a DETAIL attribute specified, and you can scroll through 11 different displays and get a great deal of information.
Now when you want to create the program, the command looks a little different:
CRTPGM PGM(MYLIB/MYPGM) MODULE(MYLIB/ENTRYMOD) BNDSRVPGM(MYLIB/MYSRVPGM)
Hopefully, you will agree that this command is much cleaner to use, especially if you had 30 modules instead of three. While this is nice, the greatest benefit comes when you need to change a module. In the first example, you had to execute the Update Program (UPDPGM) command for every program that uses the module, which was not a pretty maintenance picture. With service programs, you only have to issue one command, UPDSRVPGM, like so:
UPDSRVPGM SRVPGM(MYLIB/MYSRVPGM) MODULE(MYLIB/PROC2)
Doing so updates not only the service program itself but also all of the programs that have bound PROC2. This automatic update is perhaps the best argument for using service programs, but it can also cause its own set of problems.
Tuesday, June 17, 2008
Wednesday, May 28, 2008
RTNDTA Display file Keyword
In most of our RPG program we would perform the following steps:
1. CHAIN and release the database record without lock.
2. Move the appropriate database fields to the screen fields.
3. Display the screen.
4. Read the screen looking for changes and, if changes had been made, then we would CHAIN again to the database record.
5. Move the appropriate screen fields to the database fields. 6. Finally, update the record.
This process can be made easier with the DDS keyword Return Data (RTNDTA). This keyword can eliminate the need to create separate variable names in display files used for database file updates. The display file can reference the database fields instead. No need to worry about field attributes matching between the database file and the display file. We don't have to code any MOVEs or Z-ADDs, and the program size is smaller as there are not as many variables.
Here's how it's done. DDS coding:
Place the RTNDTA keyword at the record level on the appropriate record of the display file. Use the database field names and reference the database file. This will bring the database fields into the display file automatically when you retrieve the database record. RPG coding:
1. CHAIN and release the database record.
2. Display the screen.
3. Read the screen looking for changes and, if changes have been made, CHAIN again to the database record.
4. Reread the display format using the READ operation. This is what makes this technique work. Since we CHAINed again to the database record, the internal representation of the display file record is overlaid and any changes to the display record are lost. But by reading the display record again (with the RTNDTA keyword), you can retrieve the original values of the screen.
5. Update the database record.
1. CHAIN and release the database record without lock.
2. Move the appropriate database fields to the screen fields.
3. Display the screen.
4. Read the screen looking for changes and, if changes had been made, then we would CHAIN again to the database record.
5. Move the appropriate screen fields to the database fields. 6. Finally, update the record.
This process can be made easier with the DDS keyword Return Data (RTNDTA). This keyword can eliminate the need to create separate variable names in display files used for database file updates. The display file can reference the database fields instead. No need to worry about field attributes matching between the database file and the display file. We don't have to code any MOVEs or Z-ADDs, and the program size is smaller as there are not as many variables.
Here's how it's done. DDS coding:
Place the RTNDTA keyword at the record level on the appropriate record of the display file. Use the database field names and reference the database file. This will bring the database fields into the display file automatically when you retrieve the database record. RPG coding:
1. CHAIN and release the database record.
2. Display the screen.
3. Read the screen looking for changes and, if changes have been made, CHAIN again to the database record.
4. Reread the display format using the READ operation. This is what makes this technique work. Since we CHAINed again to the database record, the internal representation of the display file record is overlaid and any changes to the display record are lost. But by reading the display record again (with the RTNDTA keyword), you can retrieve the original values of the screen.
5. Update the database record.
CHAIN in CL program
Most AS/400 programmers are familiar with the Override Database File (OVRDBF) command for substituting one file for another, changing a file to share an open data path (ODP), and other common uses. But many may not be aware that it can also be used with the Receive File (RCVF) command to perform random record access, similar to CHAIN or SETLL operation codes in RPG.The way to do this is to use the POSITION parameter of the OVRDBF command. It can be used to get a record with a certain key value. To do this, you must specify the name of a field and one of the following search values.
• KEY (Key Equal)-The record with the given key value will be retrieved.
• KEYA (Key After)-The record following the record with the given key value will be retrieved.
• KEYAE (Key After or Equal)-If a record with the given key value exists, it will be retrieved. If not, the record with the next higher value will be retrieved.
• KEYB (Key Before)-The record preceding the record with the given key value will be retrieved.
• KEYBE (Key Before or Equal)-If a record with the given key value exists, it will be retrieved. If not, the record with the next lower value will be retrieved.
The following code fragment demonstrates the use of the POSITION parameter of the
OVRDBF command.
DCLF FILE(MYFILE)
OVRDBF FILE(MYFILE) + POSITION(*KEY 1 MYFMT KEYFLD)
RCVF
This example will retrieve a record from file MYFILE (format MYFMT), which has a key value matching the value in the field KEYFLD. The other key search values work similarly.
• KEY (Key Equal)-The record with the given key value will be retrieved.
• KEYA (Key After)-The record following the record with the given key value will be retrieved.
• KEYAE (Key After or Equal)-If a record with the given key value exists, it will be retrieved. If not, the record with the next higher value will be retrieved.
• KEYB (Key Before)-The record preceding the record with the given key value will be retrieved.
• KEYBE (Key Before or Equal)-If a record with the given key value exists, it will be retrieved. If not, the record with the next lower value will be retrieved.
The following code fragment demonstrates the use of the POSITION parameter of the
OVRDBF command.
DCLF FILE(MYFILE)
OVRDBF FILE(MYFILE) + POSITION(*KEY 1 MYFMT KEYFLD)
RCVF
This example will retrieve a record from file MYFILE (format MYFMT), which has a key value matching the value in the field KEYFLD. The other key search values work similarly.
Subscribe to:
Posts (Atom)