# Compaq ACMS for OpenVMS
Writing Server Procedures

Previous | Contents | Index

## 12.1.2 Form Definition

Because of the modularity of the components of ACMS, there are no Oracle-specific issues that relate to the generation of a DECforms form.

DECforms code is typically not hand-generated, but rather is generated by the DECforms Forms Development Environment, an easy-to-use interface for forms generation.

## 12.1.3 Read Database COBOL Step Procedure

The COBOL procedure (VR_GET_SITES_PROC) in Example 12-2, which is a processing step procedure that becomes part of the VR_SERVER procedure server, performs the Oracle database access necessary to return an array of site data back to the task.

Keep the following points in mind when you look at the code example:

- For simplicity's sake, no robust error handling is used (although robust error handling is available with Compaq's ACMS and programming language products).
- Although this example of a server procedure accesses the Oracle database, it is possible to have server procedures that manipulate data only (and do not access that data from a database manager).

Note Although COBOL is used in this example, users can create server procedures using any programming language that supports the OpenVMS Calling Standard and supports Oracle. This holds true for all COBOL examples in this guide. Writing procedures is fully described in Compaq ACMS for OpenVMS Writing Server Procedures.

Table 12-2 describes the coding in the VR_GET_SITES_PROC step procedure in more detail.

Example 12-2 VR_GET_SITES_PROC COBOL Step Procedure

    IDENTIFICATION DIVISION.

    PROGRAM-ID. VR-GET-SITES-PROC.

    ENVIRONMENT DIVISION.

    CONFIGURATION SECTION.
    SOURCE-COMPUTER.        VAX-11.
    OBJECT-COMPUTER.        VAX-11.

    DATA DIVISION.

    WORKING-STORAGE SECTION.

    01 RET-STAT     PIC S9(9) COMP.                                        [SRV1]

    01 RECNOTFND    PIC S9(9) COMP VALUE IS EXTERNAL VR$_SIRECNOTFND.      [SRV2]
    01 DBFATAL      PIC S9(9) COMP VALUE IS EXTERNAL VR$_DB_FATAL.

            EXEC SQL                                                       [SRV3]
                BEGIN DECLARE SECTION
            END-EXEC.

    01 VR_SI_IND_ARRAY.
       05 VR_SI_IND OCCURS 9 TIMES PIC S9(4) COMP.

            EXEC SQL
                END DECLARE SECTION
            END-EXEC.

    01 SI-ARRAY-LIMIT       PIC S9(9) COMP VALUE IS 60.                    [SRV4]

    01 SQL-SUCCESS          PIC S9(9) COMP VALUE IS 0.                     [SRV5]
    01 REC-NOT-FOUND        PIC S9(9) COMP VALUE IS +100.

            EXEC SQL                                                       [SRV6]
                INCLUDE AVERTZ_ORACLE_DIR:SQLCA.CBT
            END-EXEC.

    LINKAGE SECTION.                                                       [SRV7]

            EXEC SQL
                INCLUDE AVERTZ_ORACLE_DIR:VR_SITES_WKSP.LIB
            END-EXEC.

            EXEC SQL
                INCLUDE AVERTZ_ORACLE_DIR:VR_SI_ARRAY_WKSP.LIB
            END-EXEC.

    PROCEDURE DIVISION USING VR_SITES_WKSP, VR_SI_ARRAY_WKSP GIVING RET-STAT.

    MAIN-SECTION.                                                          [SRV8]

            SET RET-STAT TO SUCCESS.

            EXEC SQL
                WHENEVER SQLERROR GOTO SQL-ERROR-HANDLER
            END-EXEC.

            EXEC SQL
                DECLARE SITES_ARRAY CURSOR FOR
                    SELECT * FROM SITES
                        WHERE SITES.CITY = :WS_CITY
                              OR
                              SITES.REGION_ID = :WS_REGION_ID
                        ORDER BY SITES.SITE_NAME ASC
            END-EXEC.

            EXEC SQL
                WHENEVER NOT FOUND GOTO SQL-NOT-FOUND
            END-EXEC.

            EXEC SQL
                OPEN SITES_ARRAY
            END-EXEC.

            EXEC SQL
                WHENEVER NOT FOUND CONTINUE
            END-EXEC.

            SET SI_ARRAY_INDEX TO 1.

            PERFORM FILL-ARRAY THRU FILL-ARRAY-EXIT UNTIL
                (SQLCODE = REC-NOT-FOUND) OR (SI_ARRAY_INDEX > SI-ARRAY-LIMIT).

            EXEC SQL
                CLOSE SITES_ARRAY
            END-EXEC.

            EXEC SQL
                COMMIT
            END-EXEC.

            GO TO EXIT-PROGRAM.

    FILL-ARRAY.

            EXEC SQL
                FETCH SITES_ARRAY INTO :WS_SITE_ID,
                                       :WS_SITE_NAME,
                                       :WS_FIRST_ADDRESS_LINE,
                                       :WS_SECOND_ADDRESS_LINE,
                                       :WS_CITY,
                                       :WS_REGION_ID,
                                       :WS_COUNTRY_ID,
                                       :WS_POSTAL_CODE,
                                       :WS_PHONE_NO
            END-EXEC.

            IF SQLCODE = SQL-SUCCESS
                THEN MOVE VR_SITES_WKSP TO SI_ARRAY(SI_ARRAY_INDEX).

            SET SI_ARRAY_INDEX UP BY 1.

    FILL-ARRAY-EXIT.

            EXIT.

    SQL-NOT-FOUND.

            MOVE RECNOTFND TO RET-STAT.

            EXEC SQL
                ROLLBACK
            END-EXEC.

            GO TO EXIT-PROGRAM.

    SQL-ERROR-HANDLER.

            MOVE SQLCODE TO RET-STAT.

            EXEC SQL
                WHENEVER SQLERROR CONTINUE
            END-EXEC.

            GO TO EXIT-PROGRAM.

    EXIT-PROGRAM.

            EXIT PROGRAM.

