Jazz On Line Programming: Introduction

Jazz On Line Programming: Introduction. 1

General On-Line Concepts. 1

Writing On-line Programs. 2

Generating a New CICS Program.. 2

Creating a Screen. 4

Basic Menu Processing. 6

On-line Program Logic. 7

Automatic processing – at start 7

Default processing of AID keys. 8

Automatic processing – at end. 8

Testing our CICS Program.. 8

Re-Testing our CICS Program.. 13

Writing an On-line Enquiry Program.. 13

Alternate Indexes:  DKEY and UKEY. 14

Generic keys and Wildcard characters. 15

Handling Multiple Records. 18

Next:  Complex Enquiries and Updating Files. 18

One other thing – Displaying and Entering Coded Fields. 19

Testing our 2nd CICS Program.. 19

 

Prerequisite reading: Introduction to Jazz.

 

Although Jazz minimizes the differences, there remain substantial differences between on-line and batch programming, and some new concepts will need to be learned so we start with a general introduction to On-Line Processing Concepts. This chapter should be read before the later sections dealing with more complex enquiries and record updating are read.  Even if you are going to start straight away with Web Services and Service Oriented Architecture and are never going to write “Classical” CICS programs – i.e. using 3270-type screens – it is worth quickly reading this chapter first.  The heavier stuff – more detail on handling 3270 screens and dealing with record updating – is covered in the next few chapters, and I’ve tried to leave most of this detail out of this chapter so that those who are going straight to SOA can just get the minimum understanding that they need.

General On-Line Concepts

The most obvious difference from batch programming is that an on-line program communicates with a terminal. This has several important effects on the program structure.

 

Firstly, terminal communication is used to control the program. An on-line program establishes a dialogue with the operator and is, in effect, continually asking the operator what to do next. For example, a system may start by displaying a screen such as:

 

            XYZ COMPANY INVENTORY SYSTEM 
            CHOOSE FUNCTION REQUIRED FROM LIST BELOW:
            1.         INSPECT INVENTORY
            2.         ORDER PART
            3.         MAKE UP CUSTOMER ORDER
            4.         INSPECT ACTIVITY FILE
               SELECTION  _

Depending on the response from the operator, the program then continues along a particular path. This may involve many further responses and operator decisions. Typically the program spends microseconds doing processing, and minutes waiting for a response: almost all of its time is spent waiting. A terminal is a very slow device since its speed is that of its human operator: even a simple interaction will require the operator to read the screen, think about what they’ve read, and press a key in response. A more complex transaction may require that the operator think about potential responses, look up instructions and check information, perhaps with a customer on the phone, while the terminal waits for the response. A complete transaction such as making an airline booking may involve many interactions and may be spread out over many minutes.

 

In contrast, batch programs are written to process many transactions with minimal operator intervention. A typical batch program will read a file and produce a report: once started it will spend significant time doing its processing before its output is ready to be read, and any waiting time (for the next record) is minimal. The processing/waiting ratio is minutes/microseconds, the reverse of the on line situation.

 

This makes the structure of on-line and batch systems very different. For example, an on-line system must be capable of changing rapidly from one task to another, usually doing very little in each task. Since there may be an enormous number of possible permutations of task sequence, an efficient mechanism for passing control from one task to another is important.

 

Secondly, an on line system may have hundreds or even thousands of users using the system at the same time. Imagine a travel agent making an airline reservation, a process that may take up to half a hour as the travel agent discusses flight options with the customer in front of them or on the phone. In the meantime, other agents around the world are also making reservations, possibly on the same flight. An on-line system must be written so that this is taken into account. Each user must be able to use the system as if they were its only user. While waiting for the response from one user, the system goes on with servicing others. When the response is received, the system must be able to continue as if uninterrupted. In the meantime, other users may have updated information in files accessed by the first user. The on-line system must therefore be able to cope with potential problems which arise when two or more users attempt to update the same record.

 

The on-line system must also cope with the problems of potential system failure. What happens if the system fails while several users are in the middle of transactions which can update files? With a batch system the job can be rerun using the original inputs. Only with unusually long processes or very large databases is it necessary to provide a specific recovery mechanism other than restoring files to their initial state and rerunning. Contrast this with an on-line system where actions may have been taken and decisions made on the basis of inputs which no longer exist.

 

