Compaq ACMS for OpenVMS
Writing Server Procedures


Previous Contents Index

The following example illustrates how to handle RMS errors using BASIC. Note that the EXIT HANDLER statement is used to resignal the error and exit the error handler in BASIC.


    FUNCTION LONG pers_change_employee_proc( employee_record emp_wksp ) 
 
    %INCLUDE "pers_files:pers_common_defns" 
    %INCLUDE %FROM %CDD "pers_cdd.employee_record" 
 
 
    DECLARE LONG sts 
 
    MAP ( emp_map ) employee_record emp_rec 
 
 
    WHEN ERROR IN 
        GET # emp_file,                                         & 
            KEY # 0 EQ emp_wksp::emp_badge_number,              & 
            ALLOW NONE,                                         & 
            WAIT 20 
        IF emp_rec::emp_last_update = emp_wksp::emp_last_update & 
        THEN 
            MOVE TO # emp_file, emp_wksp 
            sts = SYS$GETTIM( emp_rec::emp_last_update BY REF ) 
            IF ( sts AND 1% ) = 0%                              & 
            THEN 
                CALL LIB$STOP( sts ) 
            END IF 
            UPDATE # emp_file 
            pers_change_employee_proc = persmsg_success 
 
        ELSE 
            pers_change_employee_proc = persmsg_empchanged 
        END IF 
        UNLOCK # emp_file 
 
    USE 
        SELECT ERR 
            CASE    basicerr_record_not_found 
                pers_change_employee_proc = persmsg_empdeleted 
            CASE    basicerr_record_locked,                             & 
                    basicerr_deadlock,                                  & 
                    basicerr_wait_exhausted 
                CALL ACMS$RAISE_TRANS_EXCEPTION( ACMS$_TRANSTIMEDOUT ) 
 
            CASE    ELSE 
                IF ( RMSSTATUS( emp_file ) = RMS$_NRU ) OR              & 
                   ( RMSSTATUS( emp_file ) = RMS$_DDTM_ERR )            & 
                THEN 
                    CALL ACMS$RAISE_TRANS_EXCEPTION( RMSSTATUS( emp_file ) ) 
                ELSE 
                    CALL ACMS$RAISE_NONREC_EXCEPTION( RMSSTATUS( emp_file ) ) 
                    EXIT HANDLER 
                END IF 
        END SELECT 
    END WHEN 
 
    END FUNCTION 


Chapter 5
Using Message Files with ACMS Tasks and Procedures

At times, tasks and procedures need to return messages to users telling them, for example, that information they requested is locked by another user, that information they typed is not valid for the file the task is using, or that other errors have occurred. You can simplify returning messages to users by setting up a message file that contains the text of messages you want to display. If you set up a message file, you can change the text of messages without having to recompile and relink the procedures and definitions in the application.

This chapter discusses the following topics:

For more information on creating message files than is in this chapter, see OpenVMS Command Definition, Librarian, and Message Utilities Manual.

5.1 Creating Source Files of Messages

A message source file has two main parts:


.TITLE VRMSG Messages for AVERTZ 
.IDENT /Version 1.0/ 
 
.FACILITY VR,1 / PREFIX=VR_ 
 
.SEVERITY INFORMATION 
 
MULCURECFND <Multiple customer records found> 
MULRSRECFND <Multiple reservation records found> 
 
.END 

The following sections explain how to write each part of a message source file. Example 5-1 contains a complete message source file.

5.1.1 Setting Up Message File Characteristics

Three kinds of information can appear in the first part of a message source file, which contains statements that apply to the entire message file:

The .TITLE statement defines the object module name, which is assigned to the object module when you compile the source file using the Message Utility. The object module does not need to have the same name as the source file or the file containing the object module, but it is common practice to do so. The maximum length of the module name is 31 characters.

In the .TITLE statement, include a module name and a listing title. For example:


.TITLE VRMSG Messages for AVERTZ 

