Chapter 4. Designing the Business Logic

In this chapter:

The specification outline for the COBOL business logic component for the sample application is a simple one—to provide a program to perform create, read, update, delete, and browse operations on the customer account file.

The design phase for the component specifies in detail:

  • The interfaces to the component

  • Any errors the component may encounter and report

  • Usage constraints, such as the need to call the read operation before calling the update operation

It is important to note before starting to design and develop the component that the simple and incomplete specification above could be implemented in many ways, altering the balance of responsibilities and affecting the ease of development and debugging of the total application. In the real world, the final specification only evolves after several meetings involving the architect and the component developers, and a number of redesigns. As they work through the sample to get it right first time, consultation with the users of the application is critical to ensure the correct design decisions. During the design stage, you should include the following steps:

  • Determine what the COBOL component should do

  • Incorporate CICS design guidelines

  • Determine data handling

  • Design the individual functions

  • Map the functions to CICS programs

  • Check business logic programs

Understanding What COBOL Components Need to Do

The first step is to ensure that you understand what your architect has said that the component must do. It is also essential to talk to the actual users of the application to find out how they do their work and how they view the functions you intend to provide.

You need to check for information or functions that nobody requested but that nevertheless may be required when real work is attempted. Inevitably the users make the same discoveries after you’ve completed your programming effort, and you’ll be left to make changes later when it may prove difficult, rather than now when it is easy. It is very important to repeat this validation step as the design process moves along from a broad outline toward a more and more detailed specifications.

As a result of these deliberations, you decide that your COBOL component will provide interfaces to do the following:

  • Return the contents of a customer account record, given an account number.

  • Add a new customer account record, given an account number and customer data.

  • Modify an existing account record, given an account number and modified data.

  • Delete an account record, given an account number.

  • Access customer account records by name; that is, given a last name or part of it, return a list of matching names with corresponding account numbers and addresses.

The component must be able to accept these requests from other components running inside or outside CICS.

A fundamental principle of the design is that users must always read a record before modifying or deleting it.

Once you understand the purpose of the component, you need to consider other aspects of the design. These include the structure of the data, environmental restrictions, and the estimated workload.

Looking at the Data Structure

Naturally, the detailed design of your business logic is going to be influenced by the established form of the existing customer data. The account file is very much at the center of this application. Its records are shown in Table 4-1.

Table 4-1. Account File Records

Field

Length

Occurs

Total

Type

Account number (Key)

5

1

5

Read/Write

Surname (Last name)

18

1

18

Read/Write

First name

12

1

12

Read/Write

Middle initial

1

1

1

Read/Write

Title (Dr., Mr. and so on)

4

1

4

Read/Write

Telephone number

10

1

10

Read/Write

Address line

24

3

72

Read/Write

Other charge name

32

4

128

Read/Write

Cards issued

1

1

1

Read/Write

Date issued

6

1

6

Read/Write

Reason issued

1

1

1

Read/Write

Card code

1

1

1

Read/Write

Approver (initials)

3

1

3

Read/Write

Special codes

1

3

3

Read/Write

Account status

2

1

2

Read-only

Charge limit

8

1

8

Read-only

Payment history:

(36)

3

108

Future Use

Balance

8

  

Future Use

Bill date

6

  

Future Use

Bill amount

8

  

Future Use

Date paid

6

  

Future Use

Amount paid

8

  

Future Use

The fields marked as Read/Write are the ones that are to be maintained by your online program. Those marked Read-only are updated by an existing billing and payment application.

Assessing Restrictions

As well as the users’ requirements, certain other requirements are imposed by the environment in which the COBOL component runs. The component must:

  • Maintain the integrity of the account file using CICS functions. This means that it must be protected from inconsistent or lost data, whether resulting from a failure in the application or CICS or the operating system. It must also be protected from total loss, such as a device error or other catastrophe.

  • Accept requests from a variety of places.

  • Run the program in your CICS region.

  • Use the existing account file, a VSAM key-sequenced data set containing about 50,000 fixed length records of 383 characters each, including the 5-digit account number key.