These problems are common to all on-line systems, and so a standard solution is supplied by IBM. Instead of each application programmer having to individually code logic for rapid task switching, data sharing, recovery, and all the other common features of on-line systems, it is taken care of by a standard teleprocessing system, CICS. On-line programs are therefore written as tasks for this system, whether they are “green screen” applications typical of 1970-style systems, or web services supplying data to clients which might be Windows programs, web pages, or mobile apps.

Writing On-line Programs

We’ll illustrate the process with a few very simple programs.  The simplest way of creating an On-Line Jazz program is to click the [New] button, select the program type and set a few other details, and have Jazz create it for you.  We’ll do this as we create a menu program that invokes one of three other programs, a Customer Enquiry, Customer Update, or Order enquiry/update.  This is about as simple as it’s possible to get: the menu doesn’t have to look up files, let alone edit them. All it has to do is to show a screen offering choices, and then do something depending on the operator’s choice.  At the start we have neither the program, nor the screen: we’ll develop both.

Generating a New CICS Program

1.            Click the [JazzGen] button: -

After prompting you to save the current program, Jazz responds with the “New” screen. Expand the categories at the left until you find what you’re looking for, which in this case is “New CICS Program”: -

 

2.                   Click “New CICS program”.  Jazz responds with a screen with options for this kind of object: -

We

a.                   Give the program name.  You’d check the Replace checkbox if it already existed and you wanted to replace it.  In this case we’ll call the program MENU1

b.                  The screen name and commarea name will be given by default by adding “S” and “C” to the program name. We may as well accept these defaults.

c.                   Enter a transaction code (TRANSID) that will initiate this program.

d.                  Select the program type: we want Basic.

e.                   Select the screen type: 3270 or Web page. Since (in 2015) the only option is 3270, we’ll choose that.

f.                    Click [Finish]

That’s it!  Jazz will first create the Commarea, then it creates the screen, and then the program.  The next thing that we see is the generated program: -

 

The first thing that we do is to edit MENU1C, the COMMAREA definition.  Right-click on the keyword COMMAREA to see: -

 

Menu1 will have three alternatives, and we’ll be asking the user to enter a number 1, 2, or 3.  We add a definition for a suitable field: -

DEFINE MENU1C COMMAREA DATA(

    Function PIC '9' RANGE(1:3),

    JZ-XCTL CHAR(1) BOOLEAN);

The other field, JZ-XCTL, is a CHAR(1) field that may have value “Y” or “N”.  It is used by Jazz, so you should not remove it.

Creating a Screen

Now we return to our program and click [Screen].  We can see that Jazz has generated a screen, but it’s essentially empty, so we edit it to provide the menu function that we want.  Mostly this is just typing text on to the screen, until we get to the point where we want to put the function code on to the screen.   To put this field into the screen we

1.       Expand the MENU1C definition

2.       Drag the field Function from this definition on to the screen

 

 

Note that when we dragged Function on to the screen the drag-and-drop created three fields: a constant “Function” that is the field’s name (or HEADING) from its definition, an input field with the correct format, and an asterisk.   When the program is running the asterisk is normally hidden, but it will become visible if a user enters an invalid function value.

 

Any of these constants or fields can be dragged around the screen if we’ve put them in the wrong position.  Swipe the area you want to move: -

 

then hold down <ctrl> while clicking on one of the objects in the selected area.  The selected items are highlighted: -

and can now be dragged to any empty area of the screen.  (“Empty” includes the current position of the selected items, so you can easily drag them a character or two left or right).

 

When we’ve got the screen edited to our satisfaction we click [Save] or [Process] to return to our program.  [Save] saves the screen locally, creating a screen description that we can re-edit at any time.  [Process] also does this, but it also submits a job to the zOS system to compile our screen (CICS calls it a “map”), a necessary step before we can use it.   If we click [Process] then as we continue with the next step, editing the program logic, you’ll see the job submission messages appear at the bottom of the Jazz workbench until [Job Results] turns green.  When this happens you can inspect the returned job, which will be a BMS assembly.

Basic Menu Processing

Returning to our program we write the logic to do what we want: -

 

1.                   We start by writing “Accept (Function);” which Jazz changes to ACCEPT (MENU1S.Function); when the program is checked. This moves Function from the screen to MENU1C, but even more importantly it checks it – that it is numeric, and in the range 1 to 3.  If an invalid value is entered then the “*” becomes visible and a message such as “Function Not Numeric” will be put in the error field at the bottom of the screen.