After the module name (here, VRMSG) is a listing title. If you use the /LIST qualifier when compiling the source file, the listing title (in this case, Messages for AVERTZ), appears at the top of each page of the .LIS file. The maximum length of a listing title is 28 characters.

Optionally, you can use an .IDENT statement after a .TITLE statement to include additional information (beyond that supplied by the .TITLE statement) in the object module and the listing file. For example, you can use .IDENT to identify the version of the file:


.IDENT /Version 1.0/ 

The Message Utility includes the literal string from the .IDENT statement in the object module name.

To include comment text in your source file, use an exclamation mark (!). For example:


! History: 
!           V1.0    Created 12-May-91. 
 

Comment text helps others understand the message file and documents the history of the file.

5.1.2 Writing Messages

The main part of a message source file includes the following:

The following sections explain how to write these.

5.1.2.1 .FACILITY Statement

You must have at least one .FACILITY statement and one .END statement in a message file.

The following example illustrates how to use the .FACILITY statement:


.FACILITY VR,1 
  . 
  . 
  . 
.END 

Always include both a 1- to 9-character facility name and a facility number in each .FACILITY statement. In the example, VR is the facility name. Separate the facility name and the facility number with either a comma, one or more spaces, or tabs. The name used in a .FACILITY statement does not need to be unique in the message file.

The number in the .FACILITY statement must be a decimal value in the range of 1 to 2047. The facility number used must be unique for the facility name. In the example, 1 is the facility number. For a list of the qualifiers that you can use with the .FACILITY statement, see OpenVMS Command Definition, Librarian, and Message Utilities Manual.

The .END statement has no parameters or qualifiers. Always end the file with an .END statement.

5.1.2.2 .SEVERITY Statements

In each block of messages, group messages by their OpenVMS severity levels. The five severity level keywords are:

Use these keywords to mark the beginning of a subgroup of messages in the .SEVERITY statement. For example:


.FACILITY VR,1 
.SEVERITY INFORMATION 
  . 
  . 
  . 
.END 

In message files for ACMS tasks, application developers can write the text of severity messages. In the AVERTZ sample application, most messages are either INFORMATION level or WARNING level messages. The messages for recoverable errors, for example, indicate that an error prevented the procedure from completing but that the user can recover from the error.

Chapter 3 and OpenVMS RTL Library (LIB$) Manual contain more information about severity levels.

5.1.2.3 Message Names and Text

Messages contain the following:

In the previous example, each message text follows a message name (MULCURECFND, for example). ACMS uses message symbols (rather than message names) to retrieve message text from the message file. The linker also uses message symbols to resolve the message symbols in step procedures.

When you compile a message source file, the Message Utility creates a symbol for each message by putting the facility code and an underscore (_) in front of each message name.

Follow these guidelines when creating and using message symbols:

Example 5-1 shows a complete message source file.

Example 5-1 Source File of Messages

 
.TITLE VRMSG Messages for AVERTZ 
.IDENT /Version 1.0/ 
.FACILITY VR,1 /PREFIX=VR_ 
 
.SEVERITY INFORMATION 
MULCURECFND <Multiple customer records found> 
MULRSRECFND <Multiple reservation records found> 
VEUPGPRF    <Vehicle upgrade performed - no charge> 
VEDNGPRF    <Vehicle downgrade performed - rates adjusted> 
CURECUPD    <Customer record has been updated in database-hit RETURN to continue> 
CURECINS    <Customer record has been inserted in database> 
CHKINCOMP   <Vehicle Checking-in completed successfully - hit RETURN to continue> 
CHKOUTCOM   <Vehicle Checkout completed successfully - hit RETURN to continue> 
RESVCOMP    <Vehicle reservation completed successfully - hit RETURN to continue> 
VERECFND    <Vehicle(s) found in class requested, choose one> 
RESSUCCNCLD <Reservation successfully canceled - hit RETURN to continue> 
 