Table 12-2 Description of Code for VR_GET_SITES_PROC COBOL Step Procedure
Callout | Description
--- | ---
`[SRV1]` | Defines the status that is returned to the task. RET-STAT is returned to the ACMS$L_STATUS field in the ACMS$PROCESSING_STATUS workspace. When the value of ACMS$L_STATUS changes, ACMS internally updates related fields, such as ACMS$T_SEVERITY_LEVEL, which can be tested when control is returned to the task.
`[SRV2]` | Defines an external status that matches up with the message file that is used in the ACMS application. These values can then be used in the task as well.
`[SRV3]` | Declares COBOL variables that are used in the Oracle SQL statements. (These varibles must be included in the DECLARE SECTION.)
`[SRV4]` | Defines the maximum number of sites (60) that can be returned to the task. This number matches the dimensions of the VR_SI_ARRAY_WKSP.
`[SRV5]` | Defines SQL status values.
`[SRV6]` | Includes the Oracle SQL communications area that is updated every time an SQL statement is executed.
`[SRV7]` | Includes the two workspaces that are passed back and forth between the ACMS task and this procedure. The text library includes embedded SQL DECLARE SECTION statements, because the fields in the workspaces are used in the embedded SQL statements in the 3GL code.
`[SRV8]` | Declares a cursor, opens the cursor, fetches data into the cursor and closes the cursor. Control is then returned to the task that called this procedure. This is one of the ways that this code can be distributed between the various portions of procedure server code. (Because this manual assumes Oracle experience, it does not include a detailed explanation of all of the SQL code.)

Keep the following in mind so that your 3GL server code is interoperable:

- Server processes are serially reusable, which means that there is no guarantee that one user will run the same instance of a server process consecutively. Because of this, the contents of working storage might not be the same throughout all the steps of a task for a particular user (unless server context is retained over processing steps, which is not recommended). The contents of working storage must be moved to an ACMS workspace so that the values are preserved over multiple users of a server.
- Whenever a host variable is used in an embedded SQL statement, that variable must be declared either in working storage or in the linkage section between the SQL BEGIN DECLARE SECTION and the SQL END DECLARE SECTION statements. If the variables are included in a record definition, the copied record definition must be a text record definition and not a CDD record definition. (See Section 12.4 for information about field and record definitions.)
- Oracle SQL does not include a statement like the Rdb SQL DECLARE EXTERNAL SCHEMA statement. The connection to an Oracle database is made through the logical ORA_SID, which ties a process to an instance of an Oracle database.
- The Oracle database manager performs an implicit SET TRANSACTION READ ONLY and then increments its locks when data is selected for update. The Rdb SQL SET TRANSACTION statement is replaced by the SQL CONNECT statement.
- The Oracle server code includes commits and rollbacks within the 3GL code. You cannot embed commits and rollbacks in the task TDL code as you can with Rdb. Also, you cannot use the database recovery TDL statements in the task definition.
- The ORACLE ARRAY FETCH statement is recommended, because it allows a single database read to fetch multiple rows into a cursor.

When debugging, an application developer's debugging session is different from a multiuser production environment. The application developer is a single user of that instance of the server process and, as such, is automatically guaranteed the same instance throughout the debugging session. The developer must ensure that working storage variables that need to be saved between processing steps in the task are moved into a workspace and passed back and forth between the task and the 3GL code.

After you write an Oracle server procedure, you must compile it. Use the following Oracle SQL precompile statement to compile the VR_GET_SITES_PROC procedure:

    $  PROCOBOL HOST=COBOL INAME=vr_get_sites_proc MODE=ANSI FORMAT=TERMINAL -
    _$ HOLD_CURSOR=Y RELEASE_CURSOR=NO SELECT_ERROR=NO SQLCHECK=SYNTAX

Execute the following statements to compile the VR_GET_SITES_PROC code with the COBOL compiler, and insert the resulting object into an object library:

    $ COBOL vr_get_sites_proc
    $ LIBRARY ora_obj_lib vr_get_sites_proc

Once all of the modules are compiled, link them with the following command, where VR_SERVER is the name of the server executable, and VR_OBJECT is the object created for that server when the task group is built with an ACMS ADU BUILD GROUP command:

    $ LNPROCOB vr_server vr_object, ora_obj_lib/LIB

# 12.2 Application, Task Group, and Menu Definitions

This section describes the code that:

- Sets the environment and control characteristics of tasks and task groups (AVERTZ_VR_APPLICATION application definition)
- Sets the resources required by the group of tasks (VR_TASK_GROUP task group definition)
- Displays a list from which users can choose available tasks and menus (ACMS_SAMPLE_MENU menu definition)

## 12.2.1 Application Definition

Example 12-3 is an ACMS application definition (AVERTZ_VR_APPLICATION) that defines the characteristics for the application, the servers, and the task groups.

Table 12-3 describes the coding in the AVERTZ_VR_APPLICATION application definition in more detail.

Example 12-3 AVERTZ_VR_APPLICATION Application Definition

    REPLACE APPLICATION AVERTZ_VR_APPLICATION                              [APP1]
    AUDIT;

    MAX SERVER PROCESS IS 2;                                               [APP2]
    MAX TASK INSTANCE IS 5;

    APPLICATION USERNAME IS ORAAPP;                                        [APP3]
    APPLICATION DEFAULT DIRECTORY IS "AVERTZ_ORACLE_DIR";

    TASK DEFAULTS ARE                                                      [APP4]
        ACCESS CONTROL LIST IS
            ID [*,*] ACCESS EXECUTE;
        AUDIT;
        WAIT;
    END TASK DEFAULTS;

    SERVER DEFAULTS ARE                                                    [APP5]
        AUDIT;
        DEFAULT DIRECTORY IS "AVERTZ_ORACLE_DIR";
        LOGICAL NAME IS ORA_SID = "X1";
        MINIMUM SERVER PROCESSES IS 0;
        USERNAME IS USERNAME OF APPLICATION;
    END SERVER DEFAULTS;

    TASK GROUP IS                                                          [APP6]
        VR_TASK_GROUP: TASK GROUP FILE IS "AVERTZ_ORACLE_DIR:VR_TASK_GROUP";

    END TASK GROUP;
    END DEFINITION;