Using an existing file and its predefined format illustrates one of the dilemmas with which designers are faced. The file as defined has a numeric key of length five so has a maximum of 99,999 records. In order to allow for future expansion, the key should be defined as alphanumeric and with just one letter in the key can grow to 359,964 records. Obviously the simple numeric checks that are in the code would have to be modified to fit whatever scheme is adopted.

Secondly, the use of a fixed length record is not the best choice for the future. This application does not use an explicit postcode or Zip Code, but if it had, the change in length would have a major impact where the designer would have to squeeze the elongated fields in, whereas if the record was defined as variable in length with spare space on the end, the change would be no more than a simple addition.

Estimating the Workload

Now is the time to find out how often the system is expected to cope with the transactions of each type, what sort of response times are expected, what times of the day the application has to be available, and so on. This allows you to design programs that are efficient for the bulk of the work, and it helps you to determine system and operational requirements.

For the sample application, you can assume that your inquiries produced the following information:

  • There will be about 100 additions, 500 modifications, 50 deletions, and 2,000 inquiries (by account number) per day in the accounting department.

  • The people in accounting are unable to estimate the number of inquiries that they would make by name, but they like the idea, and therefore may be expected to make some use of this facility.

  • The update and add activity is broken into separate functions, such as name and address changes, credit limit adjustments, and setting up a new account. Because these discrete activities are performed by different personnel, they could be attempted simultaneously for an individual customer. Another remote possibility is that the same account number could be erroneously assigned to two different new accounts. In order to ensure that conflicting work is not performed at the same time, the system needs to prevent more than one person operating on the same account at the same time. (This is a new requirement, not in the original specification.)

  • Customer services makes nearly 10,000 inquiries per day against account records, ninety percent of them by name. For most of these, the only items used from the complete account record are the name and address (to verify that it is the right record), and the credit status and limit. A management decision has been taken that payment history will be deferred to release 2.

  • Head office will only want to query the file, and do this on an occasional basis.

  • The requests from external users (customers) come in using another component that restricts access to inquiry on their account number only. The volume of these requests is unknown, but it is anticipated that this could become popular with customers, so scalability of the application is essential.

Tip

In assessing estimates of transaction frequency, you need to account for a fact of life: if you make it much easier to do something, such as an inquiry, users will almost certainly do it more often than they used to! Indeed, the eventual transaction rates experienced with online systems are almost always higher than can be predicted from the current workload—often a reliable indication of their success.

Summary

Having identified the purpose of the component, and other aspects of the design, you can now go on to design the processing programs that you’ll need. So, let’s continue now with some application design considerations. This implies that some element of scalability needs to be considered at the design stage.

Incorporating CICS Design Guidelines

To convert what you have learned about the requirements for your business logic component into a detailed design, you need to be familiar with some general design principles for server components.

There are three important things you learned from your estimation of the workload:

  • You need to design a highly scalable solution. By definition this means that you use the same resources in a number of different environments—thus improving your efficiency.

  • You need to prevent multiple users updating the same account record at the same time.

  • You need to design a clean approach to error handling.

Using Resources Efficiently

The resources you have to use efficiently are:

  • Shared resources:

    • Processor storage

    • Processor time

    • Transmission capacity to auxiliary storage space

    • Communication bandwidth

  • Single-user resources, which can be used by only one user at a time, such as file records being updated, scratchpad areas, and so on

Let’s examine these individually and develop some guidelines for designing and programming CICS applications from them. Remember, there’s bound to be conflict from time to time when trying to conserve one resource at the cost of another. The appropriate compromises vary from one program to the next.

Shared resources

You can use different techniques for locking (allowing single use of) specific types of resources. These are described in the following paragraphs:

Processor storage

