Contents
CALL and INVOKE both pass control [and parameters] to another, separately compiled object, so they are similar but they are not the same: -
· CALL passes control to a subprogram which is written separately but linked into the same executable program as the object containing the CALL. CALL may be used in either Batch or CICS programs. Control will return to the statement following CALL unless there’s a program error (Abnormal termination, or “Abend”).
· INVOKE is only valid in CICS programs and web services, and the “call” is managed by CICS. The invoked object may be another CICS program, including a CICS program within another CICS system, or it may be a web service. Program execution may be terminated after INVOKE has passed control.
To pass control and parameter[s] to another CICS or Web Service task.
INVOKE CICSName
[(parameter)] [TRANSFER | ABENDIF(condition)];
CICS-name follows the rules for external names, i.e. it must be eight characters or less, and may not contain a hyphen. There may be a single parameter, typically a COMMAREA definition. Like CALL, for INVOKE to be used there must be a definition of the program’s interface, typically provided with COPY. For example
COPY CICS1C;
INVOKE
CICS1(CICS1C);
In this example COPY CICS1C; causes the following interface
definition to be used: -
COPY CICS1C;
DEFINE CICS1 PARAMETERS CICS DATA(CICS1C UNSPECIFIED);
CICS1C can be almost any COMMAREA
definition, provided that it includes a field named JZ-XCTL, defined as
shown. The field does not have to be the
last or only field in the COMMAREA, but it
must be present if you are invoking a program generated by MANASYS.
DEFINE CICS1C COMMAREA DATA(
JZ-XCTL CHAR(1) BOOLEAN);
The reason
for this is that before INVOKE passes control the generated COBOL executes
a MOVE to JZ-XCTL like #3030: -
003020* INVOKE CICS1(CICS1C); CICSXX
003030 MOVE 'Y' TO JZ-XCTL OF CICS1C. CICSXX
003040 EXEC CICS
CICSXX
003050 LINK PROGRAM ('CICS1') COMMAREA(CICS1C) RESP(JZ-RESPONSE)CICSXX
003060 END-EXEC.
CICSXX
This allows
the invoked program to recognize that it has been passed a COMMAREA, but no input screen.
If TRANSFER is specified the current program is
terminated. Execution continues with the
invoked program, and will not return to the called program, but will return to the
current program’s return point.
INVOKE Service-Name (Input message)] [REPLY(Output message)] [ABENDIF(condition)];
For example,
COPY MyJSv-JSPG1;
INVOKE MyJSv-JSPG1(IJSPG1.*) REPLY(OJSPG1.*);
The service-name is
hyphenated, dividing it into two parts: -
1.
The
first part (MyJSv in this case) is a shorthand label
for the URL, assigned when the web service was defined.
2.
There
may be several programs (in some context, called “operations”) at this URL, so
the second part names the program that you are invoking, in this case
JSPG1.
3.
The COPY book MyJSv-JSPG1 will contain three definitions: -
a.
DEFINE MyJSv-JSPG1 SYSTEM DATA(…); gives some information about this service
and program.
b.
DEFINE IJSPG1 WEBSERVICE DATA(…); describes
the input message passed to the program
c.
DEFINE OJSPG1 WEBSERVICE DATA(…); describes the
output message returned from the program.
d.
There
must be no DEFINE statements
between these definitions, although they can appear before DEFINE MyJSv-JSPG1 or after OJSPG1.
Web services are
invoked with an input message, and normally return an output message. Even when the format of the output data is
the same as the input these are separate records in your program, and you do
not have INOUT parameters.
Normally you write INVOKE …
REPLY, e.g.
INVOKE MyJSv-JSPG1(IJSPG1.*) REPLY(OJSPG1.*);
The program invokes the web service, sending it an input message, and waits. When the response is received the program continues with the statement after INVOKE. If a reply is not received within your system’s default limit (typically 30 seconds), your program will Abend (terminate abnormally).
If REPLY is omitted then the program doesn’t wait for a reply, but continues with the statement following INVOKE. Use this to invoke services that will continue asynchronously and won’t send a response. If a response were sent, you won’t receive it even if your program has not terminated.
All INVOKE
statements require an interface definition, so the INVOKE
statement will be preceded by COPY that causes a definition of the web service
to be included in your program. This is
no problem if you are testing your own web services, but how do you handle web
services created by others? A web
service might be developed by a developer working in another company: you
probably don’t even know what language the service is written with, only it’s
URL and whether it communicates with JSON or WSDL messages. Fortunately, the URL
and message type is often (but not always) sufficient for Jazz to discover the
interface and create the COPY book for you.
Write INVOKE ?; and click [Check]. A dialog
results that gives you a list of the services that you already know about, and
you can choose which you want to invoke.
If a suitable Jazz definition of the interface is already available to
your program, a COPY statement is
inserted and the INVOKE ?; statement is replaced with something like
COPY MyJSv-JSPG1;
INVOKE MyJSv-JSPG1(IJSPG1.*) REPLY(OJSPG1.*);
For new web
services you enter the URL of the service’s description, and Jazz will attempt
to find a description of the web service’s input and output messages, and
create a suitable COPY book
for you. This process is described in Web Service Discovery. You may choose to edit the definition to take
advantage of the descriptive power of Jazz definitions: for example replacing a
simple definition
SEX
CHAR(1),
with
SEX
LIKE MyTypes.SEX,
to use your standard definition
DEFINE MyTypes SYSTEM DATA(
SEX
CHAR(1) CT(M:Male,F:Female),
…
You might also
choose to add ASSIGN properties to the
definition to reduce the need for Assignment statements before and after the INVOKE statement.
This option is not yet available: this section is provided
for discussion. The keyword might be FAILIF.
MANASYS Jazz programs usually terminate through their normal exit, but if they encounter an error from which they can’t recover, for example trying to read from a file that doesn’t exist, or add a decimal number that doesn’t have the correct packed-decimal format, then they “abend”, or terminate abnormally, and exit through their Abend Exit.
CALL and INVOKE statements may return to this program having executed “normally”, but the values returned in their output parameters may indicate an error that should force an abend. For example, you’ve invoked a web service to perform an update but the parameters return indicate that the update failed. If you wish this to immediately terminate your program and force it to abend, you can write
ABENDIF (condition)
If the condition is true, then your program will abort with suitable messages.