Table 12-3 Description of Code for AVERTZ_VR_APPLICATION Application Definition
Callout | Description
--- | ---
`[APP1]` | Replaces an old CDD dictionary application definition with the current application definition or creates a new definition if one does not already exist. Section 12.4 discusses the role of the CDD dictionary. The AUDIT clause indicates that application-level activities (such as starting and stopping the application) are noted in the ACMS audit log.
`[APP2]` | Specifies the maximum number of server processes that this application can have running, and the maximum number of task instances that can be active for this application. The maximum number of task instances is larger than the maximum number of server instances because users share server processes serially.
`[APP3]` | Defines the OpenVMS account and default OpenVMS directory for the application.
`[APP4]` | Describes the defaults for each task. The access control list is related to task security. The AUDIT clause indicates that task-level activities (such as the calling of tasks, including the time and user name of the caller) are noted in the ACMS audit log. The WAIT clause causes a message to be displayed to the user when a task has finished executing. The user is required to press Return to get back to a menu. The AUDIT and WAIT clauses are optional.
`[APP5]` | Describes the attributes for the procedure server. The AUDIT clause indicates that server-level activities (such as the calling of servers, including the time and user name of the caller) are noted in the ACMS audit log. The DEFAULT DIRECTORY clause associates a default device and directory with the server process. The instance of the AVERTZ Oracle database is known to the server through the use of the logical ORA_SID. The minimum number of server instances for this server is set. The server process runs in the same account as the application.
`[APP6]` | Lists the task group that is associated with this particular application. Although this sample has a single task group, ACMS applications often consist of several tasks groups that contain many tasks in each application.

## 12.2.2 Task Group Definition

Example 12-4 is an ACMS task group definition (VR_TASK_GROUP). The task group definition specifies:

- Message file specification
- DECforms form file information
- Tasks that belong to the group
- Procedures that are in the server

Table 12-4 describes the coding in the VR_TASK_GROUP task group definition in more detail.

Example 12-4 VR_TASK_GROUP Task Group Definition

    REPLACE GROUP VR_TASK_GROUP                                            [GRP1]

    MESSAGE FILE IS "AVERTZ_ORACLE_DIR:VRMSG.EXE";                         [GRP2]

    FORMS ARE                                                              [GRP3]
      VR_RESERVE_CAR_FORM IN "VR_FORMS.EXE" WITH NAME VR_RESERVE_CAR_FORM,
      VR_DISPLAY_SITES_FORM IN "VR_FORMS.EXE" WITH NAME VR_DISPLAY_SITES_FORM,
      VR_DISPLAY_CU_FORM IN "VR_FORMS.EXE" WITH NAME VR_DISPLAY_CU_FORM;

    TASKS ARE                                                              [GRP4]
          VR_RESERVE_CAR_TASK   : TASK IS VR_RESERVE_CAR_TASK;
          VR_DISPLAY_SITES_TASK : TASK IS VR_DISPLAY_SITES_TASK;
          VR_DISPLAY_CU_TASK    : TASK IS VR_DISPLAY_CU_TASK;
    END TASKS;

    SERVER IS VR_SERVER:                                                   [GRP5]
          PROCEDURE SERVER IMAGE IS "VR_SERVER.EXE";
          PROCEDURES ARE
                     VR_FIND_SI_PROC,
                     VR_GET_RATES_PROC,
                     VR_VERIFY_AVAILABILITY_PROC,
                     VR_FIND_CU_PROC,
                     VR_STORE_CU_PROC,
                     VR_WRITE_RS_PROC,
                     VR_GET_REGIONS_PROC,
                     VR_GET_SITES_PROC,
                     VR_GET_CUSTOMERS_PROC,
                     VR_MOVE_RE_PROC,
                     VR_MOVE_SI_PROC,
                     VR_MOVE_CU_PROC;
          INITIALIZATION PROCEDURE IS VR_INIT;                             [GRP6]
          TERMINATION PROCEDURE IS VR_TERM;                                [GRP7]
          DEFAULT OBJECT FILE IS "VR_OBJECT.OBJ";
    END SERVER;

    END DEFINITION;