In an online system, storage needs constantly change. Most exist only for the duration of a transaction, and so, in assessing storage needs you have to consider not only how much is used, but for how long. The trade-off between space and time requires the following storage consumers to be considered:

  • The internal CICS data areas associated with any transaction being processed. You should therefore minimize the duration of the transaction.

  • The program or programs being executed to accomplish the transaction. Don’t worry about the size of programs, because they are shared by all transactions and there is only one copy in the system at a time. It is much more important to structure the code well for ease of maintenance.

  • Keep the size of working storage areas as small as possible; for example, WORKING STORAGE in COBOL or large stack arrays in Java.

Processor time

In general, you need to conserve processor time. Calls for CICS or operating system services take much longer, relatively speaking, than straight application code. Avoiding unnecessary commands reduces processor time much more than fine tuning your code.

It is undesirable to do long calculations in an online program, because you may be sharing the process with thousands of other users. If such calculations are necessary, you need to use an application design approach that is beyond the scope of this book.

Auxiliary storage

Disk space and transmission capacity is optimized in an online system by minimizing input/output by, for example, creating additional indexes instead of performing sequential searches.

It is undesirable to do complex database queries in an online program. If such queries are needed, special design approaches are needed; these are beyond the scope of this book.

Communication bandwidth

There are two main principles governing community bandwidth:

Capacity

Send only the necessary data.

Latency

Send in a single message as much as is likely to be needed.

Single-user resources

Resources that can only be used sequentially by one user at a time are something that we do not want multiple transactions accessing concurrently. A file record destined for update is a perfect example of this type of resource. CICS provides a user-locking mechanism (called EXEC CICS ENQUEUE/DEQUEUE) for transactions to prevent concurrent use and CICS uses the mechanism internally to obtain a lock prior to using the resource and free it automatically at the end of the task or at a user syncpoint. While one transaction owns the lock, other transactions that wish to use this resource have to wait. Therefore, minimize the duration of transactions that require exclusive use of resources because everyone else who wants to update that resource is held in a queue until the lock is released.

CICS applications do not typically need to obtain locks explicitly, because CICS file and database operations use locks automatically to implement the Isolation property of ACID transactions. CICS locks can be held only for the duration of a single task. If a lock needs to be held for longer than this, other approaches are needed. This is discussed in more detail in the next section.

Maintaining File Integrity: Using Locking

When a user works on an account, she will bring the account details onto the screen, work with the information, optionally save changes to the database and cease working with the customer account.

There is a potential problem if two users try to do this on the same account at the same time. Both users could be making changes based on the same old copy of the record. Changes made by the first user to complete his work go into the file, but then changes from the second user will overwrite the first user’s updates. You must ensure that, when one user starts to work with a customer account record, subsequent users are prevented from doing so. As discussed in Transactions in Chapter 2, ACID transactions should not wait for user input. Thus, you can’t use the Isolation property of ACID transactions to prevent multiple users working on the same account.

Our solution is to introduce an application-level locking scheme that locks out other users between the initial display of the account details on the screen and ceasing to work with the customer record. Note that you can still exploit the capabilities of ACID transactions during the step that saves the changes.

Use of an application locking scheme is better than using ACID transactions from the perspective of users, too. If you used a long-running ACID transaction to protect against double updating, the second user would be locked out waiting for the first user to complete his work. With an application lock, you can tell the second user to try again later, and you can even pass information as to who owns the lock so that the second user (who may have the actual customer waiting on the telephone) can discuss the problem with the first. Let’s look at one way this locking mechanism could work.

Suppose that as soon as a user asked to update an account number, you make a note in a scratchpad area. (CICS provides scratchpad facilities for keeping track of things between transactions.) You can leave the number there until the update is entirely completed and then erase it. In our example, this means that if you write a scratchpad record in a subsequent transaction, it erases the earlier one. Before starting any update request, you can check to see if the account number is in use. If it is, you can tell the user this and ask him or her to resubmit the request later. Furthermore, you can let the user display the record even if it is in use.

