HP OpenVMS Systems Documentation
Compaq ACMS for OpenVMS
Chapter 2 briefly introduces the concept of ACMS workspaces and shows how to use them to pass data between parts of an application. Chapter 4 describes workspaces in more detail. Specifically, this chapter describes the three types of ACMS workspaces and explains how to use them to perform the following functions:
Compaq ACMS for OpenVMS Writing Server Procedures explains how to write the procedures required for the
task definitions explained in this chapter.
4.1 Understanding the Types of ACMS Workspaces
The three types of workspaces you can use in your task definitions are:
Task is the default and most frequently used workspace type. Use task workspaces to store database records; to pass data between parts of your application, such as the form and exchange steps; and to perform error handling. Because ACMS retains task workspaces only for the life of a task instance, task workspaces do not use a lot of memory and CPU time. A task instance is one iteration of a task. Therefore, unless your application has certain requirements that can be met only by using user or group workspaces, use task workspaces.
A system workspace is one of three ACMS-supplied task workspaces. The ACMS$PROCESSING_STATUS workspace stores status information returned from procedures. The ACMS$SELECTION_STRING workspace stores text strings passed by the terminal user when the user selects a task from the menu. The ACMS$TASK_INFORMATION workspace stores task execution information. Because system workspaces are task workspaces, they do not use much memory and CPU time.
User workspaces let you store information used by a single user in many tasks or many task instances. User workspaces are helpful when the user needs to use the same information as a key for multiple task selections. For example, in a personnel application, a user might need to retrieve various information about an employee by choosing several tasks. Instead of requiring the user to type in the employee's number for each task, you can store the employee number in a user workspace so that it is available for all tasks that the user selects during that particular ACMS session.
You might also use user workspaces to store user-specific information that changes during the user's session. For example, you might want to keep a log of the type of work done by the user. Because ACMS retains user workspaces for the duration of the user's session, user workspaces require more memory and CPU time than task workspaces.
Group workspaces let you store information used by many users in many tasks or instances of the same task. You typically use group workspaces to store static information. For example, an accounting application might include several tasks that use the current interest rate. Instead of requiring users to repeatedly enter the interest rate, you can store it in a group workspace. Because ACMS retains group workspaces as long as the application is started, group workspaces require more memory and CPU time than task workspaces.
Table 4-1 briefly summarizes the availability and purpose of the three types of workspaces.
|Task||For duration of task instance||
Passing information between:
|User||For user's ACMS session||Storing user-specific information|
|Group||As long as the application is started||Storing static information required by many tasks in a group|
You want to trap errors that a task encounters and tell the user what happened whenever a task encountered them. You use workspaces to pass error-related information among the procedure, the definition, and the form in task definitions.
There are two kinds of workspaces you may want to use for error handling:
The task definitions explained in Chapter 2 used the ACMS$PROCESSING_STATUS system workspace for error handling. When you use the ACMS$PROCESSING_STATUS workspace with the GET ERROR MESSAGE clause, ACMS:
When using workspaces that you define to handle errors, pass the workspace to the form or procedure and move values to a field in the workspace. You then test the workspace in the action part of the step to determine what to do next. This is how the tasks explained in Chapter 2 use the QUIT_KEY field of a workspace to handle actions in exchange steps. You can handle actions in processing steps in the same way.
For example, you can add a field for storing information returned by the WRITE_RESERVE_PROC procedure to the record definition for ADD_RESERVE_WKSP used in the Add Car Reservation task in Chapter 2. Example 4-1 shows the new CDD definition for ADD_RESERVE_WKSP.
|Example 4-1 Record Definition for ADD_RESERVE_WKSP|
Definition of record ADD_RESERVE_WKSP | Contains field WK_CONTROL | | Datatype text size is 7 characters | Contains field CUST_NUMBER | | Datatype signed longword | Contains field CUST_NAME | | Datatype text size is 30 characters | Contains field CUST_STREET_ADDRESS | | Datatype text size is 30 characters | Contains field CUST_CITY | | Datatype text size is 20 characters | Contains field CUST_STATE | | Datatype text size is 2 characters | Contains field CUST_ZIP | | Datatype text size is 5 characters | Contains field CUST_PHONE | | Datatype text size is 10 characters | Contains field CAR_TYPE | | Datatype text size is 3 characters | Contains field RENTAL_DATE | | Datatype text size is 6 characters | Contains field RETURN_DATE | | Datatype text size is 6 characters
The WRITE_RESERVE_PROC procedure returns a value to WK_CONTROL, the new field you have added. Because the WK_CONTROL field is a 7-character text field, the WRITE_RESERVE_PROC procedure can return a literal string describing the success or failure of writing a new record to the Reservation file.
PROCESSING CALL WRITE_RESERVE_PROC IN RESERVE_SERVER USING ADD_RESERVE_WKSP; CONTROL FIELD WK_CONTROL "FAILURE" : GOTO PREVIOUS EXCHANGE; END CONTROL FIELD;
The WRITE_RESERVE_PROC procedure stores a value in the WK_CONTROL field of ADD_RESERVE_WKSP, and you use the CONTROL FIELD clause to test that value. Then you can return a message to the user. There are three ways to return messages to the user:
In this case, if the WRITE_RESERVE_PROC procedure returns the string FAILURE to the WK_CONTROL field, GOTO PREVIOUS EXCHANGE returns ACMS to the previous exchange. You can use the form in the previous exchange to display a message telling the user that the new car reservation record was not added to the file. The "FAILURE" in this example is literal error message text that displays when the WRITE_RESERVE_PROC procedure returns the string FAILURE to the WK_CONTROL field.
Example 4-2 shows the complete definition for the Add Car Reservation task using a workspace that you define for error handling.
|Example 4-2 Task Definition for Add Car Reservation Task|
REPLACE TASK ADD_CAR_RESERVATION_TASK WORKSPACES ARE ADD_RESERVE_WKSP, QUIT_CTRL_WKSP; BLOCK WORK WITH FORM I/O IS GET_RENTAL_INFORMATION: EXCHANGE WORK IS RECEIVE FORM RECORD ADD_RESERVE_FORM_REC_LIS RECEIVING ADD_RESERVE_WKSP, QUIT_CTRL_WKSP; ACTION IS CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY "QUIT" : EXIT TASK; END CONTROL FIELD; WRITE_RESERVATION_INFORMATION: PROCESSING WORK IS CALL WRITE_RESERVE_PROC IN RESERVE_SERVER USING ADD_RESERVE_WKSP; ACTION IS CONTROL FIELD IS WK_CONTROL "FAILURE" : GOTO PREVIOUS EXCHANGE; END CONTROL FIELD; END BLOCK WORK; ACTION IS REPEAT STEP; END DEFINITION;
You can use information that the user supplies when selecting a task from a menu as input to a task.
Users often must type the number or keyword of the task they want to run when selecting a task from a menu like the one shown in Figure 4-1.
Figure 4-1 A Selection Menu
To display the review history of an employee from the menu in Figure 4-1, the user types HISTORY in response to the Selection: prompt.
When a user selects a task from a menu, the first step of the task is often an exchange step asking the user to supply a key, usually something like an employee number or department number. Instead of asking the user for the key after making the selection, however, you can let the user supply that information when making a selection. ACMS stores this selection string in the system workspace, ACMS$SELECTION_STRING.
Example 4-3 shows the record definition of the ACMS$SELECTION_STRING workspace.
|Example 4-3 Definition for the ACMS$SELECTION_STRING Workspace|
DEFINE RECORD DISK1:[CDDPLUS]ACMS$DIR.ACMS$WORKSPACES.ACMS$SELECTION_STRING. ACMS$SELECTION_STRING STRUCTURE. ACMS$T_SELECTION_STRING DATATYPE TEXT 255. END STRUCTURE. END RECORD.
Like the ACMS$PROCESSING_STATUS system workspace, the ACMS$SELECTION_STRING workspace is automatically available to all tasks. In the ACMS$SELECTION_STRING workspace, ACMS stores any text containing up to 255 characters that the user types after typing the number or keyword of a task.
If you use the ACMS$SELECTION_STRING workspace to let the user type in a record key, the first exchange step of the task can check for that key in the ACMS$SELECTION_STRING workspace. The exchange step displays a DECforms panel asking for the key only if the workspace field is empty. Any validation work that the form normally performs is bypassed. If the field contains a key, ACMS does not do any work in the first exchange step of the task and goes directly to the second step.
VALIDATE_EMPLOYEE: EXCHANGE CONTROL FIELD ACMS$T_SELECTION_STRING "" : RECEIVE FORM RECORD DISPLAY_NUMBER_FORM_REC RECEIVING ACMS$SELECTION_STRING; NOMATCH : NO EXCHANGE; END CONTROL FIELD;
You can also use the CONTROL FIELD clause to take conditional actions based on the contents of a workspace field. ACMS checks the field ACMS$T_SELECTION_STRING field in the VALIDATE_EMPLOYEE step. If the field is empty, the user did not supply an employee number when selecting the Display Basic task, and DISPLAY_BASIC_FORM displays a panel asking for the employee number. The form stores this number in the ACMS$SELECTION_STRING workspace.
At the end of the previously shown exchange step, the ACMS$SELECTION_STRING workspace always contains an employee number, typed in either as a selection string or in response to the initial panel. Because the processing step in the Display Basic task needs the employee number to know what record to get, you must pass the contents of the selection string workspace to the procedure in the processing step.
PROCESSING CALL DISPLAY_BASIC_GET USING ACMS$SELECTION_STRING, HIST_RECORD, PERS_RECORD; CONTROL FIELD ACMS$T_STATUS_TYPE "G" : GOTO NEXT STEP; "B" : GET ERROR MESSAGE; GOTO PREVIOUS EXCHANGE; END CONTROL FIELD;
The DISPLAY_BASIC_GET procedure uses the employee number stored in the ACMS$SELECTION_STRING workspace to read basic employee information from both the History and Personnel files. You name the ACMS$SELECTION_STRING workspace in the USING part of the CALL clause, if the processing step uses information stored in the workspace.
The error handling in this processing step is the same as that in other tasks explained in this manual. If the DISPLAY_BASIC_GET procedure returns a recoverable error, ACMS:
The DISPLAY_BASIC_GET procedure has to test and clear the ACMS$T_SELECTION_STRING workspace before using the form. If the workspace had contained a value when tested in the first exchange step, this would have put the task into an infinite loop.
Example 4-4 shows the complete definition for the Display Basic task.
|Example 4-4 Definition for Display Basic Task|
REPLACE TASK DISPLAY_BASIC USE WORKSPACES ADMIN_WORKSPACE, HIST_RECORD, PERS_RECORD, QUIT_CTRL_WKSP; DEFAULT SERVER IS ADMINISTRATION_SERVER; DEFAULT FORM IS DISPLAY_BASIC_FORM BLOCK WORK WITH NO SERVER CONTEXT FORM I/O VALIDATE_EMPLOYEE: EXCHANGE CONTROL FIELD ACMS$T_SELECTION_STRING "" : RECEIVE FORM RECORD DISPLAY_NUMBER_FORM_REC RECEIVING ACMS$SELECTION_STRING; NOMATCH : NO EXCHANGE; END CONTROL FIELD; PROCESSING CALL DISPLAY_BASIC_GET USING ACMS$SELECTION_STRING, HIST_RECORD, PERS_RECORD; CONTROL FIELD ACMS$T_STATUS_TYPE "G" : GOTO NEXT STEP; "B" : GET ERROR MESSAGE; GOTO PREVIOUS EXCHANGE; END CONTROL FIELD; DISPLAY_BASIC_DATA: EXCHANGE TRANSCEIVE FORM RECORD DISPLAY_BASIC_FORM_REC, QUIT_CTRL_FORM_REC SENDING ADMIN_WORKSPACE RECEIVING QUIT_CTRL_WKSP; CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY "QUIT" : EXIT TASK; END CONTROL FIELD; END BLOCK WORK; ACTION REPEAT STEP; END DEFINITION;
When using the ACMS$SELECTION_STRING workspace to let the user supply a record key when selecting a task, you:
When you use the contents of the ACMS$SELECTION_STRING workspace as
input to a task, validation of that information, normally handled by
the form, must be handled in the procedure code of the task.
4.4 Using Group Workspaces
Often there is some information that many tasks in a task group use. For example, in an accounting application there may be several tasks in a task group that always require the current interest rate. You can store this shared information in a group workspace.
Each task instance using a group workspace gets its own copy of the workspace. ACMS discards the copy of the workspace belonging to each task instance, but unless the workspace is being updated, ACMS keeps the original contents of a group workspace when a task instance is finished, as it does with the contents of a task workspace. This procedure allows many tasks or different instances of the same task to use the contents of a group workspace many times.
A Labor Reporting task shows one example of how to use a group workspace. This task lets the user type information about the work that an employee did on different projects. Part of the information used by the task each time it runs is the week-ending date. Rather than require the user to supply the date whenever typing information for an employee, you can store that date in a group workspace. The task can then access that workspace each time it runs.
Example 4-5 shows the record definition for LABOR_GROUP_WORKSPACE.
|Example 4-5 Record Definition for GROUP_WORKSPACE|
DEFINE RECORD DISK1:[CDDPLUS]ACMS$DIR.ACMS$EXAMPLES_RMS.LABOR_GROUP_WORKSPACE. LABOR_GROUP_WORKSPACE STRUCTURE. WK_ENDING_DATE DATATYPE TEXT 6. INITIAL VALUE "". END LABOR_GROUP_WORKSPACE STRUCTURE. END LABOR_GROUP_WORKSPACE.
The Labor Reporting task uses the last of these methods to set the initial contents of the workspace. The first step of the task uses a CONTROL FIELD clause to test the contents of the workspace and, if the workspace does not contain the week ending date, runs another task, Get Initial Value, that initializes the workspace. You can run another task without returning the user to a selection menu by using the task-call-task feature, described in detail in Chapter 5.
The Get Initial Value task consists of a single processing step that runs a procedure to initialize the group workspace.
The Labor Reporting task is the only task using the workspace named LABOR_GROUP_WORKSPACE, so you can declare this group workspace at either the group or task level. However, by declaring workspaces at the group level, you ensure that the same workspace name is used consistently by all tasks. You use the USE WORKSPACES clause in the task definition to specify that workspaces to be used in a task are declared at the group level:
USE WORKSPACES LABOR_GROUP_WORKSPACE, LABOR_RECORD, LABOR_WORKSPACE;
Here is the first step of the Labor Reporting task:
PROCESSING NO PROCESSING; CONTROL FIELD LABOR_GROUP_WORKSPACE.WK_ENDING_DATE "" : GOTO TASK GET_INITIAL_VALUE_TASK; NOMATCH : GOTO NEXT STEP; END CONTROL FIELD;
The WK_ENDING_DATE field must be defined to have an initial value of " ". If you do not define an initial value for the field, ACMS initializes it with zeros. If the CONTROL FIELD clause tests the field for " " and finds zeros, it always takes the action associated with the NOMATCH keyword, because the field is not empty.
If the WK_ENDING_DATE field is empty, ACMS runs INITIAL_VALUE_TASK. Example 4-6 shows the definition for that task.
|Example 4-6 Complete Definition for the Get Initial Value Task|
REPLACE TASK GET_INITIAL_VALUE_TASK USE WORKSPACE LABOR_GROUP_WORKSPACE WITH UPDATE LOCK; PROCESSING CALL LABOR_GET_INITIAL_VALUE IN WORKSPACE_SERVER USING LABOR_GROUP_WORKSPACE; CONTROL FIELD ACMS$T_STATUS_TYPE "G" : GOTO TASK LABOR_DATA_ENTRY_TASK; "B" : CANCEL TASK; END CONTROL FIELD; END DEFINITION;
The LABOR_GET_INITIAL_VALUE procedure gets the week-ending date from a file and stores it in the WK_ENDING_DATE field of the workspace LABOR_GROUP_WORKSPACE. When the week-ending date needs to be changed, the contents of the file must be changed, and the application or applications using that workspace must be stopped and restarted.
If the LABOR_GET_INITIAL_VALUE procedure is unsuccessful, ACMS cancels the task, returning the user to the menu. If the procedure is successful, ACMS processes the rest of the Labor Reporting task. When the initial processing step of that task runs, the LABOR_GROUP_WORKSPACE contains the week-ending date. The next step in the task can:
In the Labor Reporting task, once the first processing step has checked the contents of the group workspace, an exchange step uses a form to display an initial panel. Here is the first exchange step of the Labor Reporting task:
EXCHANGE TRANSCEIVE FORM RECORD LABOR_GROUP_FORM_REC, EMPLOYEE_FORM_REC_LIS SENDING LABOR_GROUP_WKSP RECEIVING EMPLOYEE_RECORD_WKSP, QUIT_CTRL_WKSP; ACTION IS CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY "QUIT" : EXIT TASK; END CONTROL FIELD;
When this step is complete, the task runs like any other update task. The user supplies a record key to a form in this exchange step. A procedure in a processing step uses that key to read information from a file or database. A form in an exchange step displays that information for the user. The user can then type additional information. In the Labor Reporting task, the user types project information for an employee.
Example 4-7 shows the complete definition for the Labor Reporting task.
|Example 4-7 Definition for Labor Reporting Task|
REPLACE TASK LABOR_DATA_ENTRY_TASK USE WORKSPACES EMPLOYEE_RECORD_WKSP, LABOR_GROUP_WKSP, LABOR_RECORD_WKSP, QUIT_CTRL_WKSP; DEFAULT SERVER IS LABOR_SERVER; DEFAULT FORM IS LABOR_FORM BLOCK WORK WITH FORM I/O PROCESSING NO PROCESSING; CONTROL FIELD LABOR_GROUP_WKSP.WK_ENDING_DATE "" : GOTO TASK GET_INITIAL_VALUE_TASK; NOMATCH : GOTO NEXT STEP; END CONTROL FIELD; EXCHANGE TRANSCEIVE FORM RECORD LABOR_GROUP_FORM_REC, EMPLOYEE_FORM_REC_LIS SENDING LABOR_GROUP_WKSP RECEIVING EMPLOYEE_RECORD_WKSP, QUIT_CTRL_WKSP; ACTION IS CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY "QUIT" : EXIT TASK; END CONTROL FIELD; PROCESSING CALL LABOR_EMPLOYEE_GET USING EMPLOYEE_RECORD_WKSP; CONTROL FIELD ACMS$T_STATUS_TYPE "B" : GET ERROR MESSAGE; GOTO PREVIOUS EXCHANGE; "G" : GOTO NEXT STEP; END CONTROL FIELD; GET_PROJECT_DATA: EXCHANGE TRANSCEIVE FORM RECORD LABOR_FORM_REC, LABOR_FORM_REC_LIS SENDING LABOR_RECORD_WKSP RECEIVING LABOR_RECORD_WKSP, QUIT_CTRL_WKSP; ACTION IS CONTROL FIELD IS QUIT_CTRL_WKSP.QUIT_KEY "QUIT" : EXIT TASK; END CONTROL FIELD; PROCESSING CALL LABOR_PROJECT_PUT USING LABOR_GROUP_WORKSPACE, LABOR_RECORD_WKSP; CONTROL FIELD ACMS$T_STATUS_TYPE "B" : GET ERROR MESSAGE; GOTO PREVIOUS EXCHANGE; END CONTROL FIELD; END BLOCK WORK; ACTION REPEAT STEP; END DEFINITION;