.SEVERITY WARNING 
CURECNOTFND  <Customer record not found> 
RCRECNOTFND  <Rental class record not found> 
RERECNOTFND  <Invalid state/country-reenter valid state/country names> 
RSRECNOTFND  <Reservation record not found > 
SIRECNOTFND  <Site record not found, press PF1 S for a list of sites> 
VERECNOTFND  <No vehicles available for checkout - hit RETURN to continue> 
VRHRECNOTFND <Vehicle rental history record not found> 
NOTCHKOUT    <Vehicle not checked out> 
RESCNCLD     <Reservation was canceled - reenter data or PF1 Q to quit> 
CARCHKIN     <Reservation archived,car checked in,paid in full> 
CARCHKOUT    <Vehicle has already been checked out - reenter data or PF1 Q to quit> 
RESCLOSED    <Reservation archived,car checked in,payment pending> 
DLRENOTFND   <Invalid Driver's license state/country> 
NOCANCEL     <Reservation cannot be canceled at this stage> 
INACTIVE     <Please enter data or task will be canceled due to inactivity> 
DDTM_TIMEOUT <The distributed transaction timed out --- please retry> 
 
.SEVERITY ERROR 
NO_DUP           <Duplicate database key> 
DEADLOCK         <Database deadlock> 
INTEG_FAIL       <Database integrity failure> 
LOCK_CONFLICT    <Database lock conflict> 
CAR_UNAVAILABLE  <Vehicle unavailable - hit RETURN to continue> 
CHK_CANCL_ERR    <Error in checkout or cancel reservation> 
HIST_WRITE_ERR   <Error in writing to history file> 
UPDATE_ERROR     <Error updating file> 
 
.SEVERITY FATAL 
BILLERR          <Bill computation error - canceling transaction> 
DB_FATAL         <Fatal database error - check audit log> 
ICRECNOTFND      <ID increment control record not found> 
 
.END 

Example 5-1 lists the messages available to tasks in the AVERTZ Vehicle Rental task group. For example, the example lists both CURECNOTFND and RCRECNOTFND under a .SEVERITY WARNING statement. When you compile the file, the Message Utility sets the low three bits of the longwords representing the message symbols to the binary value corresponding to WARNING level (000).

Regardless of what the error level was when the procedure trapped the error, if you return CURECNOTFND or RCRECNOTFND as status values of your procedure, the error level of the return status is WARNING. For information on returning status values, see Chapter 3.

5.2 Compiling Message Files

To use message files with ACMS applications, create two output files from your source file:

Figure 5-1 shows the steps you take and the files you create when you compile message files. Following the figure are numbered instructions that correspond to the numbers in the figure.

Figure 5-1 Creating Message Files


  1. Edit a message file (.MSG) with an editor.
    Follow the instructions in Section 5.1 to create a source file containing the text of messages.
  2. Create the object module (.OBJ) containing the message text from the message file by running the Message Utility with the /OBJECT qualifier. For example:


    $ MESSAGE /OBJECT=VRMSG.OBJ VRMSG.MSG
    

    The optional /OBJECT qualifier defines the name of the object module. If you omit the qualifier (and do not use /NOOBJECT), the utility assigns the file name of the input file to the object module with a file type of .OBJ. The default file type for the input file is .MSG.

  3. Create an .EXE message file by using the LINK command with the /SHARE qualifier. For example:


    $ LINK /SHARE=VRMSG.EXE VRMSG.OBJ
    

    The /SHARE qualifier defines the name of the shareable image to be created by the Linker. If you omit the file name from the /SHARE qualifier, the Linker assigns the file name of the input file to the object module output file, giving the output file a file type of .EXE. The default file type for the input file is .OBJ.

  4. Create an object module that points to the .EXE message file containing the message text by running the Message Utility again, using the /FILE_NAME qualifier with the MESSAGE command. For example:


    $ MESSAGE /FILE_NAME=ACMS$EXAMPLES:VRMSG.EXE/OBJ=VRMSG_PTR  VRMSG
     
    

    When you use this command, the Message Utility creates an object module named VRMSG_PTR.OBJ. This object module contains the message symbols from the source file, but points to VRMSG.EXE for the text corresponding to those symbols. The default file name for the text message file is the same file name as the source file; the default file type is .EXE.
    Always include the device and directory specification for the text message file. Otherwise, ACMS looks for the text message file in the same directory as the ACMS software. Make sure that the name you use in the /FILE_NAME qualifier is the same as the name of the file you created with the LINK command.

  5. After creating the pointer object module, link it into the procedure server images for all servers that handle tasks using that message file. The procedure server image contains all the modules for the procedure server, including step, initialization, and termination procedures; the message object module; and the server control object module created by the BUILD command of the Application Definition Utility. For example:


    $ LINK /DEBUG /EXE=VR_SERVER.EXE VR_SERVER.OBJ, -
    _$ ...,VRMSG_PTR
    

    This example is an abbreviated version of the LINK command. See Chapter 6 for instructions and examples of full LINK commands.