This isn’t quite all, however. Because CICS ensures that transactions are either executed completely or not at all, you have to make sure that all your protected resources get updated in what CICS regards as a single transaction to ensure the consistency of your data. In the conversational case, (see Table 10-1) the program performs all the steps in one transaction. On the other hand locks are held over two terminal output/input operations so the scalability of the system might be adversely affected by a user going to lunch in the middle of a transaction. In the pseudo-conversational case (see Table 4-2), the files are all updated in the third transaction (this is the preferred solution), but the scratchpad is updated in two different transactions (not so good). The real benefit of this design is that no locks are held while waiting for user’s terminal input, so step 2 has disappeared between 1 and 3 and step 6 between 5 and 7.

Table 4-2. Example of Pseudo-Conversational Transactions

Transaction

Steps

Operations

First

1

Display menu screen

Second

3

Receive menu screen (which is presumed to contain a correct modify request)

 

4

Invoke the business logic component to read the required record

 

5

Display the record in formatted form

Third

7

Receive the changes

 

8

Update the account file accordingly

 

9

Re-display the menu screen

If the second transaction is completed successfully, but something happens to the third, the scratchpad record is written but not erased. Our data files would be consistent, which is the main concern, but you’d be unable to update the record involved until you could somehow reset the scratchpad.

You can get around this by designing a slightly more sophisticated scratchpad mechanism, for instance, by putting a limit on the time for which a transaction can own an account number. Then an error in the third transaction or thoughtless behavior by a user (going to lunch in the middle of a modification) will not cause an account record to become unusable for more than a short period of time. But all this involves extra coding and complications—is it worth it?

Absolutely. You can program your own mechanism for avoiding concurrent updates. Double updating is one of those problems you can tackle in a variety of ways. We chose a scratchpad. A drawback of a scratchpad, however, is that all future (and, as yet, unknown) transactions that update the account file have to refer to this scratchpad. However you can control this by the design you have chosen to separate the presentation logic from the business logic. Since all updating automatically manages the locking, this should be less of a problem than it may appear at first.

Handling Errors

As developers of a reusable component, you must handle errors well. Hence, your component does some or all of the following actions for each error, which correspond to the following table:

  1. Ensures that the system continues without damage by cleaning up:

    • ACID transactions

    • Conversations

    • Memory

    • Locks

  2. Ensures that the end user, or the calling program or component, knows what’s happened by means of an on-screen message or return code, or occasionally an abnormal end (abend).

  3. Ensures that CICS administrators know what’s going on.

  4. Ensures that you, the developer, can find out why the error happened by writing debugging information to a log file or providing a dump.

Categories of errors in a CICS transaction

The errors that can occur in a CICS transaction can be divided into five categories. For each category, you need to consider which of the error-handling actions are required.

Conditions that aren’t normal from the CICS point of view but are anticipated in the program

For example, when you try to read a record and get a “not found” response.

Errors in this category should be handled by explicit logic in the program. None of the error-handling described above are needed.

Actions needed: 2. (If a record is not found the user should be told.)

Conditions caused by user errors and input data errors

An error of this kind in the sample application would occur if a user tried to add an account number that already existed.

Errors in this category should also be handled by explicit logic in your program. Ideally, no errors of this type should be allowed to stop the program, or do anything else to upset the user.

Actions needed: 2.

Conditions caused by omissions or errors in the application code

These may result in the immediate failure of the transaction (abend) or simply in a condition that you believed “could not happen” according to your program logic. In the sample application, an attempt to add two identical records to the account file would represent this kind of error. You wouldn’t expect it, because you’ve already tested in the frontend transaction that no record with the same key is in the file. One of the main goals of the debugging process should be to get rid of this type of error.

Actions needed: 1, 2, 3, 4.

Errors caused by mismatches between applications and CICS resource definitions, generation parameters and Job Control Language (JCL)

An example is when CICS responds “no such file exists” to your read or write request. When you are first debugging an application, these problems are almost invariably your fault. Perhaps the definition of the file was not installed into the CICS system you are using to test or you spelled a name differently in the program than that used in the definition.