2.                   Now all we need to write is logic to invoke the various programs for options 1, 2, and 3.   The CASE statement is ideally suited to this kind of logic.

Here is our complete program: -

 

Click [Process] and the program is submitted to zOS to be compiled.  If we have also processed the screen then we’re almost ready to test our first CICS program.  Before we look at this, we should take a little time out to look at what’s going on.

On-line Program Logic

In contrast to batch programs where the heart of the logic is a PROCESS statement controlling an I/O loop, on-line program logic is executed once: basically

            Process the Input data.  “Input” is the input screen and the Commarea (if any)

            SEND a response

 

Once we have sent a response the system has to wait for a reply.  Even when the user is very fast this will take many seconds, and it might take minutes.  We don’t want our program waiting for a reply because this will lock up resources that other users may need, so Jazz CICS programs are “pseudo-conversational”. In other words, the program terminates as soon as it displays another screen (SEND) or exits (EXIT). If you want to save any data for later you must save it explicitly by putting it into a special area called COMMAREA. We may not need to bother with this as Jazz may handle this automatically as it does here, but later we’ll see examples where COMMAREA needs to be used explicitly.

Automatic processing – at start

We started our program with

            PROGRAM MENU1 CICS INSCREEN(MENU1S) COMMAREA(MENU1C) TRANSID(MNU1);

INSCREEN means that when this program initiated it expects an input screen, described by the layout (“Map” in CICS) MENU1S. Jazz therefore automatically creates logic to read this screen. However what if the screen hasn’t been sent?  This will be the case if program MENU1 was initiated from an empty screen with just a CICS transaction code? The program therefore tests that there is something in the screen, sending a blank MENU1S screen to itself if there is not. It also sends this blank screen if the user clicks the PF3 button. In effect our program starts with

IF EIBCALEN = 0 THEN

    SEND MENU1S ERASE;

END IF;

 

However this is not visible in our Jazz program (we’d have to look at the generated COBOL). If the logic gets past this initial test then the program will read the screen.

 

All this is automatically generated into your program because you included INSCREEN(…) in your PROGRAM statement, so you don’t need to worry about it. From the first statement that you write you can assume that there is some data in the INSCREEN record.  Of course this doesn’t mean that every field in this record has data, or that the data is valid.

Default processing of AID keys

Another thing that we might need to think about: what if the user doesn’t click [Enter].  Normally we’d expect them to enter some data into the screen and click [Enter], but they may click a function key:  PF1 to F12 or Clear.  Keys other than [Enter] are called “AID” keys, and you may want your program to do something special if they’re clicked.  If you don’t think about this Jazz will provide defaults: -

            PF3 = “Return”.  The initial screen will be redisplayed as if you hadn’t clicked Enter

            PF12 = “Exit”.  The program will be terminated, either back to a clear screen or to the CICS program that invoked this one.

            Clear.  The screen will be cleared except for a message “Enter transaction code” and you can start again.

When relevant, Jazz will also provide defaults for PF7 (up), PF8 (down), PF10(Previous), and PF11(Next).

 

Other Aid keys will cause a response: -

            “Invalid Key Pressed”

and the user can try again.

 

If you want to provide particular handling for an AID key you simply write a HANDLE statement.  For example

HANDLE PF4 PF5;

            MENU1S.ERROR = 'PF4 or 5 clicked';

            SEND SCREEN MENU1S ALARM;

HANDLE ENTRY;

            Write your normal logic here

Automatic processing – at end

At the logical end of our program Jazz generates appropriate logic to terminate the program and return control back to CICS. Our program will almost always terminate through its “Normal Exit”, and probably do something like sending a message back to the user. However every time that a Jazz program uses a CICS command or an I/O command it will check to see that everything worked normally.  If an error has occurred the program will exit through its “Abnormal Exit” where messages will be displayed before the program terminates.

 

Situations like: record can’t be found, input data is not valid, and so on are routine and will be handled by logic such as IF CUSTF.$Found THEN … and within the logic handled by ACCEPT statements.  These are not “Abnormal Errors”, and the program exits normally.

 

The logic that we write will be between these two automatic parts. We will write logic to handle the normal return from the screen – when the user enters some data into the screen and clicks Enter – but we’ll also want to deal with various other situations also such as dealing with keys other than [Enter]. Typical CICS logic therefore tests for a number of response situations.