Table 12-4 Description of Code for VR_TASK_GROUP Task Group Definition
Callout | Description
--- | ---
`[GRP1]` | Replaces an old CDD dictionary task group definition with the current task group definition or creates a new definition if one does not already exist. Section 12.4 discusses the role of the CDD dictionary.
`[GRP2]` | Names the message file that is used in the GET ERROR MESSAGE clause in the tasks.
`[GRP3]` | Lists the DECforms form files that are used by the tasks in the task group, the location of those forms on the system, and the label (for reference) that is used within the task definition for each form.
`[GRP4]` | Lists the task definitions that are associated with that task group and the label that is used for each task. Typically, the label is the same as the name, but can be changed for special circumstances.
`[GRP5]` | Defines the contents of the procedure server named VR_SERVER. The procedure server is a single process that manages the initialization procedure (VR_INIT), the termination procedure (VR_TERM), and all the step procedures.
`[GRP6]` | Names the initialization procedure that is run when the procedure server images starts up.
`[GRP7]` | Names the termination procedure that is run when the procedure server image runs down.

## 12.2.3 Menu Definition

Example 12-5 is an ACMS menu definition (ACMS_SAMPLE_MENU) that allows users to select a menu or a task. In this example, the menu definition file contains the definitions for a hierarchy of menus. The VR_RESERVE_CAR_TASK in the third-level menu calls the VR_DISPLAY_SITES_TASK described in Section 12.1.1. In larger applications, multiple options (tasks and menus) are typically offered on the menu.

Table 12-5 describes the coding in the ACMS_SAMPLE_MENU menu definition in more detail.

Example 12-5 ACMS_SAMPLE_MENU Menu Definition

    REPLACE MENU ACMS_SAMPLE_MENU                                            [MEN1]

    HEADER IS "  A C M S    S a m p l e    A p p l i c a t i o n   M e n u"; [MEN2]

    ENTRIES ARE                                                              [MEN3]

        AVERTZ_TOP: MENU IS AVERTZ_ORACLE_CDD.AVERTZ_TOP;
                    TEXT IS "AVERTZ APPLICATION MENU";

    END ENTRIES;
    END DEFINITION;

    REPLACE MENU AVERTZ_TOP

    HEADER IS
    "                          A V E R T Z    T O P     M E N U  ";

    ENTRIES ARE                                                              [MEN4]

        VR_MENU:    MENU IS AVERTZ_ORACLE_CDD.VR_MENU;
                    TEXT IS "Vehicle Rental Menu";

    END ENTRIES;
    END DEFINITION;

    REPLACE MENU VR_MENU
    HEADER IS
                    "      V E H I C L E     R E N T A L     M E N U";

    ENTRIES ARE                                                             [MEN5]

        RESERVE:   TASK IS VR_RESERVE_CAR_TASK IN O_AVERTZ_VR_APPLICATION;
                   TEXT IS " Reserve Car Task";
    END ENTRIES;
    END DEFINITION;

Table 12-5 Description of Code for ACMS_SAMPLE_MENU Menu Definition
Callout | Description
--- | ---
`[MEN1]` | Replaces an old CDD dictionary menu definition with the current menu definition or creates a new definition if one does not already exist. Section 12.4 discusses the role of the CDD dictionary.
`[MEN2]` | Defines the text to be displayed at the top of the ACMS menu (the name of the menu).
`[MEN3]` | Defines each first-level menu item. (In this case, there is only one first-level menu item: AVERTZ APPLICATION MENU.) The menu definition also defines the name of the menu definition for the menu item and the text associated with that menu item. Typically, a menu definition consists of multiple entries for tasks and, possibly, additional menus.
`[MEN4]` | Defines each second-level menu item. (In this case, there is only one second-level menu item: Vehicle Rental Menu.)
`[MEN5]` | Defines each third-level menu item. (In this case, there is only one third-level menu item: Reserve Car Task.)

# 12.3 Additional Procedure Server Components

This section describes the code that:

- Makes the initial connection to an instance of an Oracle database for a server process (VR_INIT initialization procedure)
- Disconnects the server process from an instance of an Oracle database (VR_TERM termination procedure)

Previous | Next | Contents | Index