These conditions sometimes occur after the system has been put into production use as well. In this stage, they are usually the result of changes to a CICS resource definition, or a failure to install a resource definition, or JCL, more often than not related to some other application.

This category needs the same treatment as errors in a program that you are debugging. Once the program is in actual use, however, something more is needed when one of these conditions arises. You must give users an intelligible message that they or their supervisors can relay to the operations staff, to help in identifying and correcting the problem. For example, if an administrator has disabled a file for some reason and forgotten to re-enable it, you want a message to the operations staff that says that the problem is caused by a disabled file (and which file, of course). Moreover, you should program for these eventualities from the start, as this part of the program will need debugging just as well as the rest.

Actions needed: 1, 2, 3.

Errors related to hardware or other system conditions beyond the control of an application program

The classic example of this is an “I/O error” while accessing a file. As far as the application programs are concerned, this category needs the same treatment as the one above. Systems or operations personnel still have to analyze the problem and fix it. The only differences are that they probably didn’t cause it directly, and it may take much more effort to put right.

Actions needed: 1, 2, 3.

Handling Data

Having decided what you want to do, you can now determine what data is required to do it, and how to organize that data.

The Account File

In the sample application, you know that you need access to all the fields that make up records in the existing account file, because this is the data that you intend to maintain and display. You need direct access to these records by account number for several of the required operations (create, read, and so on). Happily, this file exists in a form directly usable by CICS (a VSAM key-sequenced data set (KSDS), with the exact key that you need).

This isn’t pure luck or coincidence. The account number is the natural key for this file, and a VSAM key-sequenced data set is a good choice for a mixture of sequential and direct processing, such as probably occurs now in the batch programs that already use this file. Table 4-3 shows the record format for this file.

Table 4-3. Account File Record Formats

Field

Length

Occurs

Total

Account number (Key)

5

1

5

Surname (Last name)

18

1

18

First Nname

12

1

12

Middle initial

1

1

1

Title (Dr., Mr., and so on)

4

1

4

Telephone number

10

1

10

Address line

24

3

72

Other charge name

32

4

128

Cards issued

1

1

1

Date issued

6

1

6

Reason issued

1

1

1

Card code

1

1

1

Approver (initials)

3

1

3

Special codes

1

3

3

Account status

2

1

2

Charge limit

8

1

8

Payment history:

(36)

3

108

Balance

8

  

Bill date

6

  

Bill amount

8

  

Date paid

6

  

Amount paid

8

  

The Name File

You’ll be accessing the account file records by account number, but you also need to access them by a second key—the customer’s last name. There are many ways of achieving an alternative path into a file. For example, VSAM provides a facility called an alternate index, which can be used in CICS.

CICS supports other data formats including SQL with the IBM DB2 relational database product, and hierarchical data access with the IBM IMS/DB DL/I product. These systems provide powerful cross-indexing facilities, and they have many other features that reduce the coding required in user applications. They support complex data structures, provide increased function and simplify the maintenance of file integrity. If you have data that you need to access by more than just a few different key fields, or if you have data that does not arrange itself into neat units like the account records in this application, you should use a database system. CICS also supports various non-IBM databases as well.

For this component you’ll use a simple technique, frequently used and quite appropriate to an application of this size. You’ll build an alternate index on the customer’s last name. This requires a one-time setup, and it means that every update to the base index (account number) is also accessible by both account number and last name (surname) without any extra intervention by your application.

The Locking File

One of the requests made when discussing the Accounts Department’s needs was that no conflicting work should be allowed at the same time. As considered in Maintaining File Integrity: Using Locking earlier in this chapter, you decided to use a “scratchpad” to implement the requirement of “locking” an account. The question then is how to implement this scratchpad. You have various alternatives, for example, temporary storage, but the easiest is to use a file. Table 4-4 shows the record format for this file.

Table 4-4. Scratchpad File Record Format

Field

Length

Format

Account number (Key)

5

Character

Owner:

12

Character

User

8

Character

Terminal

4

Character

Date

4

Packed decimal

Time

4

Packed decimal

Since the lock needs to be maintained by account, the account number is the field used. The logical owner of the account lock is a combination of the user field and the CICS terminal identifier since neither on its own can be guaranteed to be unique. First, CICS allows the same user to be active at multiple terminals. Second, the terminal identifier may not be relevant if entry to the system is using the CICS Client technology or Distributed Program Link (DPL). With CICS web enablement, the terminal identifier may be randomly generated.

As already discussed, the lock should have a limited lifetime. The current date and time are included when it is created. This can be tested later to see if a user has exceeded the time allowed for a lock to prevent an account from becoming unavailable.

The main drawback to this use of a file is the apparent contradiction of the resource usage guideline regarding performing unnecessary I/O operations. In fact, this can be overcome because CICS has a facility called a data table that allows the programmer to think they are accessing this use of the locking file, but in fact the data is kept in memory and no actual input/output operation takes place—the best of both worlds, simplicity and efficiency.

Recovery Requirements

As discussed already, CICS prevents loss of integrity associated with partly completed transactions. However, you must protect the account file from disasters such as a catastrophic device failure.

In some environments, you can keep an extra copy of an important file, or keep enough information to recreate it (such as backup versions and the input needed to bring it up to date). In a business application environment, this isn’t so easily done. You cannot copy the file after every update. Nor can you afford to lose all the updates since the last time you copied the file. These updates were entered at terminals by many different users, who may not remember what stage they had reached when you last secured the file, who may not have ready access to the input documents any longer, and who will certainly be very cross if they have to re-key a large number of transactions!

CICS provides facilities to address this concern. If you have a file that must be protected, you ask CICS to journal the updates. CICS then keeps a copy of every change made to the file. It logs these changes on an appropriate journal. If you lose a file, you go back to the most recent copy of it and then run a restore program that applies the changes recorded on all the journals created since that copy was made.

In your sample application, the account file is clearly a file that must be protected in this way. By way of contrast, the locking file is implemented as a data table where no I/O takes place, so changes to it are not written to a journal because no actual hardening of the data ever takes place. (In other words, no physical I/O takes place to move the data from volatile to non-volatile storage for this logical file.)

The only way this data would be destroyed is by the failure of the entire system, which would require a restart of all of the activity anyway; in this case, you would want to reconstruct the data as far as possible.

Designing the Individual Functions

The accounts department performs additions, modifications, deletions, and inquiries by account number. Head office only needs to view and add new accounts. Customer requests will be restricted to inquiry by their account number only. These are the classic Create, Read, Update, and Delete (CRUD) functions of an application. Because the lock handling is specific to the CRUD activities, you decide to include this function in the program as well.

However, customer service performs ninety percent of its inquiries by name. This quite distinct feature does not fall into any of the normal CRUD activities. As a result you have decided to split the business logic into two distinct areas, the CRUD activities and the browse activities. However, underlying each process are the three key functions of the common error handling, creating a lock and freeing a lock:

Common error handling

Because error handling can be invoked from a variety (and possibly increasing number) of frontend presentation programs, the first thing the backend business logic programs must do is to ensure that the data passed seems reasonable. If it is not, the backend program needs to generate an error message to be returned to the frontend caller. Other errors that are encountered need to be handled.

Creating a lock

We have discussed the need for locks and it is not surprising that this forms an important part of our code; this is required in order to ensure only one person can update the same account at a time. A check needs to be done to ensure that no other user currently owns the account record.

Freeing a lock

Because a lock must be obtained before any actual action is taken against an account, a function needs to exist to free it in case the user decides not to proceed with the original intention. A check needs to be done to ensure that the lock deletion is successful.

Figure 4-1 shows a summary of the key steps that are implemented in the business logic program. This is called NACT02 and you will find the complete code on the CD-ROM that accompanies this book.

Creating, Reading, Updating, and Deleting Account Records

