Crossing CICS BRIDGES, Part II
In the conclusion of this two-part article, Carol Shanesy explores Receive and Send Commands, Mapping Inputs, ADS, Critical Restrictions, and Intercepts and Syncpoints.
This past month in Crossing CICS BRIDGES, Part 1Carol Shanesy covered CICS TS 1.2, Bridge Transactions and Execution Environments. This month in Part 2, she explores Receive and Send Commands, Mapping Inputs, ADS, critical restrictions and Intercepts and Syncpoints.
RECEIVES: On RECEIVE commands, the exit must provide the input that would ordinarily come from the 3270 terminal that invoked the transaction. You do this by providing the address and length of the input, the cursor position and the attention identifier in the BRXA.
If the input was included in information obtained during the initialization invocation of the exit, most of the work is already done. You need only point to it in the user area of the BRXA. If not, however, you can get it at this time, and you can use all the commands and resources available to an ordinary transaction for this purpose. If the new source(s) provide data in a different order or segmentation than the user transaction expects - if two RECEIVEs are used for what is arriving as one item, for example, or vice-versa, you can save information in the user area between RECEIVEs, or collect information from several sources for a single RECEIVE.
You may need to format input from new sources to put it in the sequence the old transaction expects. For terminal control RECEIVE commands, you also need to prefix the data with the three-byte "read header" (the attention identifier and the cursor position) if the application looks at it (most applications get this information from the EIB, and you need only a three-byte spacer). If the transaction issues READ BUFFER commands (very unusual), then you need to present the input in the form of an image of the 3270 screen.
MAPPED INPUT: These situations are essentially the only cases where you deal with even limited 3270 control information. For the more common case of a RECEIVE MAP command, all you need to do is to put the input data directly into the format described by the symbolic map, that is, into the form the application sees after BMS has removed the 3270 device dependencies. You can do this in either of two ways. You can copy the symbolic map into the bridge exit program in the same way that the user application programs have done, refer to the individual fields in the map by name and write map-specific code. If your exit handles a small number of maps or only a specific application, this is probably the logical choice. Input to the exit on a RECEIVE MAP intercept includes the MAP and MAPSET names, so that your program logic can select among the maps if it handles more than one.
Alternatively, you can use the ADS descriptor. ADS means "application data structure" and is the new term for the symbolic map or DSECT. You can write general code to parse this simple structure and map the input accordingly if you are writing a more general-use exit. The descriptor is included automatically in the physical map if you assemble the mapset under Version 1.2, and is loaded and located for you if you have turned on a flag in the BRXA.
You may also want to audit the input during this invocation of the exit, to reduce the possibility of going through an error cycle in the program, where the user program detects an input error and sends a message back to the terminal asking for a correction.
SEND COMMANDS: Four types of SEND commands are supported by the bridge: terminal control SEND, and BMS SEND MAP, SEND TEXT and SEND CONTROL.
On all of them, the bridge allows you to collect output(s) from the user transaction. You can deliver them to some destination - perhaps an MQ queue or the Web - and you can process them in any way you wish first. You might extract some fields and ignore others, re-arrange the information or otherwise reformat it. You may also want to combine the output from several SENDs and deliver it as a single item, and/or defer delivery until the end of the transaction; if so, you can use the user sub-area of the BRXA to aggregate output. As in the case of RECEIVE commands, you may want to audit the contents, to avoid sending bad data to an application downstream. For example, you may need to ensure that the output is true output and not an error message from the application complaining about your input.
Note that there is no CICS requirement to do anything with the output at all. Some SEND commands do not even provide it (SEND CONTROL FREEKB, for example), and the appropriate exit action may be simply to set normal response codes and return.
On SEND MAP commands, the output is presented in ADS format (that is, as defined by the logical map), and you get the MAP and MAPSET name. Here again you have two choices for extracting the data you want. You can include the logical map in your bridge exit and write map-specific code or you can parse the output using the ADS descriptor.
In addition to the key information - the location and length of the output data, map and mapset names - the bridge exit gets most of the other information that the application provides on the SEND command: The options that apply to the command (ERASE, LAST, WAIT, definite response, INVITE, structured fields, etc.), plus the cursor position, write control character, magnetic stripe reader data, etc.
OTHER INTERCEPTS: Three other terminal control commands are intercepted. On a CONVERSE, the exit does SEND processing followed immediately by RECEIVE processing. ISSUE DISCONNECT and FREE might be treated as "no-ops" in the bridge exit, since there is nothing real to free or disconnect, or they might signal the exit to dispose of any transaction output it is holding. ISSUE ERASEAUP (erase all updated fields) might be noted as information to be saved for the next input cycle, or it might simply be ignored.
SYNCPOINTS: The bridge exit is invoked whenever the user transaction issues an explicit SYNCPOINT or SYNCPOINT ROLLBACK command, and also before an implicit SYNCPOINT, such as occurs on a DL/I TERM call or a CREATE command. These invocations allow the bridge exit to ensure that updates to recoverable resources done by the exit are synchronized with those done by the user transaction. On an explicit commit request, the exit can do almost anything: Issue the command in the form received, change the ROLLBACK indication, or ignore it entirely, and it can update recoverable resources before or after, or both.
You might, for example, deliver output accumulated from SEND commands before issuing the SYNCPOINT. On implicit commits, the exit cannot change the command, but it update recoverable resources (for example, deliver output), so that the changes are included in the unit of work about to be committed.
RETRIEVE COMMANDS: Some 3270 transactions are initiated by a START command rather than unsolicited terminal input and get their initial input with a RETRIEVE command rather than a RECEIVE. Consequently, CICS intercepts RETRIEVE as well as RECEIVE commands in the bridge environment. The exit gets and provides the same type of information that it does on a RECEIVE.
TASK TERMINATION: The final invocation of the bridge exit occurs at task termination. On this call, the exit must specify the keep time for the bridge facility. Normally, you keep a terminal if there are subsequent transactions in a pseudo-conversational sequence and discard it otherwise. You specify a time limit, so that idle terminals don't accumulate over lunch breaks.
CICS provides a token to identify the terminal. You need to save it if transactions in the sequence save state data in the TCTUA or COMMAREA, or are otherwise sensitive to the name of the terminal. Otherwise, the bridge exit cannot identify its data from other instances of the same pseudo-conversational sequence. You might include the token with the other task output, and require whatever process is invoking a transaction under the bridge and pass it back when it invokes the next leg of the sequence. An alternative is to save it in temporary storage or a file under some identifier that you can determine from information available at the start of the next transaction. You may need to save the NEXTTRANSID with it, if it is not implied in the same data, because you need it in the initialization call, before you have access to the kept bridge facility where it is stored.
You also need to do any clean-up associated with your particular implementation of the bridge. For example, if you are discarding the bridge facility, you may need to capture the contents of the TCTUA first, or, if you are keeping it, you may want to save information there. In addition, there may be task output that has not yet been delivered, messages to be written, etc. You can still update recoverable resources at this point, because the implicit SYNCPOINT at end of task has not occurred yet. However, you are not allowed to issue an explicit SYNCPOINT in this invocation.
If the task ends abnormally, the bridge invocation is slightly different, in that you cannot update recoverable resources (non-recoverable ones are okay). CICS passes the abend code, so that you can determine what happened and take appropriate action. You might, for example, want to send a message to an external application. You can even change the abend code, but you cannot prevent the abend; the exit cannot act as an abend handler.
Changes to CICS Externals
The bridge feature has introduced some changes to CICS externals. They are all additions, however; existing programs should execute unchanged. The only change to the API is a new option on the ASSIGN command which lets a program determine whether it is running under the bridge or not and, if it is, the name of the bridge transaction. There are new options on the TRANSACTION and PROFILE resource definitions, and similar options on the corresponding INQUIRE and SET commands in the SPI and XPI commands. There is one new XPI command as well, INQUIRE CONTEXT, which returns the bridge exit program name, bridge facility name, bridge transaction identifier, bridge exit area (BRXA) address and a "context" value that indicates whether the task is running under the bridge or not, and if it is, whether it is currently in the bridge exit or the 3270 transaction code.
The macros that define BMS mapsets have been modified to produce ADS descriptors in load modules assembled under CICS TS 1.2, and a utility for recreating BMS macro source from mapset load modules is now available, in case the mapset source has been lost.
There is also one additional global user exit. When enabled, XFAINTU is invoked just after CICS has created a new bridge facility and again just before a bridge facility is discarded. You might use the invocation at create time to populate the TCTUA and the invocation at discard to extract information from it, for example.
ADS DESCRIPTOR: The DFHMDx macros with which you assemble BMS mapsets have been changed in CICS TS 1.2 to produce an "ADS descriptor" for each map in the mapset. The descriptors for the maps are included in the mapset load module, and CICS will load and locate them for the exit turns on a flag in the BRXA.
A descriptor provides the same information as the symbolic map (DSECT, ADS). However, you interpret the information at execution time rather than hard-coding field names into your source code. This has several implications:
Your program has to parse the structure, which requires more code and logic than referring to named fields directly. Nonetheless, the structure is simple, and once you have written the code (or lifted it from the CICS-supplied sample), you can use it over and over again.
You do not need to include copybooks for symbolic mapsets in your source code. In a bridge exit, for example, this means that you can write your code to handle a number of maps, or whole classes of maps, by defining a simple set of rules for the inputs and outputs which you are going to pass to the 3270 transactions. To take the simplest example, you might require that applications using an exit send and receive input in a stream that consists of the map fields in order of appearance, using some suitable fixed length each. Or you might require two fields each, length and data, in order. Or triples of field name, content and length, in any order.
You do not need to recompile a bridge exit to handle additional maps, provided they are used in the way your exit supports.
The descriptor for a map has two parts. There is a header, followed by a field descriptor for each named field in the map. (You only need to know about named fields to communicate with a program that uses a 3270 interface, because the symbolic map it uses contains only named fields.) The header contains essentially the information that you supply in the DFHMDI map definition macro, plus some additional information to help you parse the fields.
The field descriptors contain the name, offset within the map, length, justification, fill character and occurrence number (if they have an OCCURS clause).
There are some restrictions in the initial version of the bridge. Perhaps the most important one is that a transaction running under the bridge cannot issue a START to its own terminal. This practice is not unusual in "menu" transactions, where the initial end-user input is simply a selection from a list of functions. The transaction handling this initial selection issues a START to a second transaction, specifying its own terminal as principal facility and passing the terminal input as "start" data. The usual purpose of the switch is to execute the real business logic under its own transaction identifier, to provide granularity for performance tuning, statistics, security, billing, etc.
This restriction stems from the fact that a transaction running under the bridge cannot have a principal facility. We mentioned earlier that bridge transactions are non-terminal transactions, from the point of view of CICS and other transactions executing at the same time, even though the legacy code is convinced that it has a principal facility. However, since the bridge facility is not a real terminal outside its owner's world, no one, including the owner, can START a transaction with it as principle facility.
This is not as serious a restriction as it might look at first. Menu transactions tend to be fairly simple, and the only real change required is in the START command itself. This can be changed to any command that the bridge intercepts and that passes data (a SEND, perhaps), so that the bridge exit can issue the START itself. This replacement START will be to a bridge transaction identifier associated with the second transaction and can pass not only the START data for the transaction, but the token and any other details it wants.
Alternatively, you can simply remove the terminal from the START and change the target transaction to the associated bridge transaction. In this case, however, if the second transaction needs to know the token value (i.e., needs the same bridge facility), you will have to add it to the START data or pass it some other way.
Still another possibility is to absorb the menu logic into the bridge exit or move it to the external process that is using the legacy application. This may occur naturally as part of the redesign, so that the selection from the menu comes bundled with the input to the function chosen, allowing the exit to skip the menu entirely and go straight to the business function.
An alternative to START for changing from one transaction identifier to another is RETURN IMMEDIATE INPUTMSG. Here CICS attaches a new task at the same terminal without leaving bracket state; the new task thinks it has been started by unsolicited terminal input, and gets the data passed in INPUTMSG with a standard RECEIVE. In the bridge environment, this technique suffers the same complication as START: There isn't any terminal, and hence no associated input message. The RETURN works, but the INPUTMSG data is ignored.
Some other restrictions related to the non-terminal environment: There are no terminal statistics for a transaction running under the bridge and there is no PSB security check on remote DL/I requests.
Finally, because the bridge facility is not a real terminal, the VTAM and TCAM global user exits associated with these access methods are not invoked in the bridge environment. These are the GLUEs invoked at task attach, after an input event, before an output event, and, for VTAM, before a message is broken into RUs.
The fact that a transaction running under the bridge cannot have a principal facility also means that another system cannot start such a transaction via an LU6.1 or APPC ATTACH, because the link session becomes the principal facility in this case. You have to invoke another, non-bridge transaction in this situation, and let it initiate the bridge transaction by a START. On the other hand, a bridge transaction can have an alternate facility, so a bridge transaction can hold a synchronous conversation with another system, so long as the bridge transaction initiates the conversation.
Another restriction is that not all terminal control and BMS commands are supported in a bridge environment. The only omissions that may affect a significant number of applications are the features in full-function BMS that allow you to build a screen from multiple maps (the ACCUM option) and build a set of pages in temporary storage for subsequent display at the terminal (PAGING). Routing is allowed, provided your own terminal (that is, the bridge facility) is not included in the routing list or as the error terminal, and you can use PAGING and ACCUM in the context of such a ROUTE.
There are a few restrictions relative to task-related user exits as well. You should not use a TRUE that is enabled for task start (i.e., a TRUE invoked by CICS on every task start) in the initialization invocation of the bridge exit. The reason is that this invocation occurs before the task-start invocation of the TRUE, so that you are invoking the TRUE before it has initialized for your task, and you are almost certain to confuse it. MQ is an exception to this restriction; the MQ TRUE can cope with this possibility. In addition the exit generally should not use a TRUE also used by the user transaction, such as DB2 or DBCTL, as the exit calls may affect those in the existing code. It may work in some cases, but you should exercise caution if you do it. Finally, the true will not see terminal information for a transaction running under the bridge, as it would for a real 3270.
A few more: The bridge transaction and the 3270 transaction must be defined as local to the same CICS. That is, the bridge exit cannot execute remotely from the 3270 transaction. It also cannot issue SIGNON and SIGNOFF commands, although, as noted, it can specify a user and/or password for CICS to verify. Bridge transactions cannot specify RESTART either. Finally, certain CICS-supplied transactions cannot execute as bridge transactions: CEDF, CEDX, CSFE, CSGM.
To summarize briefly, the bridge offers you a powerful new tool for extending the lifetime of 3270-interface transactions. It allows you to use the business logic in large bodies of existing code in new combinations, from new platforms, with new user interfaces. You do not need to modify the old code and you can use it in the original 3270 form at the same time as the new mode.
There are few restrictions on how you build your interface to the new source of input and output, and yet the bridge overhead is relatively low, probably comparable to the legacy code running with 3270s. Moreover, the structure of your application remains the same with respect to recovery: You work within the same unit-of-work boundaries as the legacy code, with the flexibility of extending the unit-of-work to new resources. The coding required is modest and requires the same skills as ordinary CICS application code.
ABOUT THE AUTHOR:
Carol Shanesy is on the CICS/390 team in the IBM Dallas Systems Center and has worked with CICS from macro days to Parallel Sysplex. She and can be reached at (914) 766-4488 or firstname.lastname@example.org.