Testing our CICS Program

With a batch program Jazz could generate the necessary JCL (Job Control Language) for the GO step and so when we submitted our job it just ran, producing the report or output file or whatever it was supposed to do.  With a CICS program there is still slightly more that we need to do before we can try out our program.  The first time that you do this you may need a little help from your system programmer as your local rules may be a little different to mine.  However the general principles will be the same.

 

Firstly, you need to know how to start, use, and stop your CICS system.  Your system may be different, but for me: -

·         To start CICS I log into zOS/TSO.  I go to ISPF option SD, enter command /S CICSTS51,START=INITIAL    This will respond with “NO RESPONSE RECEIVED” but if I check with the ST command I see that task CICSTS51 is running.

·         To use CICS I start another zOS TN3270 emulator session and select “CICS”.   A splash screen is displayed, I clear this, and I can then enter CICS commands (transaction codes) like CEMT, CEDA, etc, plus any transaction codes that I’ve defined for my application.  Initially of course there are only the CICS commands.

·         To stop CICS, from the CICS session enter transaction CEMT P SHUT,IMM 

 

So far our program MENU1 and its screen MENU1S have been compiled into our CICSLOAD library.  For me this is IBMUSER.MANAJAZZ.CICSLOAD.  To start using them with CICS we must define them to CICS.  We do this with CICS command CEDA. I entered these CEDA commands: -

 

·         DEF PROGRAM(MENU1) GROUP(MANAJAZZ)

·         DEF MAPSET(MENU1S) GROUP(MANAJAZZ)  

·         DEF TRANS(MNU1) PROGRAM(MENU1) GROUP(MANAJAZZ)

·         DEF LIBRARY(MANAJAZZ) DSNAME(IBMUSER.MANAJAZZ.LOADCICS) GROUP(MANAJAZZ) 

·         INSTALL GROUP(MANAJAZZ)

 

If the program or layout (mapset) has already been defined to CICS for this group then you’ll get error messages from the CEDA step.  See Re-Testing our CICS Program below.

 

CEDA operands can be abbreviated: DEF is short for “DEFINE” and “TRANS” is short for “TRANSACTION”.  You only need to write enough of the operand to make it unique: I could have written “GR” for “GROUP”, “MA” for “MAPSET”, “PROG” for “PROGRAM”, “LIB” for “LIBRARY”, and “I” for “INSTALL”.

 

CICS Objects are defined in groups.  The name is arbitrary: I suggest that you use as group name the name defined in your Jazz Configuration: -

 

You should put related objects into the same group.  In my tests I’ve put everything into group “MANAJAZZ” which is defined by its first occurrence:  DEF PROGRAM(MENU1) GROUP(MANAJAZZ) first defines the group, then defines the program into it.  Note that as well as naming the group “MANAJAZZ” we can also use this name for other objects within the group: for example here the library is also called “MANAJAZZ”.  We’ll see other examples later.

 

Finally the group is installed: this makes everything defined into it available to CICS.  We can now clear the screen, enter the transaction code “MNU1” and our program displays its screen:

 

We can respond to a screen by entering data – in this case choosing option 1, 2, or 3 – and clicking [Enter], or we can respond by clicking one of the function keys like PF3, CLEAR, etc.   Jazz default logic will handle any of the function keys.  Click here to learn about this default handling, and how to override it if you need to.

 

IF we enter an invalid value like 4 or X then there will be an error message and the program will wait for a correct value.

 

Since we haven’t yet written any of the programs, if we enter 1, 2, or 3 our program will attempt to call them and fail, causing program Menu1 to trap the error and respond with an error screen. 

 

Just in case you’re interested, here is the COBOL program generated by Jazz for this menu function, and here is the code to create the 3270 screen.  Fortunately you’ll rarely, if ever, need to work at this level of detail.

Re-Testing our CICS Program

If you’re like me, as soon as you start testing your program you’ll want to change it.  Perhaps it doesn’t run at all and there are errors to be corrected.  Or you see some minor changes – a spelling mistake in the screen text, for example. With a batch program you simply re-compile and re-run the program, but with CICS programs you have to tell the CICS system that there is a new copy of the program or screen. We do this with the CICS command

            CEMT SET PROGRAM(name) NEWCOPY

where “name” is the name of the program that you’ve just changed. 

 