The program (NACT02) adds a record to the file based on the data passed to it. It uses the three functions, handling errors, creating locks, and freeing locks, that we have just described. This procedure is common for the four functions of this part of our application (creating, reading, updating and deleting). However it must check that a lock is owned by the user requesting the add; this implies that a lock must be created. Likewise, at the end of the transaction the lock must be freed.

The process, therefore, consists of checking to see if a lock exists (maybe the record is in use by someone else). If not, it creates a lock, adds your record, confirms that it has been added sucessfully, and either returns an error message to the caller, or if it is successful, frees the lock and returns to caller.

Outline of the Create, Read, Update and Delete program (NACT02)
Figure 4-1. Outline of the Create, Read, Update and Delete program (NACT02)

Reading a record

This is slightly different from the process of creation, updating, and deletion in that there are actually two types of read required:

  • An inquiry only function

  • A read anticipating some sort of file update (thus requiring a lock)

If a lock was required, checking needs to be done to ensure that no other user currently “owns” the account. If all is well, then you attempt to read the record from the file.

Browsing Records

This logic attempts to find all matches on the accounts file for the criteria specified. The initial search uses the name file, but the application must perform more specific filtering (based on first name). The four phases of this program, which is called NACT05, are similar to those of the CRUD program as shown in Figure 4-1. As with CRUD, the initial phase sets up the basic function of error handling as well as validation of the correct form of user input. Copybooks are used in all the sample programs to define interfaces so that everyone has the same layout.

The browse program (NACT05) scans the database for records matching the input value supplied by the end user. The position within the file to start scanning is passed using an EXEC CICS STARTBR command. If there are no matches, the program should return an appropriate message back to the user. Browsing itself does not involve any locks, but, of course, when using last names for a search there is always the possibility of duplicates. In step 3 of Figure 4-2 the command EXEC CICS READNEXT is invoked to continue the browse until the key last name does not match the input and the remainder of the program returns the results and displays them.

It is good practice to use an EXEC CICS ENDBR command to free any pointers to the file when you have finished scanning for matches. CICS will clean this up, if this is not done, at task termination.

Error Processing

This is one of the most complex areas of the system since it needs to handle a wide variety of scenarios. In order to allow for the future expansion of the system to include other functions, this should be designed to tolerate some scenarios that cannot happen with the original specification but which might occur in the future.

These scenarios include the ability for the program to be entered in a variety of ways, either under application or CICS control. The program needs to distinguish between these different possibilities. Much of the logic is specific to the CICS environment and is discussed later. However, in general, the error handler needs to:

Outline of the Browse a Record program (NACT05)
Figure 4-2. Outline of the Browse a Record program (NACT05)
  • Record information about the problem.

  • Back out any changes made in the current Unit Of Work (UOW)—see the glossary for a definition.

  • Send messages to the user, to a log, and possibly to the systems administrator responsible for CICS.

  • Terminate the task or return to the application program requesting these services.

Figure 4-3 is a high-level overview of the error handling program. We’ll discuss this in more details in the next chapter when we talk about actually programming the constituent pieces.

Mapping the Functions to CICS Programs

You’ve now reached the point where you can start to arrange the processing of your component into CICS programs. There is no requirement that you use exactly one program for this—a component can consist of many programs. There is no requirement that you use one program per function—the parameters and returned values of a CICS program are in a data area called the COMMAREA and not controlled or checked by CICS. Hence you could put completely unrelated functions having entirely different parameters and returned values into the same program, providing there was at least one part of the COMMAREA that could be reliably used to determine which function the caller wanted.

Outline of the Error Handling Program (NACT04)
Figure 4-3. Outline of the Error Handling Program (NACT04)

You can observe that the functions that operate on a single record have many similarities. Since each of these functions requires the same sort of initial parameter verification and locking requirements it seems sensible to combine them into a single program.