Do not link the text message file into the server image. The .EXE file created with the MESSAGE command is separate from the server image, in the same way that a run-time library is separate from a program.

If you need to change the wording of a message, change the message source file; then use the MESSAGE and LINK commands to create a new text message file (.EXE). You do not need to relink the procedure server image. For example:


$ MESSAGE /OBJ=VRMSG.OBJ VRMSG.MSG
$ LINK/SHARE=VRMSG.EXE VRMSG.OBJ

If you change only the message text, you do not need to create a new object module pointer file. However, if you add a new message, delete a message, change the order of messages in the file, or change a message symbol, you must create a new object module pointer file and relink the server image to include that new module (steps 4 and 5). Otherwise, the symbols in the message file and in the server image do not correspond to one another.

5.3 Displaying User-Defined Messages

After you define error messages in a message file, you can return message names from a server procedure and have the task calling the procedure trap for errors. Follow these steps for returning and displaying user-defined messages:

  1. Define all symbols that you want a procedure to return as external to the program. In COBOL, use the VALUE IS EXTERNAL clause in the procedure. For example:


    01  CURECNOTFND              PIC S9(11) COMP 
                                 VALUE IS EXTERNAL VR_CURECNOTFND. 
    

    In the previous example, the message name is CURECNOTFND; the message symbol is VR_CURECNOTFND.
    In BASIC, use the EXTERNAL CONSTANT statement to define the message symbol in the procedure. For example:


           EXTERNAL LONG CONSTANT VR_CURECNOTFND 
    

    You can define return values either in the program or in a library file of values.

  2. In the procedure, move the message name into the return-status workspace. For example:


    SQL-NOT-FOUND. 
    * If no customer record was found, return warning status. 
            IF CTRL_KEY = "CUSID" THEN 
                    MOVE CURECNOTFND TO RET-STAT 
            . . . 
            END-IF. 
    

    When a procedure returns a value in a return status field, ACMS does the following:


    Chapter 3 explains fields in the ACMS$PROCESSING_STATUS workspace.
  3. Have the task definition check the ACMS$T_STATUS_TYPE field of the ACMS$PROCESSING_STATUS workspace.
    Include the GET MESSAGE clause in the task definition to direct ACMS to store the error message associated with the message symbol in the ACMS$T_STATUS_MESSAGE workspace. For example:


    ACTION IS 
       IF (ACMS$T_STATUS_TYPE = "B") THEN 
           GET MESSAGE INTO vr_control_wksp.messagepanel; 
           GOTO PREVIOUS EXCHANGE; 
       END IF; 
    

    According to the previous instructions, ACMS checks the ACMS$T_STATUS_TYPE field. If it is B (bad), ACMS retrieves the error message. ACMS then goes to the previous exchange step in the task definition to display the error message.


Previous Next Contents Index