The same applies to the MAPSET: if you change the screen enter (for example)

            CEMT SET PROGRAM(CICS1S) NEWCOPY

Note that the command is “SET PROGRAM”, not “SET MAPSET”.

Writing an On-line Enquiry Program

Our next program is about as simple as an enquiry program can be.  We want to display a screen that asks which record we want to see, then responds by displaying that record. So we could write a program that asks for an account number: -

 

But will the user know the account number?  Perhaps they only know the customer’s name.  We can hardly send the customer away to find out their account number before we can tell them whether there’s any money in their account!  We want to write the program so that we can look up the record by EITHER the account number or their name.  This is easy if we’ve defined alternate indexes with our file.

Alternate Indexes:  DKEY and UKEY

To provide lookup by either account or name is very easy.  We do this by defining an alternate index in the record definition with the DKEY or UKEY property: -

DEFINE CustF TYPE(VSAM) DATA( 

    Account PIC '999999' HEADING 'Account Number' KEY,

    Subgroup GROUP,        

        Region DECIMAL(3),       

        District DECIMAL(3),

        END GROUP,   

    Name CHAR(15) REQUIRED DKEY 'ibmuser.vsam.custf1',

    SalesThisMonth MONEY(7,2),   

    SalesYTD MONEY(7,2),         

    Billingcycle LIKE types.month,

    DateCommenced CHAR(10))

    DSNAME 'ibmuser.vsam.custf';

 

DKEY means “Duplicate key”, meaning that there might be several records with the same value of Custf.Name.   UKEY is less common: it means “Unique Key” and would be used for fields like Social Security Number that are unique, but are not the record’s primary key.  There would not be two customers with the same Social Security Number, and an attempt to create a second record with a value already used would raise an error.  With a VSAM record DKEY and UKEY specify an alternate index, so we must use IDCAMS to create the index and path: -

//IBMUSERL JOB  ,CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID,COND=(8,LT)

//*** THIS JOB IS FOR MANAGEMENT OF VSAM FILES. 

//    SET MEMBER=DTREGN 

//    SET SOURCE=IBMUSER.MANAJAZZ.SRCLIB 

//*      

//STEP1    EXEC PGM=IDCAMS

//DATAIN   DD DSN=&SOURCE(&MEMBER),DISP=SHR 

//VSAMOUT  DD DSN=IBMUSER.VSAM.CUSTF,DISP=SHR

//SYSPRINT DD SYSOUT=*   

//SYSIN    DD * 

  DELETE IBMUSER.VSAM.CUSTF1 

  DELETE IBMUSER.VSAM.CUSTF1.AIX

  DEFINE AIX (NAME(IBMUSER.VSAM.CUSTF1.AIX) -

              RELATE(IBMUSER.VSAM.CUSTF) -

              TRACK(10 10) VOLUMES(VPWRKA) KEYS(15 10) -

              NONUNIQUEKEY UPGRADE REUSE)

  DEFINE PATH (NAME(IBMUSER.VSAM.CUSTF1) -

               PATHENTRY(IBMUSER.VSAM.CUSTF1.AIX) UPDATE)

  BLDINDEX INDATASET(IBMUSER.VSAM.CUSTF) -

           OUTDATASET(IBMUSER.VSAM.CUSTF1.AIX)