On the other hand, the name search function is quite distinct in its requirements. Because there are no updates, it requires no locking logic and has a rather different set of input and output areas, so it is reasonable that this function be placed in a different program. Finally, the error handling is to be common so it should be a separate program as well. If it were not separate, the same code would need to be included in all of the other programs that would introduce a potential maintenance problem.

The scope of resource names within CICS is such that you need to agree them with the designers of other components running within the same CICS region/address space. However, because the mapping of components to a CICS is a decision that comes during deployment, it is in practice sensible to coordinate names across all applications within an installation. In our sample, the application architect decided that all CICS program names would begin with the four-character code NACT followed by a different number for each program. Figure 4-4 shows the outline of the components of the sample application. These three programs make up the business logic:

NACT02

The Create, Read, Update, Delete (CRUD) functions that operate on a single record.

NACT04

The error handling program.

NACT05

The name browse function.

Later we will discuss NACT01—the 3270 screen presentation logic and NACT03—the print presentation logic.

Summary of the components of the Sample Application
Figure 4-4. Summary of the components of the Sample Application

Looking at the Business Logic Programs

You’ve now defined three programs, (the business logic (NACT02), error handling (NACT04), and browsing records (NACT05)), that implement your component. In this section, we’ll review briefly what each program does. This material repeats much that we have discussed previously but it is arranged somewhat differently. Feel free to move on to the next chapter if you are already comfortable with the program structure that we’ve defined.

The Create, Read, Update, and Delete Backend Progam (NACT02)

This program is LINKed to by whatever frontend requires its services. It executes as a stateless task, reacting in isolation to each request without reference to what might have been requested previously by the user—that is the job of the frontend program.

When called, the program validates and analyzes the request. Once accepted, the request is acted upon according to the action demanded. Thus, locks are checked, added, or deleted as appropriate and the account file is accessed as it should be.

A key detail in the implementation of this program is that the EXEC CICS commands used should conform to the DPL subset as defined in the CICS Application Programming Guide. If this is done, any component can be used unchanged by the various frontend invocations.

The program uses the standard error handling approach designed for the application, and uses CICS facilities to identify program NACT04 as the one to be invoked in the event of an abend occurring, as well as using it to process any unexpected errors that may arise.

The ABEND/Error Handler Program (NACT04)

This program implements the standard error handling actions designed for the application. It is designed in such a way as to be able to allow it to be entered in a variety of ways for maximum flexibility. It can:

  • Have control transferred to it under application control (EXEC CICS XCTL)

  • Be called using CICS services (EXEC CICS LINK)

  • Be called using COBOL services (Dynamic CALL)

  • Be entered as a result of CICS abnormal end processing (EXEC CICS ABEND)

As the program needs to distinguish between these different possibilities, it obtains information from CICS about its environment. Depending on how the program was entered, it obtains information about the problem from data passed to it or directly from CICS. It builds messages appropriate to the type of error. Then it initiates a transaction dump, backs out any changes made to recoverable resources (for example, the account file), and outputs the messages to the locations appropriate to its environment. It then finishes its processing in a manner that ensures the task is eventually (if not immediately) terminated.

The Name Browse Backend Program (NACT05)

This program is LINKed to by whatever frontend requires its services. It executes as a stateless task, reacting in isolation to each request without reference to what might have been requested previously by the user—that is the job of the presentation logic.

When called, the program validates and analyzes the request. Once accepted, the request is acted upon according to the action demanded. Thus, records are returned to the caller based on the criteria supplied by the end-user by reading the account/name file.

Summary

Essentially these programs implement the processing described earlier in “Common error handling” and Browsing Records. There are some important points to note about the implementation of this logic. The name browse program can return up to 80 name matches. This may be too many, but it does mean that the total length of the COMMAREA returned is less than the maximum 32,500 bytes. With this limit, this implies:

  • There is a maximum number of matches that can be returned in one call.

  • The program must not only implement a browse function but also a continue function to overcome that upper limit of matches that can be returned in one call.

The program implements the standard error handling approach designed for the application.

Get Designing and Programming CICS Applications now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.