/*

(NB: DATAIN is not used in this job)

 

Note that with DKEY and UKEY options you may give the path name: here we’ve written DKEY 'ibmuser.vsam.custf1' and in a batch program there’d be a DD statement for the path, //CUSTF DD DSN=IBMUSER.VSAM.CUSTF1,DISP=SHR.  If we omit this then Jazz will find the file name “custf” at the end of the DSNAME option and append 1, 2, 3, etc to it as it finds each alternate index option in the definition.  Making the path name explicit is recommended.

Generic keys and Wildcard characters

One more thing before we go ahead and re-generate program CICS1.  The program will now look up CustF by either Account or Name.  Here are the first few records of our test database, sorted by Name: -

Account Number Region District *----Name-----* Billingcycle 

        000014      6        8 ABRAHAM,Abram      March     

        000015      6        7 AGNUS,Agnes        August    

        000016      6        3 AGNUS,Agnes        December  

        000017      8        2 AKELANE,Robert     January   

        000018     11        2 ALFRED,Albert      August    

        000019     11       10 ALGIRDASOF,Olgi    November  

        000020      2        2 ANDREW,Andrs      June      

        000025      5       10 APTHORPE,Alice     December  

        000023      8        5 APTHORPE,Benjam    March     

        000021      7        8 APTHORPE,John      April     

        000028      3        6 APTHORPE,Joseph    ********* 

        000024     10        4 APTHORPE,Robert    March     

        000022      5        7 APTHORPE,Thomas    August    

        000026      2        2 APTHORPE,WILLIA    April     

        000027     11        7 APTHORPE,WILLIA    August    

        000029      7        4 ARNAULT,Arnould    June      

        000030      3        8 ARVO,Arvi          June      

        000034      6        3 ATKINSON,Arnold    January   

        000033      3        1 ATKINSON,Bertra    ********* 

        000035      5        1 ATKINSON,Joseph    July      

        000032      6       10 ATKINSON,Kathle    January   

        000031      4        4 ATKINSON,Regina    January   

        000051      7        4 AXCELL,AlfredEd    September 

 

We probably don’t want to have to enter “APTHORPE,Alice ” to read the first “APTHORPE” record, and our Jazz program doesn’t require us to.  Instead, when the search field has format CHAR then Jazz assumes that we want to treat our input value as a generic key: we enter “Apthorpe” and the program returns the record with account = 25, and name of “APTHORPE,Alice  ”.  This is the default: we don’t need to do anything special to make this happen, and this default applies to any key with CHAR format including the primary key, not just to keys defined with DKEY or UKEY.  However it doesn’t apply to Custf.Account as this has format PIC ‘999999’, not CHAR.

 

If we want something different then we can add FULL or WILDCARD “character” to the properties of NAME in its data definition,

            Name CHAR(15) REQUIRED DKEY 'ibmuser.vsam.custf1' WILDCARD '*',

or as an option of the KEY value within the GET statement

GET Custf KEY(Custf.name FULL);   

 

FULL means that the full key length will be used: now we would be looking for a value “Apthorpebbbbbbb”  (“b” represents a blank character), and without entering the exact name value we wouldn’t find any records.  WILDCARD functions like GENERIC but requires the user to enter the special character ('*' in this example) to denote the end of the search string.

 

As before we may as well start by getting Jazz to generate our program for us. We start by clicking [New], then selecting New CICS Program, as we did with Menu1: -

 

The most important differences from Menu1:  we’ve selected program type 1 Table Enquiry, and given the table name.  I’ve given a TRANSID value which will allow this program to be initiated directly as well as from Menu1, and I’ve set up the exit to go back to Menu1 anticipating that this is the way it will normally be used. Click [Finish] and Jazz will create our program and screen for us! 

 

Here is the screen that Jazz generated for us.  Name has been moved from the list of general display fields to the search field area: -

 

 

Jazz has sent this off to be compiled on the zOS system.  Of course we may want to change the default screen, in which case we’ll edit it an re-process it.  And of course we may want to change our program logic, but at least what Jazz has generated for us is a start, and it may even be what we want.  Here is the program logic that Jazz generated: -

*# Last Updated by  at 17/06/2015 2:15:39 p.m.

PROGRAM CICS1 CICS INSCREEN(CICS1S) TRANSID(TRN1) COMMAREA(CICS1C) EXIT(Menu1);

COPY Custf;

ACCEPT (CICS1S.Account OR CICS1S.Name);

DEFINE TS1 TYPE(TS) DATA(

    Account LIKE CustF.Account);

GET Custf KEY(CustF.Account OR CustF.Name) TS(1);

    #373 I GET statement returns one record at a time for Name

END GET CustF;

IF Custf.$Found = 'N' THEN;

    CICS1S.error = 'No Record Found';

END IF;

SEND Inscreen;

 

There are a few features of this program that need comment.

1.         Here, instead of separating the two fields with a comma we’ve used OR indicating that they are alternatives. If we’d written

ACCEPT (CICS2S.Account, Cics2S.name);

then the ACCEPT’s validation logic would have required a value to be given for both fields.  Because we’ve used OR then if a value is given for CICS2S.Account any value given for Cics2S.name will be ignored.

 

Similarly

GET Custf KEY(Custf.Account OR Custf.Name);

first checks to see if there’s a value in Custf.Account that is not the default (zero). If there is then it looks up Custf by Custf.Account.  If not then it tests to see if there is a value for Custf.Name and uses that.  There must be one or other value or else the ACCEPT statement would have reported an error.

 

NOTE THE IMPLICATION: you cannot have a record whose key value (primary KEY, DKEY, or UKEY) is its default value.  Thus if you have defined your record layout as

DEFINE CustF TYPE(VSAM) DATA( 

    Account PIC '999999' HEADING 'Account Number' KEY VALUE 1234,

then there could not be a record with Account = 1234, and you could use a test

            IF CustF.Account = 1234 THEN;

to distinguish whether this were a real record or not.  Of course the normal default value is zero, meaning that if you’d omitted the VALUE property then you would not be able to create or access a record with CustF.Account = 0.

Handling Multiple Records

So far so good: but what about the fact that GET Custf KEY(Custf.Name); might return several records?  For example, searching for “Apthorpe” there are 8 possible records.  GET can only return one at a time, and will return the first, but what about the other seven?  Again, Jazz handles this completely automatically.

 

On recognizing a multi-record situation Jazz adds to our program: -

1.            A definition of a Temporary Storage file: -

DEFINE TS1 TYPE(TS) DATA(

    Account LIKE CustF.Account);

2.         An option TS(1) is added to the GET statement, making it

GET custf KEY(CustF.Account OR CustF.Name) TS(1);

 

Jazz generates logic that, when a name value is entered and [Enter] clicked, reads the set of qualifying records (there are 8 for “Apthorpe”) and stores their primary key values in TS1.  The first record is returned and (if there are more) PF11 (=Next) is enabled.  The user can then move forwards and backwards through the list of eight records with PF11 and PF10.  Here we’ve clicked “PF11 twice to be looking at the 3rd record: -

 

Once again, for your interest here is the COBOL program and the screen layout.

 

Next:  Complex Enquiries and Updating Files

In this topic we’ve introduced the basic principles of on line programming, showing you how to write a simple enquiry program. The next two topics build on the knowledge that you’ve gained here, showing you how to write update programs, and how to write more complex enquiries and updates in which you bring together families of records such as a customer record, and a list of that customer’s current orders.  If you are interested in writing web service programs and you’re not intending to write “classical CICS” programs using 3270-type screens you can probably skip these chapters and go straight to the chapter on Service Oriented Architecture.

 

Once again, for your interest here is the COBOL program and the screen layout.

One other thing – Displaying and Entering Coded Fields

 

Notice the way that BillingCycle is displayed: -

 

In CustF BillingCycle is defined: -

    Billingcycle LIKE types.month,

 

LIKE types.month means that its definition is the same as types.month, which is defined: -

DEFINE Types TYPE(SYSTEM) DATA(

    Month CODES(January,February,March,April,May,June,July,August,September,October,November,December));

 

Coded fields are not unique to on-line programming, but they are particularly useful as they provide concise record layouts (in this case, requiring only a TINYINT variable which is a single byte), specify validation rules (must have a value from 1 to 12), specify a display format (one of the values “January” etc), and by defining a distinct data type they reduce our opportunity for programming errors.

 

When the field is displayed its value is converted to the display value “January” etc.  We enter the value as 1 to 12.

 

 

Testing our 2nd CICS Program

As earlier, before we can test our program we must add it to our CICS application group with CICS command CEDA.  As well as the program, mapset, and transaction, this is the first time that we have used the CUSTF file so this must also be defined.  We don’t need to repeat the LIBRARY definition.

 

·         DEF PROGRAM(CICS1) GROUP(MANAJAZZ)

·         DEF MAPSET(CICS1S) GROUP(MANAJAZZ)  

·         DEF TRANS(TRN1) PROGRAM(CICS1) GROUP(MANAJAZZ)

·         DEF FILE(CUSTF) GROUP(MANAJAZZ) DSNAME(IBMUSER.VSAM.CUSTF)

 

These are added to the previous definitions, so that when we execute

·         INSTALL GROUP(MANAJAZZ)

the whole group, programs MENU1 and CICS1 and all their associated objects, is installed.

 

We do this, then we either

Enter transaction MNU1 to display the menu, and select 1, or

Enter transaction TRN1

 

If we change the program then we need to execute

            CEMT SET PROGRAM(CICS1) NEWCOPY

and if we change the screen

            CEMT SET PROGRAM(CICS1S) NEWCOPY