Introduction

Introduction: RPC Broker V. 1.1

The RPC Broker is a client/server system within VA's Veterans Health Information Systems and Technology Architecture (V IST A) environment. It enables client applications to communicate and exchange data with M Servers.

This manual describes the development features of the RPC Broker. The emphasis is on using the RPC Broker in conjunction with Borland's Delphi software. However, the RPC Broker supports other development environments.

This manual provides a complete reference for development with the RPC Broker. For an overview of development with the RPC Broker component, see the RPC Broker V. 1.1 Getting Started with the Broker Development Kit manual.

This document is intended for the V IST A development community and Information Resource Management (IRM) staff. A wider audience of technical personnel engaged in operating and maintaining the Department of Veterans Affairs (VA) software may also find it useful as a reference.

About this version of the RPC Broker

What's New in V. 1.1 of the BDK

Context-Sensitive Help for TRPCBroker Component

Installing Context-Sensitive Help for Delphi 3.x

Installing Context-Sensitive Help for Delphi 2.x

Orientation


About This Version of the RPC Broker

This version of the Broker provides programmers with the capability to develop new V IST A client/server software using the Broker Delphi component (i.e., TRPCBroker) in the 32-bit environment.

To develop V IST A applications in a 32-bit environment you must have Delphi V. 2.0 or greater. This version of the TRPCBroker component does not allow you to develop applications in Delphi V. 1.0. However, the Broker routines on the M server will continue to support V IST A applications previously developed in the 16-bit environment.

The default installation of the Broker creates a separate Broker Development Kit (BDK) directory (i.e., BDK32) that contains the required Broker files for development.


Transition

What's New in V. 1.1 of the BDK

The following items should be noted when transitioning from the 16-bit Broker Development Kit BDK V. 1T11 (i.e., Preview BDK released in October 1995) to the current 32-bit BDK V. 1.1 (i.e., released in September 1997):

The documentation originally released with the preview BDK was not complete. This version of the BDK documentation provides more in-depth information on all properties and methods associated with the TRPCBroker component.

New Properties

The following properties are new with this version of the RPC Broker:

Property

RPCTimeLimit

RPCVersion

Obsolete Properties

The following properties were previously included with the Broker component distributed with the Broker Development Kit (BDK) preview version. These properties are either being phased out or have been removed completely from this version of the Broker because they are now obsolete:

Property Disposition

ConnectMode Being phased out. Slated for removal from the RPC Broker component (i.e., TRPCBroker)

DisconnectMode Being phased out. Slated for removal from the RPC Broker component (i.e., TRPCBroker)

Protocol Removed from this version of the RPC Broker component (i.e., TRPCBroker)

Result Removed from this version of the RPC Broker component (i.e., TRPCBroker)

ServerJob Removed from this version of the RPC Broker component (i.e., TRPCBroker)

New Method

The following method is new with this version of the RPC Broker:

CreateContext

PType Parameters

The wordproc PType in the preview version of the Broker was used to pass text out of memo boxes, for example. However, this version of the Broker now uses list instead of wordproc. Therefore, wordproc is no longer a supported PType.

Client Manager

The Client Manager, previously distributed with version 1.0 of the Broker, is no longer used by this version of the Broker. In version 1.0 of the Broker, the Client Manager provided two types of services:

  1. It was used to invoke the RPCBI.DLL.

  2. It was used by developers to set programmer preferences for using the TRPCBroker component.

By replacing the RPCBI.DLL that was distributed with the RPC Broker V. 1.0 with the BAPI32.DLL, the Client Manager is no longer required with this version of the Broker. Configuration of programmer preferences will now be done via the Broker Programmer Preferences Program

The RPCBI.DLL and Client Manager (i.e., CLMAN.EXE) installed with Broker V. 1.0 must not be removed from the vista/broker directory on the client workstation. They are still required for 16-bit Broker-based applications created using version 1.0 of the Broker (e.g., PCMM).

FileMan Components

Sample 16-bit FileMan (FM) components were originally distributed with the preview version of the RPC Broker Developer Kit released in October of 1995. The 32-bit RPC Broker V. 1.1 is not compatible with the 16-bit FM components. However, the 32-bit FileMan Delphi V. 2.0 components for preview release (i.e., available on the Intranet in January 1997) are compatible with version 1.1 of the Broker.

Please be advised that the FileMan components are no longer distributed with the RPC Broker.

For more information on FileMan components, please go to the following web address:

http://www.vista.med.va.gov/softserv/infrastr.uct/fileman/index.html


Context-Sensitive Help for the TRPCBroker Component

You can install this help file in Delphi such that context-sensitive help is available within Delphi for the TRPCBroker component.

Then you can select any property in the object inspector, press F1, and get help for that property. Also, you can select the TRPCBroker component on a form, press F1, and get help for the component.

Instructions for Delphi 3x

Instructions for Delphi 2x


Installing Context-Sensitive Help for Delphi 3.x

You can merge the help file for the TRPCBroker component into the Delphi help system. Then, when you are working with the TRPCBroker component in Delphi, you can press F1 and get context-sensitive help for it and for any of its properties.

To install this help file in Delphi 3.x:

  1. Delphi 3.x should already be installed on your programmer workstation.

  2. Exit Delphi if is running.

  3. Copy the BROKER.HLP, BROKER.CNT, BROKERSM.HLP and BROKERSM.CNT files (i.e., located in the …\BDK32\DOC directory) into the …\Delphi 3\HELP directory.

  4. Using a text editor, open the DELPHI3.CFG file in the …\Delphi 3\HELP directory. In the "Third-Party Help" section of DELPHI3.CFG, add the following statement:
    :LINK BROKER.HLP

    Save DELPHI3.CFG.

  5. Delete the hidden file DELPHI3.GID in the …\Delphi 3\HELP directory.
    • From Windows Explorer: If you have the option turned on to view hidden files, you can select this file and then delete it.

    • From the command line: Use ATTRIB to change the file attribute to not hidden, then delete the file:

      C:\Program Files\Borland\Delphi 3\HELP>attrib -h delphi3.gid

      C:\Program Files\Borland\Delphi 3\HELP>del delphi3.gid
  6. Start Delphi. On a blank form, add the TRPCBroker component from the component palette to your form. Select the TRPCBroker component on your form and press F1 for help. If the help for the TRPCBroker component comes up, you are all set.


Installing Context-Sensitive Help for Delphi 2.x

Using Delphi's HELPINST application, you can merge the help file for the TRPCBroker component into the Delphi help system. Then, when you are working with the TRPCBroker component in Delphi, you can press F1 and get context-sensitive help for it and for any of its properties.

To install this help file in Delphi 2.x:

  1. Delphi 2.x should already be installed on your programmer client workstation.

  2. Exit Delphi if is running.

  3. Copy the BROKER.CNT, BROKER.HLP, BROKER.KWF, BROKERSM.CNT, and BROKERSM.HLP files (i.e., located in the …\BDK32\DOC directory) into the …\Delphi 2.0\HELP directory.

  4. Run Delphi's HELPINST.EXE program from the …\Delphi 2.0\HELP\TOOLS folder.

  5. Use HELPINST to open the DELPHI.HDX file. From HELPINST's File menu, choose Open. The DELPHI.HDX file is usually located in the \BIN subdirectory below the main DELPHI directory.

  6. Ordinarily, several keyword files should be listed when you open DELPHI.HDX, including DELPHI.KWF and CWG.KWF.

    Do not be concerned if HELPINST reports the files as "* Not Found *".

    If the file BROKER.KWF is listed, click it once to highlight it, and then press HELPINST's red "-" button to delete it. It should now be removed from the list.

  7. Now click HELPINST's green "+" button, to add the BROKER.KWF file to HELPINST's list of .KWF files. You may need to navigate to the \HELP subdirectory of the main Delphi directory to find BROKER.KWF. Once selected, BROKER.KWF should be in HELPINST's list of .KWF files.

  8. Save the updated DELPHI.HDX file. From HELPINST's file menu, choose save. This completes the merging of this help file into Delphi's help.

  9. Exit HELPINST.

  10. Start Delphi. On a blank form, add the TRPCBroker component from the component palette to your form. Select the TRPCBroker component on your form and press F1 for help. If the help for the TRPCBroker component comes up, you are all set.

    However, you may get the message:

    "Cannot find the BROKER.HLP file. Do you want to try to find this file yourself?"

    If you get this message, click YES. Navigate to the \HELP subdirectory of the main Delphi directory, and choose BROKER.HLP and click on the Open button. Windows opens the help file, and the path to the help file should be remembered in the future.

    You can find related information about merging help into Delphi's help in Delphi's Component Writer's Guide manual (Delphi Version 2.0: pp. 77-81).


Orientation

Units

A unit is a Pascal source-code file. The BDK includes a number of units. This help file lists all of the units provided, and details what parts of the BDK are declared in each unit.

Sometimes it is helpful to know in which unit a particular item, such as a type or routine, is declared in the BDK. This is because if you use the item in your own code, you may need to include the corresponding unit in your own Pascal unit's uses clause.

Objects and Components

An object is a data type that wraps up code and data all in one bundle.

A component is an object with additional properties, methods, and events that makes it suitable for specialized purposes.

The BDK includes both objects and components. For each object and component, this help file lists the unit, declaration, properties, and methods, and a description of how to use the object or component.

Routines

Routines can either be functions or procedures. A function returns a value, and a procedure does not.

For topics in this help file describing routines, the unit and declaration for each routine is listed, and a description of the routine is provided.

Types

A type defines the possible range of values for a property or a method. A number of types are declared in the BDK, which you may need to make use of yourself in your own code. For topics in this help file describing types, the unit and declaration for each type is listed, and a description of the type is provided.


TRPCBroker

TRPCBroker Component

Properties Methods Example

Parent Class

TRPCBroker = class(TComponent)

Unit
TRPCB

Description

The TRPCBroker component provides V IST A application developers with all of the client/server-related functionality in one integrated component. Using the TRPCBroker component, an application can connect to the server by simply setting the Connected property to True. Remote procedures on the server can be executed by preparing the Param and RemoteProcedure properties and invoking either the Call, strCall or lstCall methods.

Properties inherited from the parent component (i.e., TComponent) are not discussed in this help file (only those properties added to the parent component are described). For help on inherited properties, please see Delphi's documentation on the parent component (i.e., TComponent).

Please note, a test version (i.e., version 1T11) of the RPC Broker component was previously made available to select users in October 1995 via the RPC Broker Development Kit (BDK). Users of that version of the Delphi component (i.e., TRPCBroker) should be aware that some of the properties, methods, and events found with that version of the Broker component have either been modified or removed from this version of the component because they are obsolete. In addition, new properties, methods, and objects have been added with this latest version of the TRPCBroker component.


EBrokerError

Unit
TRPCB

Description

The EBrokerError is an exception raised by the TRPCBroker component. This exception is raised when an error is encountered when communicating with the server. You should use a try…except block around all server calls to handle any EbrokerError exceptions that may occur.

For example:

try
RPCBroker1.Connected:=True;
except
On EBrokerError do
begin
ShowMessage('Connection to server could not be established!');
Application.Terminate;
end;
end;

For descriptions/resolutions to specific error messages that can be displayed by EBrokerError, please refer to the Broker Error Messages topic.


TParamRecord

TParamRecord Component

Properties Example

Unit
TRPCB

Description

The TParamRecord component is used to hold all of the information on a single RPC parameter. Depending on the type of the parameter needed, different properties are used. The PType property is always used to let the Broker on the server know how to interpret the parameter. For a single value parameter, the Value property should be used. In the case of a list or a word-processing text, use the Mult property.

The TParamRecord relationship to the TRPCBroker component is as follows:

The TRPCBroker component contains the Param property (i.e., TParams component).

The TParams component contains the ParamArray property (array [I:integer]: TParamRecord component).

The TParamRecord component contains the Mult property (i.e., TMult component).

The TMult component contains the MultArray property (array[S: string]: string).

The MultArray property internally uses a TStringList in which each element’s object is a TString.

Developers should rarely have a need to use TParamRecord by itself in their code. TParamRecord is the type of the elements in the ParamArray, default array property of the TRPCBroker component Param property. This means that when you are working with a Param[x] element, you are in reality working with an instance of TParamRecord.


TMult

TMult Component

Properties Methods Example

Unit
TRPCB

Description

The TMult component is used whenever a list of multiple values needs to be passed to a remote procedure call (RPC) in a single parameter. The Mult property of a parameter is of TMult type. The information put in the TMult variable is really stored in a TStringList, but it’s the access methods that are used to read and write that take strings as subscripts and provide the illusion of a string-subscripted array. It’s important to note that items in a TMult component may or may not be sorted. If the Sorted property is False (default), then the elements will be stored in the order they are added. If Sorted is True, items will be stored in ascending alphabetical order by subscripts.

If you attempt to reference an element by a nonexistent subscript you will get an error in form of a Delphi exception. Don’t forget that M syntax dictates that all strings must be surrounded by double quotes. So if your goal is to pass a string subscripted array of strings using TMult as a parameter to an RPC on the M server, don’t forget to surround each of the subscripts and their associated values with double quotes (“). Otherwise, M will assume that you’re passing a list of variables and will attempt to reference them, which is probably not what you want.


TParams

TParams Component

Property Method Example

Unit
TRPCB

Description

The TParams component is used to hold parameters (i.e., array of TParamRecord) used in a remote procedure call (RPC). You don’t need to know in advance how many parameters you’ll need or allocate memory for them. Simple reference or an assignment to a parameter creates it.


Hash Unit

Routines

Encrypt

Decrypt


MFunStr Unit

Routines

piece

translate


RPCConf1 Unit

Routines

GetServerInfo


SplVista Unit

Routines

SplashOpen

SplashClose


TRPCB Unit

The TRPCB unit contains the declarations for the TRPCBroker component.

When you add a component declared in this unit to a form, the unit is automatically added to the uses clause of that form's unit.

The following items are automatically declared in the uses clause:

SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs

Components

TRPCBroker

TParams

TParamRecord

TMult

Types

TParamType

EBrokerError

To see a listing of items declared in this unit including their declarations, use the ObjectBrowser.


RPC Overview

A remote procedure call (RPC) is a defined call to M code that runs on an M server. A client application, through the RPC Broker, can make a call to the M server and execute an RPC on the M server. This is the mechanism through which a client application can:

  • Send data to an M server

  • Execute code on an M server

  • Retrieve data from an M server

An RPC can take optional parameters to do some task and then return either a single value or an array to the client application. RPCs are stored in the REMOTE PROCEDURE file (#8994).

What makes a good RPC?

Creating RPCs

  • M Entry Point for an RPC

    Relationship Between an M Entry Point and an RPC

    M Entry Point First Input Parameter

    M Entry Point Return Value Types

    M Entry Point Input Parameters

    M Entry Point Examples

  • RPC Entry in Remote Procedure File

    RPC Entry in Remote Procedure file

    Cleanup after RPC Execution

    Documenting RPCs

  • Executing RPCs from Clients

How to Execute an RPC from a Client

RPC Security: How to Register an RPC

RPC Limits

Online Code Samples for RPCs


What Makes a Good RPC?

  • Silent calls (no I/O to terminal or screen, no user intervention required)

  • Minimal resources required (passes data in brief, controlled increments)

  • Discrete calls (requiring as little information as possible from the process environment)

  • Generic as possible (different parts of the same package as well as other packages could use the same RPC)


Create Your Own RPCs

Creating RPCs

You can create your own custom RPCs to perform actions on the M server and to retrieve data from the M server. Then you can call these RPCs from your client application. Creating an RPC requires you to perform the following two steps:

  1. Write and test the M entry point that will be called by the RPC.

  2. Add the RPC entry that invokes the M entry point, in the REMOTE PROCEDURE file (#8994).


Relationship Between M Entry Point and RPC

Relationship Between an M Entry Point and an RPC

An RPC can be thought of as a wrapper placed around an M entry point for use with client applications. Each RPC invokes a single M entry point. The RPC passes data in specific ways to its corresponding M entry point, and expects any return values from the M entry point to be returned in a pre-determined format. This allows client applications to connect to the RPC Broker, invoke an RPC, and through the RPC invoke an M entry point on a server.

You can use the $$BROKER^XWBLIB function in M code to determine whether the code is being run in an environment where it was invoked by the Broker. This may help you use M code simultaneously for Broker and non-Broker applications.


RPC First Input Parameter

First Input Parameter (Required)

The RPC Broker always passes a variable by reference inthe first input parameter to your M routine. It expects results (one of five return value types) to be returned in this parameter. You must always set some return value into that first parameter before your routine returns.


RPC Return Value Types

Return Value Types

There are five RETURN VALUE TYPES for RPCs as shown in the table below. You should choose a return value type that is appropriate to the type of data your RPC needs to return. For example, to return the DUZ, a return value type of SINGLE VALUE would be appropriate.

The RETURN VALUE TYPE you choose then determines what value(s) you should set into the return value parameter of your M entry point.

You should always set some value into the return value parameter of the M entry point, even if your RPC encounters an error condition.

The following RPC settings, combined with your M entry point, determine how data is returned to your client application:

RPC Return
Value Type

How M Entry Point Should
Set the Return Parameter 		RPC Word Wrap On Setting

Value(s) returned in Client Results
Single Value
Set the return parameter to a single value. For example,
TAG(RESULT) ;
 S RESULT="DOE, JOHN"
 Q
 No effect Value of parameter, in Results[0].
Array Set an array of strings into the return parameter, each subscripted one level descendant. For example,
TAG(RESULT) ;
 S RESULT(1)="ONE"
 S RESULT(2)="TWO"
 Q

If your array is large, consider using the GLOBAL ARRAY return value type, to avoid memory allocation errors.

 No effect Array values, each in a Results item.
Word Processing Set the return parameter the same as you set it for the ARRAY type. The only difference is that the WORD WRAP ON setting affects the WORD PROCESSING return value type. True

False

 Array values, each in a Results item.

Array values, all concatenated into Results[0].
Global Array Set the return parameter to a closed global reference in ^TMP. The global's data nodes will be traversed using $QUERY, and all data values on global nodes descendant from the global reference are returned.

This type is especially useful for returning data from VA FileMan word processing fields, where each line is on a 0-subscripted node.

Important: The global reference you pass is killed by the Broker at the end of RPC Execution as part of RPC cleanup. Do not pass a global reference that is not in ^TMP or that should not be killed.

This type is useful for returning large amounts of data to the client, where using the ARRAY type can exceed the symbol table limit and crash your RPC.

For example, to return signon introductory text you could do:

TAG(RESULT);
 M ^TMP("A6A",$J)=
^XTV(8989.3,1,"INTRO")
 ;this node not needed
 K ^TMP("A6A",$J,0)
 S RESULT=$NA(^TMP("A6A",$J))
 Q
 True

False

 Array values, each in a Results item.

Array values, all concatenated into Results[0].
Global Instance Set the return parameter to a closed global reference.
For example the following code returns the whole 0th node from the NEW PERSON file for the current user:
TAG(RESULT) ;
 S RESULT=$NA(^VA(200,DUZ,
0))
 Q
No effect Value of global node, in Results[0].

In the M code called by an RPC, you can use the $$RTRNFMT^XWBLIB function to change the return value type of an RPC on the fly.


RPC Input Parameter Types

Input Parameters (Optional)

The M entry point for an RPC can optionally have input parameters (i.e., beyond the first parameter, which is always used to return an output value in). The client passes data to your M entry point through these parameters.

The client can send data to an RPC (and therefore your entry point) in one of the following three Param types:

Param PType | Param Value
literal | Delphi string value, passed as a string literal to the M server.
reference | Delphi string value, treated on the M Server as an M variable name and resolved from the symbol table at the time the RPC executes.
list | A single-dimensional array of strings in the Mult property of the Param property, passed to the M Server where it is placed in an array. String subscripting can be used.

The type of the input parameters passed in the Param property of the TRPCBroker component determines the format of the data you must be prepared to receive in your M entry point.


RPC M Entry Point Examples

Examples

The following two examples illustrate sample M code that could be used in simple RPCs.

  1. This example takes two numbers and returns their sum:
    SUM(RESULT,A,B)	;add two numbers
 S RESULT=A+B
 Q
  2. This example receives an array of numbers and returns them as a sorted array to the client:
    SORT(RESULT,UNSORTED)	;sort numbers
 N I
 S I=""
 F  S I=$O(UNSORTED(I)) Q:I=""  S RESULT(UNSORTED(I))=UNSORTED(I)
 Q


RPC Entry in the REMOTE PROCEDURE File

After the M code is complete, you need to add the RPC to the REMOTE PROCEDURE file (#8994). The following fields in the REMOTE PROCEDURE file (#8994) are key to the correct operation of an RPC:

Field Name | Required? | Description
NAME (#.01) | Yes | The name that identifies the RPC (this entry should be namespaced in the package namespace).
TAG (#.02) | Yes | The tag at which the remote procedure call begins.
ROUTINE (#.03) | Yes | The name of the routine which should be invoked to start the RPC.
WORD WRAP ON (#.08) | No | Affects GLOBAL ARRAY and WORD PROCESSING return value types only. If set to False, all data values are returned in a single concatenated string in Results[0]. If set to True, each array node on the M side is returned as a distinct array item in Results.
RETURN VALUE TYPE (#.04) | Yes | This can be one of five types: SINGLE VALUE, ARRAY, WORD PROCESSING, GLOBAL ARRAY, GLOBAL INSTANCE. This setting controls how the Broker processes an RPC's return parameter.


Cleanup after RPC execution?

The Broker uses XUTL^XUSCLEAN to clean up globals upon application termination.

In addition, there is an RPC return value type, GLOBAL ARRAY, where the application RPC returns a closed form global reference, for example:

^TMP("EKG",220333551)

The Broker kills the data for the global reference for this type of RPC at the end of RPC execution.


Documenting RPCs

Each individual application development team is responsible for identifying and providing documentation for all object components, classes, and remote procedure calls they create. Other developers using these components will need to know what RPCs are called because they will need to register them with their applications.

RPCs should be documented in the DESCRIPTION field (#1) in the REMOTE PROCEDURE file (#8994) for those RPCs installed on your system. This gives you the capability of generating a catalog of RPCs from File #8994.

Delphi Component Library and Sample RPCs

The Technical Integration unit of V IST A Software Development will make available a corporate library of object components, classes, and remote procedure calls that are in use and available to the development community at large. The essential benefit of this library is the promotion of object re-use, thereby enhancing development productivity, application consistency, and quality assurance. Therefore, it will contain a wide variety of components, classes, and RPCs from many packages.

The immediate intent is to classify and catalog all of the object classes in use (including the standard Delphi classes), and to make the catalog available to all interested parties via the V IST A Software Development Home Page:

http://www.vista.med.va.gov


How to Execute an RPC from a Client Application

How to Execute an RPC from a Client

  1. If your RPC has any input parameters beyond the mandatory first parameter, set a Param node in the TRPCBroker's Param property for each. For each input parameter, set the following subproperties:
    • Value

    • PType (literal, list, or reference).

    If the parameter's PType is list, however, instead of specifying a value, instead set a list of values in the Mult property.

    Here is an example of some settings of the Param property:
    RPCBroker1.Param[0].Value := '10/31/97';
RPCBroker1.Param[0].PType := literal;
RPCBroker1.Param[1].Mult['"NAME"'] := 'SMITH, JOHN';
RPCBroker1.Param[1].Mult['"SSN"'] := '123-45-6789';
RPCBroker1.Param[1].PType := list;
  2. Set the TRPCBroker's RemoteProcedure property to the name of the RPC to execute.
    RPCBroker1.RemoteProcedure:='A6A LIST';
  3. Invoke the Call method of the TRPCBroker component to execute the RPC. All calls to the Call method should be done within an exception handler try...except statement, so that all communication errors (which trigger the EBrokerError exception) can be trapped and handled. For example:
    try
    RPCBroker1.Call;
except
  On EBrokerError do
    ShowMessage('A problem was encountered communicating with the server.');
end;
  4. Any results returned by your RPC are returned in the TRPCBroker component's Results property. Depending on how you set up your RPC, results are returned either in a single node of the Results property (Results[0]), or in multiple nodes of the Results property.

You can also use the lstCall and strCall methods to execute an RPC. The main difference between these methods and the Call method is that lstCall and strCall do not use the Results property, instead returning results into a location you specify.


RPC Security: How to Register an RPC

Security for RPCs is handled through the RPC registration process. Each client application must create a context for itself, which checks if the application user has access to a "B"-type option in the Kernel menu system. Only RPCs assigned to that option can be run by the client application.

To enable your application to create a context for itself:

  1. Create a "B"-type option in the OPTION file (#19) for your application.

    The OPTION TYPE "B" represents a Broker client/server type option.

  2. In the RPC multiple for this option type, add an entry for each RPC that your application calls. The following fields can be set up for each RPC in your option:

    Field Name | Entry | Description
    RPC (#.01) | Required | This field is used to enter a pointer to the REMOTE PROCEDURE file (#8994). This field links the remote procedure call in the REMOTE PROCEDURE file (#8994) to the package option.
    RPCKEY (#1) | Optional | This field is used to restrict the use of a remote procedure call to a particular package option. The RPCKEY field is a free-text pointer to the SECURITY KEY file (#19.1).
    RULES (#2) | Optional | This field is used to enter M code that is executed when an RPC request is made to verify whether the request should be honored.

  3. When you export your package using KIDS, export both your RPCs and your package option. KIDS will automatically associate the RPCs with the package option.

  4. Your application must create a context for itself on the server, which checks access to RPCs. In the initial code of your client application, make a call to the CreateContext method of your TRPCBroker component. Pass your application's "B"-type option's name as a parameter. For example:
    if not RPCBroker1.CreateContext(option_name) then
  Application.Terminate;

    If the CreateContext method returns True, only those RPCs designated in the RPC multiple of your application option will be permitted to run.

    If the CreateContext method returns False, you should terminate your application (if you don't your application will run, but you will get errors every time you try to access an RPC).

  5. End-users of your application must have the "B"-type option assigned to them on one of their menus, in order for CreateContext to return True. This allows system managers to control access to client applications.

Bypassing RPC Security for Development

Having the XUPROGMODE security key allows you to bypass the Broker security checks. You can run any RPC without regard to application context (without having to use the CreateContext method). This is a convenience for when you are developing an application. When you complete development, make sure you test your application from an account without the XUPROGMODE key, to ensure that all RPCs needed are properly registered.


RPC Limits

The following is a list of various constants, maximum, and minimum parameters associated with the use of the RPC Broker:

Max. No. of parameters which can be passed to the M server

Max. size of array which can be passed to the M server

Max. size of data which can be received in the Windows app. from the M server

RPC Time limit


BrokerExample Online Code Example

The BrokerExample sample application provided with the BDK demonstrates the basic features of developing RPCBroker applications, including:

  • Connecting to an M server

  • Creating an application context

  • Using the GetServerInfo function

  • Displaying the V IST A splash screen

  • Setting the TRPCBroker.Param property for each Param PType (literal, reference, list)

  • Calling RPCs with the Call method

  • Calling RPCs with the lstCall and strCall methods

The client source code files for the BrokerExample application are located in the SAMPLES\BROKEREX subdirectory of the main BDK32 directory.


Other APIs Overview

Other RPC Broker APIs

The Broker Development Kit provides the following development APIs in addition to the TRPCBroker component:

GetServerInfo Function

VISTA Splash Screen Procedures

XWB GET VARIABLE VALUE RPC

M Emulation Functions

Encryption Functions

The RPC Broker package provides the following entry points on the server for use in RPC code:

$$BROKER^XWBLIB (Determine if running from a Broker call)

$$RTRNFMT^XWBLIB (Change return format of RPC)


GetServerInfo Function

Example

The GetServerInfo function retrieves the end-user's selection of server and port to which to connect. Use this function to set a TRPCBroker component's Server and ListenerPort properties to reflect the end-user's choice before connecting to the server.

If there is more than one server/port to choose from, GetServerInfo displays an application window that allows users to select a service to connect to:

Syntax:

function GetServerInfo(var Server, Port: string): integer;

The unit is RpcConf1.

The GetServerInfo function handles the following scenarios:

  • If there are no values for server and port in the Windows Registry, GetServerInfo does not display its dialog window, and the automatic default values returned are BROKERSERVER/9200. GetServerInfo returns mrOK.

  • If exactly one server and port entry is defined in the Windows Registry, GetServerInfo does not display its dialog window. The values in the single Windows Registry entry are returned to the calling application, with no user interaction. GetServerInfo returns mrOK.

  • If more than one server and port entry exists in the Windows Registry, the dialog window is displayed. The only time that passed in server and port values will be returned to the calling application is if the user presses Cancel. However, if a user selects an entry and clicks on the OK button, the server and port parameters will be changed and returned to the calling application. GetServerInfo returns mrOK if the user pressed the OK button, or mrCancel if the user pressed the Cancel button.


Splash Screen Procedures

VISTA Splash Screen Procedures

Example

Two procedures in SplVista.PAS unit are provided to display a V IST A splash screen when an application loads:

procedure SplashOpen;
procedure SplashClose(TimeOut: longint);

It is recommended that the V IST A splash screen be opened and closed in the section of pascal code in an application's project file (i.e., .DPR).

To use the V IST A splash screen in an application:

  1. Open your application's project (.DPR) file (in Delphi, choose View | Project Source).

  2. Include the SplVista in the uses clause of the project source.

  3. Call SplashOpen immediately after the first form of your application is created and call SplashClose just prior to invoking the Application.Run method.

  4. Use the TimeOut parameter to ensure a minimum display time. The TimeOut parameter is the minimum number of milliseconds the screen will be shown.

The V IST A splash screen is illustrated below:


XWB GET VARIABLE VALUE RPC

Example

You can call the XWB GET VARIABLE VALUE RPC (distributed with the RPC Broker) to retrieve the value of any M variable in the server environment. Pass the variable name in Param[0].Value, and the type (reference) in Param[0].PType. Also, the current context of your user must give them permission to execute the XWB GET VARIABLE VALUE RPC (it must be included in the RPC multiple of the "B"-type option registered with the CreateContext function).


M Emulation Functions

Examples

Piece Function

The Piece function is a scaled down Pascal version of M's $PIECE function. It is declared in MFUNSTR.PAS.

function Piece(x: string; del: string; piece: integer) : string;

Translate Function

The Translate function is a scaled down Pascal version of M's $TRANSLATE function. It is declared in MFUNSTR.PAS.

function Translate(passedString, identifier, associator: string): string;


Encryption Functions

Kernel and the RPC Broker provide encryptions functions that can be used to encrypt messages sent between the client and the server.

In Delphi

Include HASH in the "uses" clause of the unit in which you'll be encrypting or decrypting.

Function prototypes are as follows:

function Decrypt(EncryptedText: string): string;
function Encrypt(NormalText: string): string;

On the M Server

To encrypt:

KRN,KDE>S CIPHER=$$ENCRYP^XUSRB1("Hello world!") W CIPHER
/U'llTG~TVl&f-

To decrypt:

KRN,KDE>S PLAIN=$$DECRYP^XUSRB1(CIPHER) W PLAIN
Hello world!

These encryption functions can be used for any communication between the client and the server where encryption is desired.


$$BROKER^XWBLIB

Use this function in the M code called by an RPC to determine if the current process is being executed by the Broker.

Format

$$BROKER^XWBLIB

Input

(none)

Output

Return Value 1 if the current process is being executed by the Broker; 0 if not.

Example

I $$BROKER^XWBLIB D
.; broker-specific code


$$RTRNFMT^XWBLIB

Use this function in the M code called by an RPC to change the return value type that the RPC will return on the fly.

Format

$$RTRNFMT^XWBLIB(type, wrap)

Input

type Set this to the RETURN VALUE TYPE to change the RPC's setting to. You can set it to one of the following numeric or free text values:

numeric free text

1 SINGLE VALUE

2 ARRAY

3 WORD PROCESSING

4 GLOBAL ARRAY

5 FOR GLOBAL INSTANCE

wrap Set to 1 to set the RPC's WORD WRAP ON setting to True; set to 0 to set the RPC's WORD WRAP ON setting to False.

Output

Return Value 0 if the return value type could not be changed; otherwise, the numeric code representing the return value type that the RPC is changed to.

Example

I '$$RTRNFMT^XWBLIB("ARRAY",1) D
.; branch to code if can't change RPC type


Debugging and Troubleshooting Overview

The Broker Development Kit provides facilities for debugging and troubleshooting your applications.

How to Debug Your Application

Identifying the Listener Process

Identifying the Handler Process

RPC Error Trapping

Testing Your RPCBroker Connection

Memory Leaks

Client Timeout and Buffer Clearing

Broker Errors


Debug

How to Debug Your Application

Beside the normal debugging facilities provided by Delphi, you can also invoke a debug mode so that you can step through your code on the client side and your RPC code on the M server side simultaneously.

To do this:

  1. On the client side, set the DebugMode property on the TRPCBroker component to True. When the TRPCBroker component connects with this property set to True, you will get a dialog window indicating your workstation IP address and the port number.

  2. At this point, switch over to the M server, and set any break points in the routines being called in order to help isolate the problem. Then issue the M debug command (e.g., ZDEBUG in DSM).

  3. Start the following server process:
    >D EN^XWBTCP

    You will be prompted for the workstation IP address and the port number. After entering the information, switch over to the client application and click on the OK button of the dialog window.

  4. You can now step through the code on your client, and simultaneously step through the code on the server side for any RPCs that your client calls.


ID Listener

Identifying the Listener Process on the Server

On DSM systems, where the Broker Listener is running, the Listener process name is RPCB_Port:NNNN, where NNNN is the port number being listened to. This should help quickly locate Listener processes when troubleshooting any connection problems.


ID Handler

Identifying the Handler Process on the Server

On DSM systems the name of a Handler process is ipXXX.XXX:NNNN, where XXX.XXX are the last two octets of the client IP address and NNNN is the port number.


Error Handling

RPC Error Trapping

M errors on the server that occur during RPC execution are trapped by the use of M and Kernel error handling. In addition, the M error message is sent back to the Delphi client. Delphi will raise an exception EBrokerError and a popup box displaying the error. At this point RPC execution terminates and the channel is closed.

In some instances, an application's RPC could get a memory allocation error on the server (in DSM an "allocation failure"). Kernel does not trap these errors. However, these errors are trapped in the operating system's error trap. For example, if an RPC receives or generates an abundance of data in local memory, the symbol table could be depleted resulting in a memory allocation error. To diagnose this problem, users should check the operating system's error trap.


Testing Connection

Testing Your RPC Broker Connection

To test the RPC Broker connection from your workstation to the M server, use the RPC Broker Diagnostic Program (i.e., RPCTEST.EXE)

For a complete description of the RPC Broker Diagnostic program, please refer to Chapter 4, "Troubleshooting," in the RPC Broker Systems Manual.


Memory Leaks

A good indication of a memory leak is when a running program is steadily decreasing the free pool of memory. As it runs or every time the program is started and stopped, free memory is steadily decreased.

Specifically, a program requests some bytes of memory from the Windows Operating System (OS). When the OS provides it, it marks those bytes as taken. The free pool of memory (i.e., unmarked bytes) is decreased. When the program is finished with the memory, it should return the memory back to the OS by calling the FREE or DISPOSE functions. This allows the OS to clear the "taken" status of that memory, thereby replenishing its free pool. When a programmer forgets to free the memory after use or the program fails before it has a chance to execute the code that frees the memory, the memory is not reclaimed.

At all times, the program should keep track of which memory it's using. It does this by storing "Handles" (i.e., memory addresses of the beginning byte of each memory block). Later, when freeing memory, the Handle is used to indicate which memory address to free. If the variable that holds such a Handle is overwritten, there is no way to determine the Handle.

Nine out of ten times, memory leakage can be traced back to the application code that requests memory and then forgets to return it or cannot clean up after a crash.

As common with other professional-level languages (e.g., C/C++), Delphi has constructs which applications can use to: request memory, type cast it, and return it. This requires developers to use their best judgement on how to best work with the system memory.

Avoiding memory leaks (and the often-subtle coding errors that lead to them) is a challenge for Delphi programmers, especially for those whose main experience is working with M.

The insidious effect of these leaks (e.g., gobbling up 1K of memory each time that a certain event occurs) makes them difficult to detect with normal program testing. By "normal testing" we mean exercising all the possible paths through the code once, a difficult enough process in a Windows environment. Often, these leaks will result in a symptom only under peculiar conditions (e.g., several other applications are running, reducing system resources) or only after extended use of the application (e.g., Do you notice that Windows problems crop up in the afternoon, even though you were doing the same thing that morning?).

The symptom that we are most likely to hear about from users is the following:

"My computer was working fine until I installed the XYZ V IST A package on my PC. Now, it freezes up (gives me error message, says it's out of memory, etc.) all the time, even when I am not using the XYZ package. No, I can't duplicate it, it just happens!"

One of the reasons that there is an extensive market for automated testing tools for Windows and client-server applications is that thorough testing is very difficult to do manually.

Fortunately, there are diagnostic products available for detecting code that will cause memory leaks. It will help programmers and code reviewers to find these leaks. Its use by people just starting out in Delphi programming will help them identify the situations that cause memory leaks. This can serve as a good learning experience for the new Delphi developer.

No application is immune from memory leaks, careful analysis of previous Broker code revealed some places where, under certain conditions, memory was not being released after it was used (i.e., memory leaks). These areas have been identified and corrected with this version of the Broker.


Buffer Clearing

Client Timeout and Buffer Clearing

If a remote procedure call fails to successfully complete due to a timeout on the client, the buffer on the server would contain data from the uncompleted call. Without special handling, this buffer on the server would be returned whenever the next RPC was executed.

The solution to this problem is:

  1. The new RPCTimeLimit property on the TRPCBroker component on the client helps avoid the problem in the first place.

  2. In the event of a cancellation of a Network I/O operation, the Broker state on the client changes from NO FLUSH to FLUSH. When this state change occurs, the next RPC executed undergoes a read operation prior to execution where any leftover incoming buffer is discarded. At the end of this operation, the Broker state on the client will return to NO FLUSH and the RPC will execute normally. While the FLUSH state exists, users may experience a delay while the corrupted RPC data is discarded. The delay will be proportional to the amount of data in the buffer.


Broker Programmer Preference Editor

RPC Broker Programmer Preference Editor

You can use the RPC Broker Programmer Preference Editor (BrokerProgPref.exe) to define certain default property values for the TRPCBroker component. When you add a TRPCBroker component to a Delphi application, the settings you define in the Programmer Preference Editor are used as the default property values.

Click on part of the Broker Programmer Preference Editor screen below for information on that setting.

You may want to make an entry for BrokerProgPref.exe in Delphi's Tools Menu, to make it easily accessible from within Delphi.


Tutorial Introduction

TRPCBroker Component Tutorial Introduction

The major functions of a TRPCBroker component in a Delphi application are to:

  • Connect to an RPC Broker server system from a client.

  • Execute remote procedure calls (RPCs) on that system.

  • Return data results from RPC to the client.

This tutorial guides you through using a TRPCBroker component to perform each of these tasks, by having you create a Delphi application, step-by-step. This application will retrieve a list of terminal types from the server, and display information about each terminal type.

After you have completed this tutorial, you should be able to:

  • Include a TRPCBroker component in a Delphi application.

  • Retrieve the end-user workstation's designated server and port to connect to.

  • Establish a connection through the RPC Broker component to an RPC Broker server.

  • Create M routines that return data in the formats necessary to be called from RPCs.

  • Create RPCs.

  • Call RPCs from a Delphi application to retrieve data from V IST A database.

  • Pass parameters from your Delphi application to RPCs.


Tutorial Advance Preparation

Advance Preparation

Namespacing of Routines and RPCs

Each tutorial user should choose a unique namespace beginning with Z, concatenated with two or three other letters, for example ZYXU. Use this namespace as the beginning of the names for all routines and RPCs that you create during this tutorial. Using your namespace protects the system you are using from having existing routines and RPCs overwritten. This namespace is referred to as Zxxx during the tutorial.

Tutorial Prerequisites

To use this tutorial:

  • You should already have M programming skills, and some familiarity with Delphi.

  • You must have Delphi and the Broker Development Kit installed on your workstation.

  • Your workstation must have network access to an M account that is running a Broker server process.

  • You must have programmer access in this M account, and it should be a test account (not production). Also, you need the XUPROGMODE key assigned to your user account.


Tutorial Step 1

Step 1. Create Application with a TRPCBroker Component

The first step of this tutorial is to create a Delphi application that includes a TRPCBroker component.

To do this:

  1. In Delphi, create a new application. Delphi will create a blank form, named Form1.

  2. Set Form1's Caption property to Terminal Type Display.

  3. From the Kernel component palette tab, add a TRPCBroker component to your form. The instance of the component should automatically be named RPCBroker1.

  4. Leave the default values for Server and ListenerPort as is (they are retrieved from your workstation's Registry). In the next section of the tutorial, you will add code to retrieve these values at run-time from the workstation's Registry.

  5. Set the ClearParameters and ClearResults properties to True if they are not set to True already. This ensures that each time a call to an RPC is made, the Results property is cleared beforehand, and the Param property is cleared afterwards.

    Your form should look like:

The next tasks are to use the TRPCBroker component to retrieve the end-user workstation's RPC Broker server and port information, and then to establish a connection through the TRPCBroker component to the M server.


Tutorial Step 2

Step 2. Get Server/Port

The TRPCBroker component you've added to your form is hard coded to access the Broker server and listener port that it picks up from your own (developer) workstation (by default, BROKERSERVER and 9200). Naturally you don't want this to be the only server and port that your application can connect to. To retrieve the end-user workstation's designated Broker server and port to connect to, as stored in their Registry, you can use the GetServerInfo function.

To retrieve the end-user workstation's designated server and port:

  1. Include the RPCConf1 unit in your Pascal file's uses clause. This is the unit that GetServerInfo is a part of.

  2. Double-click on a blank region of the form. This creates an event handler procedure, TForm1.FormCreate, in your Pascal source code.

  3. Add code to the FormCreate event handler that retrieves the correct server and port to connect to, using the GetServerInfo function. If mrCancel is returned, your code should quit. Otherwise, your code should then set RPCBroker1's Server and ListenerPort properties to the returned values.
    The code should should look like the following:
    procedure TForm1.FormCreate(Sender: TObject);
var   ServerStr: String;
        PortStr: String;
begin
// get the correct port and server from Registry
  if GetServerInfo(ServerStr,PortStr)<> mrCancel then
  begin
    RPCBroker1.Server:=ServerStr;
    RPCBroker1.ListenerPort:=StrToInt(PortStr);
  end {connectOK}
  else
    Application.Terminate;
end;

Now that you have code to retrieve the appropriate RPC Broker server and listener port, in the next section of the tutorial your application will use the TRPCBroker component to establish a connection to the server.


Tutorial Step 3

Step 3. Establish Broker Connection

Now that your application can determine the appropriate RPC Broker server and port to connect to, you can add code to establish a connection to the designated RPC Broker server from your application. The act of establishing a connection leads the user through signon. If signon succeeds, a connection is established.

To establish a connection from your application to a RPC Broker server:

  1. Add code to Form1's OnCreate event handler. The code should:

    a. Set RPCBroker1's Connected property to True (inside of an exception handler try...except block). This will cause an attempt to connect to the RPC Broker server.

    b. Check if an EBrokerError exception is raised. If this happens, connection failed, and your code should inform the user of this and terminate the application.

    The OnCreate event handler should now look like:

    procedure TForm1.FormCreate(Sender: TObject);
var   ServerStr: String;
        PortStr: String;
begin
  // get the correct port and server from Registry
  if GetServerInfo(ServerStr,PortStr)<> mrCancel then
  begin {connectOK}
    RPCBroker1.Server:=ServerStr;
    RPCBroker1.ListenerPort:=StrToInt(PortStr);
    // establish a connection to the RPC Broker server
    try
      RPCBroker1.Connected:=True;
    except
      On EBrokerError do
      begin {error}
        ShowMessage('Connection to server could not be established!');
        Application.Terminate;
      end; {error}
    end; {try}
  end {connectOK}
  else
    Application.Terminate;
end;

    Note Every call that invokes an RPC Broker server connection should be done in an "exception handler" try...except block, so that EBrokerError exceptions can be trapped.

  2. Save, compile and run your application. It should connect to the M server returned by the GetServerInfo function. You may be prompted to sign on with access and verify codes (unless single signon is enabled, and you are already signed on). If you can connect successfully, your application will run (at this point, it is just a blank form). Otherwise, troubleshoot your RPC Broker connection until you can get your application to connect.

  3. If the server system defined in your Registry is not your development system (the one on which you will create RPCs for this application), update your Registry using the SERVERLIST.EXE program so that your application will connect to the proper M server.

Now that your application can establish a connection to the end-user's server system, you can go about retrieving data from the server system. In the next steps of the tutorial, you will create a custom RPC that retrieves a list of all of the terminal types on the server system, and call that RPC from your application.


Tutorial: Step 4

Step 4. RPC Routine to List Terminal Types

Now that your application uses an RPC Broker component to connect correctly to an RPC Broker server, you are ready to create custom RPCs that your application can call. For the tutorial, you will create an RPC that retrieves the list of all terminal types from the RPC Broker server.

The first step in creating an RPC is to create the routine that the RPC will execute. You must create its input and output in a defined format that will be compatible with being executed as an RPC.

To do this:

  1. Choose the data format that your RPC should return. The type of data that you need to return to your client application determines the format of the routine that your RPC will call. There are five return value types for RPCs:
    • SINGLE VALUE

    • ARRAY

    • WORD PROCESSING

    • GLOBAL ARRAY

    • GLOBAL INSTANCE

    Since the type of data the tutorial application would like returned is a list of terminal types, and that list could be quite long, use a return value type GLOBAL ARRAY for your RPC. For the routine called by your RPC, this means that:

    • Your routine should return a list of terminal types in a global. Each terminal type should be on an individual data node, subscripted numerically.

    • The return value of your routine (always returned in the routine's first parameter) should be the global reference of the data global, in closed root form. The data nodes should be one level descendant from the global reference.
  2. Create a routine, in the M account that your TRPCBroker component connects to, that outputs a list of terminal types in the format determined above. The format for each data node that is returned for a terminal type could be anything; for the sake of this application, set each data node to "ien^.01 field" for the terminal type in question. Store each node in ^TMP($J,"ZxxxTT",#).
    ZxxxTT   ;ISC-SF/KC TUTORIAL RTN, BRK 1.1; 7/22/97
 ;;1.0;;
TERMLIST(GLOBREF) ; retrieve list of term types
 ; return list in ^TMP($J,"ZxxxTT")
 ; format of returned results: ien^.01 field
 N %                               ; scratch variable
 K ^TMP($J,"ZxxxTT")               ; clear data return area
 D LIST^DIC(3.2)                   ; retrieve list of termtype entries
 ; now set termtype entries into data global
 I '$D(DIERR) D
 .S %=0 F  S %=$O(^TMP("DILIST",$J,2,%)) Q:%=""  D
 ..S ^TMP($J,"ZxxxTT",%)=$G(^TMP("DILIST",$J,2,%))_"^"_$G(^TMP("DILIST",$J,
1,%))
 K ^TMP("DILIST",$J)               ; clean up
 S GLOBREF=$NA(^TMP($J,"ZxxxTT"))   ; set return value
 Q
  3. Test the routine. Call it like the Broker would:
    > D TERMLIST^ZxxxTT(.RESULT)

    a. Confirm that the return value is the correct global reference:

    > W RESULT

  ^TMP(566363396,"ZxxxTT")

    b. Confirm that the data set into the global is in the following format:

    ^TMP(566347920,"ZxxxTT",1) = 1^C-3101
^TMP(566347920,"ZxxxTT",2) = 2^C-ADDS
^TMP(566347920,"ZxxxTT",3) = 3^C-ADM3
^TMP(566347920,"ZxxxTT",4) = 38^C-DATAMEDIA
^TMP(566347920,"ZxxxTT",5) = 106^C-DATATREE
^TMP(566347920,"ZxxxTT",6) = 4^C-DEC
^TMP(566347920,"ZxxxTT",7) = 5^C-DEC132
^TMP(566347920,"ZxxxTT",8) = 93^C-FALCO
^TMP(566347920,"ZxxxTT",9) = 6^C-H1500
^TMP(566347920,"ZxxxTT",10) = 103^C-HINQLINK
^TMP(566347920,"ZxxxTT",11) = 132^C-HINQLINK
^TMP(566347920,"ZxxxTT",12) = 63^C-HP110
^TMP(566347920,"ZxxxTT",13) = 34^C-HP2621

Once you've tested your routine, and confirmed that it returns data correctly, the next step is to create the RPC that will call this routine.


Tutorial: Step 5

Step 5. RPC to List Terminal Types

Now that you've created an RPC-compatible routine to list terminal types, you can go ahead and create the RPC itself (the entry in the REMOTE PROCEDURE file) that will call the routine.

To create an RPC that uses the TERMLIST^ZxxxTT routine:

  1. Using VA FileMan, create a new RPC entry in the REMOTE PROCEDURE file. Set up the RPC as follows:
                 NAME: ZxxxTT LIST
              TAG: TERMLIST
          ROUTINE: ZxxxTT
RETURN VALUE TYPE: GLOBAL ARRAY
     WORD WRAP ON: TRUE
      DESCRIPTION: Used in RPC Broker developer tutorial.

    The RPC's RETURN VALUE TYPE is set to GLOBAL ARRAY. This means that the RPC expects a return value that is a global reference (with data stored at that global reference).

    Also, the RPC's WORD WRAP ON is set to TRUE. This means each data node from the M server is returned as a single node in the Results property of your TRPCBroker component in Delphi. Otherwise, the data would be returned concatenated into a single node in the Results property.

In the next step of the tutorial, you will call this RPC from the tutorial application, through its TRPCBroker component.


Tutorial Step 6

Step 6. Call the ZxxxTT LIST RPC

Now that you have created and tested the ZxxxTT LIST RPC on the M server system, you can use your Delphi application's TRPCBroker component to call that RPC.

To call the ZxxxTT LIST RPC from your Delphi application to populate a list box:

  1. Place a TListBox component on your form. It should be automatically named ListBox1.
    • Size it so that it uses the full width of the form, and half of the form's height.
  2. Place a button beneath ListBox1.
    • Set its caption to 'Retrieve Terminal Types'.

    • Size the button so that it is larger than its caption.
  3. Double-click on the button. This creates an event handler procedure, TForm1.Button1Click, in your Pascal source code.

  4. In the TForm1.Button1Click event handler, add code to call the ZxxxTT LIST RPC and populate the list box with the retrieved list of terminal type entries. This code should:

    a. Set RCPBroker1's RemoteProcedure property to ZxxxTT LIST.

    b. Call RPCBroker1's Call method (in a try...except exception handler block) to invoke that RPC.

    c. Retrieve results from RPCBroker1's Results property, setting them one-by-one into the list box's Items property.

    This code should look as follows:

    Procedure TForm1.Button1Click(Sender: TObject);
var
   i:integer;
begin
  RPCBroker1.RemoteProcedure:='ZxxxTT LIST';
  try
    begin {call}
      RPCBroker1.Call;
      for i:=0 to (RPCBroker1.Results.Count-1) do
        ListBox1.Items.Add(piece(RPCBroker1.Results[i],'^',2));
    end; {call}
  except
    On EBrokerError do
      ShowMessage('A problem was encountered communicating with the server.');
  end; {try}

    end;

  5. Include the mfunstr unit in the Uses clause of your project's Pascal source file. This enables your application to use the piece function included in mfunstr.

  6. Your user account must have XUPROGMODE key assigned. This allows your application to execute any RPC, without the RPC being registered. Later in the tutorial you will register your RPCs.

  7. Now run your application, and press the Retrieve Terminal Types button. It should retrieve and display terminal type entries, and appear as follows:

Now that you can retrieve a list of terminal type entries, the next logical task is to retrieve a particular entry when a user selects that entry in the list box.


Tutorial Step 7

Step 7. Associate Iens with List Box Items

When a user selects a terminal type entry in the list box, a typical action would be to retrieve the corresponding record and display its fields. The key to retrieving any VA FileMan record is knowing the ien of the record. So when a user selects an entry in the list box, you need to know the ien of the corresponding VA FileMan entry. However, the list box items themselves only contain the name of each entry, not the ien.

The subscripting of items in the list box still matches the original subscripting of items returned in RPCBroker1's Results property, as performed by the following code in Button1Click event handler:

for i:=0 to (RPCBroker1.Results.Count-1) do

ListBox1.Items.Add(piece(RPCBroker1.Results[i],'^',2));

If no further calls to RPCBroker1 were made, you could simply refer back to RPCBroker1's Results[x] item to obtain the matching ien of a list boxes' Items[x] item. But, since RPCBroker1 will be used again, the Results property will be cleared. So the results must be saved off in another location, if you want to be able to refer to them after other Broker calls are made.

To save off the Results to another location:

  1. Create a variable named TermTypeList, of type TStrings. This is where RPCBroker1.Results will be saved off to. Create the variable in the section of code where TForm1 is defined as a class:
    type
  TForm1 = class(TForm)
    RPCBroker1: TRPCBroker;
    ListBox1: TListBox;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    TermTypeList: TStrings; // Added declaration of TermTypeList
  end;
  2. In Form1's OnCreate event handler, call the Create method to initialize the TermTypeList. Do this in the first line of code of the event handler:
    TermTypeList:=TStringList.Create;
  3. In Button1's OnClick event handler, add a line of code to populate TermTypeList with the list of terminal types returned in RPCBroker1's Results property. This code will use the Add method of TStrings sequentially so that the subscripting of TermTypeList will match the subscripting of Results. The code for that event handler should then look like:
    procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
begin
  RPCBroker1.RemoteProcedure:='Zxxx LIST';
  try
    begin {call}
      RPCBroker1.Call;
      for i:=0 to (RPCBroker1.Results.Count-1) do begin {copy}
        ListBox1.Items.Add(piece(RPCBroker1.Results[i],'^',2));
        TermTypeList.Add(RPCBroker1.Results[i]); //added line
      end; {copy}
    end; {call}
  except
    On EBrokerError do
      ShowMessage('A problem was encountered communicating with the server.');
  end; {try}
end;
  4. Create an event handler for Form1's OnDestroy event (select Form1, go to the Events tab of the Object Inspector, and double-click on the right-hand column for the OnDestroy event). In that event handler, add one line of code to call the Free method for TermTypeList. This frees the memory used by the list:
    procedure TForm1.FormDestroy(Sender: TObject);
begin
  TermTypeList.Free;
end;

Then, to determine (and display) the ien of the corresponding terminal type when a user selects an item in the list box:

  1. Create an OnClick event handler for ListBox1 by double-clicking on the list box.

  2. Add code to the new event handler that checks if an item is selected. If an item is selected in the list box, display the first piece of the corresponding item saved off in the TermTypeList array (the index subscripts of TermTypeList and of the list box match each other). This is the ien of the corresponding VA FileMan entry.
    procedure TForm1.ListBox1Click(Sender: TObject);
var
  ien: String;
begin
  if (ListBox1.ItemIndex <> -1) then
  begin {displayitem}
    ien:=piece(TermTypeList[ListBox1.ItemIndex],'^',1);
    ShowMessage(ien);
  end; {displayitem}

    end;

  3. Compile and run your application. When you click on an item in the list box, the ien corresponding to that item should be displayed in a pop-up message window.

Now that you can determine the ien of any entry the user selects in the list box, you can retrieve and display the corresponding VA FileMan record for any selected list box entry.


Tutorial Step 8

Step 8. RPC Routine to Retrieve a Terminal Type Entry

Now that you have associated an ien for each record displayed in the list box, you can use that ien to display fields from any terminal type entry in the list box that a user selects. To retrieve the fields for any selected terminal type entry, you should create a second custom RPC. This RPC will need to take an input parameter, the record ien, to know which record to retrieve.

To create an RPC routine to retrieve individual terminal type records:

  1. Choose the data format that your RPC should return. The type of data that you need to return to your client application determines the format of the routine that your RPC will call. In this case, the RPC should, given an ien, return fields .01, 1, 2, 3, 4, 6, and 7 (Name, Right Margin, Form Feed, Page Length, Back Space, Open Execute, and Close Execute).

    Since this information is constrained and small, a return type of ARRAY would be suitable for this RPC. The return format of the array is arbitrary; for the sake of this application, the routine should return fields .01, 1, 2, 3, and 4 in node 0; field 6 (a 245-character field) in node 1; and field 7 (also a 245-character field) in node 2. This array must be returned in the first parameter to the routine.

  2. The routine for this RPC also needs to be able to take an ien as an input parameter. Any additional input parameters such as one for the ien must follow the required input parameter in which results are returned.

  3. Add a second subroutine to the ZxxxTT routine for the second RPC, similar to the following. This subroutine uses an ien to retrieve fields for a particular terminal type. It then sets three result nodes, each containing a specified set of fields for the record corresponding to the ien parameter.
    TERMENT(RESULT,IEN) ; retrieve a string of fields for a termtype
 ; format of results (by field number):
 ; RESULT(0)=.01^1^2^3^4
 ; RESULT(1)=6
 ; RESULT(2)=7
 ;
 N I,ARRAY S IEN=IEN_",",RESULT(1)=""
 D GETS^DIQ(3.2,IEN,".01;1;2;3;4;6;7","","ARRAY")
 S RESULT(0)="" I '$D(DIERR) D
 .F I=.01,1,2,3,4 D
 ..S RESULT(0)=RESULT(0)_ARRAY(3.2,IEN,I)_"^"
 .S RESULT(1)=ARRAY(3.2,IEN,6)
 .S RESULT(2)=ARRAY(3.2,IEN,7)
 K ARRAY Q
  4. Test the routine. Call it like the Broker would:
    >D TERMENT^ZxxxTT(.ARRAY,103)

    Confirm that the return array contains the specified fields in the following nodes:

    ARRAY(0)=C-HINQLINK^80^#,$C(27,91,50,74,27,91,72)^24^$C(8)^
ARRAY(1)=U $I:(0:255::255:512)
ARRAY(2)=U $I:(:::::512) C $I

Once you've tested your routine, and confirmed that it returns data correctly, the next step is to create the RPC that will call this routine.


Tutorial Step 9

Step 9. RPC to Retrieve a Terminal Type Entry

Now that you've created an RPC-compatible routine to retrieve fields from a terminal type record, you can go ahead and create the RPC itself.

To create an RPC that uses the TERMENT^ZxxxTT routine:

  1. Using VA FileMan, create a new RPC entry in the REMOTE PROCEDURE file. Set up the RPC as follows:
                 NAME: ZxxxTT RETRIEVE
              TAG: TERMENT
          ROUTINE: ZxxxTT
RETURN VALUE TYPE: ARRAY
      DESCRIPTION: Used in RPC Broker tutorial.
  INPUT PARAMETER: IEN    PARAMETER TYPE: LITERAL

The RPC's RETURN VALUE TYPE is set to ARRAY. This means that the RPC expects a return value that contains results nodes, each subscripted only at the first subscript level.

The WORD WRAP ON setting does not affect RPCs whose RETURN VALUE TYPE is ARRAY.

The additional input parameter needed to pass in a record ien is documented in the INPUT PARAMETER multiple. Its parameter type is LITERAL, which is appropriate when being passed the numeric value of an ien.

This RPC can now be called from a Delphi application, through the TRPCBroker component.


Tutorial Step 10

Step 10. Call the ZxxxTT RETRIEVE RPC

When a user selects a terminal type entry in the list box, the OnClick event is triggered. The new ZxxxTT RETRIEVE RPC can be called from that OnClick event, as a replacement for the code there that simply displays the ien of any selected record.

To use the ZxxxTT RETRIEVE RPC to display fields from a selected terminal type:

  1. Create labels and edit boxes for each of the fields the RPC returns from the Terminal type file:
    Terminal Type

    Field

             Add a TEdit component named: Add a Label with the Caption:
    .01 | Name | Name:
    1 | RightMargin | Right Margin:
    2 | FormFeed | Form Feed:
    3 | PageLength | Page Length:
    4 | BackSpace | Back Space:
    6 | OpenExecute | Open Execute:
    7 | CloseExecute | Close Execute:

  2. Update ListBox1's OnClick event handler. Add code so that when the user clicks on an entry in the list box, your application will call the ZxxxTT RETRIEVE RPC to retrieve fields for the corresponding terminal type, and display those fields in the set of TEdit controls on your form. This code should:

    a. Set RCPBroker1's RemoteProcedure property to ZxxxTT RETRIEVE.

    b. Pass the ien of the selected terminal type to the RPC, using the TRPCBroker's runtime Param property. Pass the ien in the Value property, i.e. RPCBroker1.Param[0].Value.

    c. The PType for the ien parameter should be passed in RPCBroker1.Param[0].PType. Possible types are literal, reference and list. In this case, to pass in an ien, the appropriate PType is literal.

    d. Call RPCBroker1's Call method (in a try...except exception handler block) to invoke the ZxxxTT RETRIEVE RPC.

    e. Set the appropriate pieces from each of the three Results nodes into each of the TEdit boxes corresponding to each returned field.

    The code for the OnClick event handler should look like the following:

    procedure TForm1.ListBox1Click(Sender: TObject);
var
  ien: String;
begin
  if (ListBox1.ItemIndex <> -1) then
  begin {displayitem}
    ien:=piece(TermTypeList[ListBox1.ItemIndex],'^',1);
    RPCBroker1.RemoteProcedure:='ZxxxTT RETRIEVE';
    RPCBroker1.Param[0].Value := ien;
    RPCBroker1.Param[0].PType := literal;
    try
      begin {call code}
        RPCBroker1.Call;
        Name.Text:=piece(RPCBroker1.Results[0],'^',1);
        RightMargin.Text:=piece(RPCBroker1.Results[0],'^',2);
        FormFeed.Text:=piece(RPCBroker1.Results[0],'^',3);
        PageLength.Text:=piece(RPCBroker1.Results[0],'^',4);
        BackSpace.Text:=piece(RPCBroker1.Results[0],'^',5);
        OpenExecute.Text:=RPCBroker1.Results[1];
        CloseExecute.Text:=RPCBroker1.Results[2];
      end; {call code}
    except
    On EBrokerError do
      ShowMessage('A problem was encountered communicating with the server.');
    end; {try}
  end; {displayitem}
end;
  3. Compile and run your application. When you click on an entry in the list box now, the corresponding fields should be retrieved and displayed in the set of edit boxes on your form.


Tutorial Register RPCs

Step 11. Register RPCs

Up until now, it has been assumed that the only user of your application is you, and that you have programmer access and the XUPROGMODE key in the account where your RPCs are accessed.

Under any other circumstance, any RPCs that your application uses must be registered for use by your application on the host system. Registration authorizes the RPC(s) for use by your client based on user privileges.

To register the RPCs used by the tutorial application:

  1. Create an option of type "B" (Broker). For example, create an option called ZxxxTT TERMTYPE for the tutorial application.

  2. In the "B"-type option's RPC multiple, make one entry for each RPC your application calls. In the case of this tutorial, there should be two entries: one for ZxxxTT LIST and one for ZxxxTT RETRIEVE.

  3. Follow the steps in How to Register an RPC to create an application context, using the ZxxxTT TERMTYPE option. Essentially, add a line of code that calls the CreateContext function, and terminates the application if False is returned. The code for Form1's OnCreate event should now look like:
    procedure TForm1.FormCreate(Sender: TObject);
var   ServerStr: String;
        PortStr: String;
begin
  TermTypeList:=TStringList.Create;
  // get the correct port and server from Registry
  if GetServerInfo(ServerStr,PortStr)<> mrCancel then
  begin {connectOK}
    RPCBroker1.Server:=ServerStr;
    RPCBroker1.ListenerPort:=StrToInt(PortStr);
    // establish a connection to the RPC Broker server
    try
      RPCBroker1.Connected:=True;
      // Check security
      if not RPCBroker1.CreateContext('ZxxxTT TERMTYPE') then
        Application.Terminate;
    except
      On EBrokerError do
      begin {error}
        ShowMessage('Connection to server could not be established!');
        Application.Terminate;
      end; {error}
    end; {try}
  end {connectOK}
  else
    Application.Terminate;
end;
  4. Compile and run your application. Try running it both with and without the XUPROGMODE key assigned to yourself. Without XUPROGMODE, you won't be able to run your application unless the ZxxxTT TERMTYPE option is assigned to your menu tree.


Tutorial: FileMan Components for Delphi

See Also: FileMan Components for Delphi

Congratulations! You have now created a sample application that performs entry lookup, and retrieves fields from any record selected by the end-user. You are now ready to create your own Delphi applications using the RPC Broker.

If your application needs to perform database tasks with VA FileMan on a server, you should consider using the FileMan Components for Delphi. These components automate the major tasks of working with database records through Delphi. Among the functions they provide are:

  • Automated entry retrieval into a set of controls

  • Automated online help for database fields

  • Automated validation of user data entry

  • Automated filing of changed data

  • Ien tracking in all controls

  • Automated DBS error tracking on the Delphi client

  • Generic lookup dialog

  • Record locking

  • Record deletion

If you need to do more than the most simple database tasks in your Delphi applications, the FileMan Components for Delphi encapsulate most of the coding needed to retrieve, validate, and file VA FileMan data.


Tutorial: Source Code

unit tut1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Trpcb, RPCConf1, StdCtrls, MFunStr;

type
  TForm1 = class(TForm)
    RPCBroker1: TRPCBroker;
    ListBox1: TListBox;
    Button1: TButton;
    Name: TEdit;
    RightMargin: TEdit;
    FormFeed: TEdit;
    OpenExecute: TEdit;
    CloseExecute: TEdit;
    PageLength: TEdit;
    BackSpace: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
     TermTypeList: TStrings; // Added declaration of TermTypeList
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var   ServerStr: String;
        PortStr: String;
begin
  TermTypeList:=TStringList.Create;
  // get the correct port and server from Registry
  if GetServerInfo(ServerStr,PortStr)<> mrCancel then
  begin {connectOK}
    RPCBroker1.Server:=ServerStr;
    RPCBroker1.ListenerPort:=StrToInt(PortStr);
    // establish a connection to the RPC Broker server
    try
      RPCBroker1.Connected:=True;
      if not RPCBroker1.CreateContext('ZxxxTT TERMTYPE') then
        Application.Terminate;
    except
      On EBrokerError do
      begin {error}
        ShowMessage('Connection to server could not be established!');
        Application.Terminate;
      end; {error}
    end; {try}
  end {connectOK}
  else
    Application.Terminate;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
begin
  RPCBroker1.RemoteProcedure:='ZxxxTT LIST';
  try
    begin {call}
      RPCBroker1.Call;
   for i:=0 to (RPCBroker1.Results.Count-1) do begin {copy}
     ListBox1.Items.Add(piece(RPCBroker1.Results[i],'^',2));
     TermTypeList.Add(RPCBroker1.Results[i]); //added line
   end; {copy}
    end; {call}
  except
    On EBrokerError do
      ShowMessage('A problem was encountered communicating with the server.');
  end; {try}
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
  ien: String;
begin
  if (ListBox1.ItemIndex <> -1) then
  begin {displayitem}
    ien:=piece(TermTypeList[ListBox1.ItemIndex],'^',1);
    RPCBroker1.RemoteProcedure:='ZxxxTT RETRIEVE';
    RPCBroker1.Param[0].Value := ien;
    RPCBroker1.Param[0].PType := literal;
    try
      begin {call code}
        RPCBroker1.Call;
        Name.Text:=piece(RPCBroker1.Results[0],'^',1);
        RightMargin.Text:=piece(RPCBroker1.Results[0],'^',2);
        FormFeed.Text:=piece(RPCBroker1.Results[0],'^',3);
        PageLength.Text:=piece(RPCBroker1.Results[0],'^',4);
        BackSpace.Text:=piece(RPCBroker1.Results[0],'^',5);
        OpenExecute.Text:=RPCBroker1.Results[1];
        CloseExecute.Text:=RPCBroker1.Results[2];
      end; {call code}
    except
    On EBrokerError do
      ShowMessage('A problem was encountered communicating with the server.');
    end; {try}
  end; {displayitem}
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 TermTypeList.Free;
end;

end.


RPC Broker DPL

RPC Broker Delphi Package Library

A new feature with Delphi V. 3.0 enables applications to be distributed in specially compiled dynamic-link libraries called Delphi Package Libraries (DPLs). DPLs enable code-sharing, reduction of executable file size, and conservation of system resources. The use of DPLs is restricted to development in Delphi 3 or higher.

VistaBroker.DPL

You can compile the TRPCBroker component code into your application, or you can choose instead to link your application to the VistaBroker.DPL dynamic link library.

For more information on how to use DPLs, see the Borland Delphi 3 User's Guide.

The VistaBroker.DPL file is installed on end-user workstations by the RPC Broker V. 1.1 end-user client workstation installation program, along with the other RPC Broker V. 1.1. client files. It is installed in an appropriate directory, depending on the operating system, such as \WINDOWS\SYSTEM, such that the DPL is accessible when it is called by application programs. Therefore, you do not need to distribute VistaBroker.DPL with your application.

Distributing the Delphi VCL30.DPL

If you choose to access functionality of the TRPCBroker component through the VistaBroker.DPL dynamic link library, an additional requirement is that the VCL30.DPL library (provided with Delphi V. 3.0) be installed on the end-user workstation.

The RPC Broker does not distribute VCL30.DPL to end-user workstations (it only distributes VistaBroker.DPL). You must ensure that VCL30.DPL is also installed on end-user workstations, perhaps through the installation instructions you provide to system managers.


Introduction to the RPC Broker DLL Interface

RPC Broker 32-bit DLL Interface Introduction

The functionality of the TRPCBroker component for Delphi is provided in a 32-bit Dynamic Link Library (DLL) interface, in BAPI32.DLL. This enables the use of any development product that can access Windows 32-bit DLLs to create applications that communicate with M servers through the RPC Broker.

In Delphi, you have direct access to the TRPCBroker component itself, and its properties and methods. In other development environments, you can only access the properties and methods of the TRPCBroker component through DLL functions. So to understand the DLL interface, you should understand how the TRPCBroker component is used in its native environment (Delphi).

DLL Exported Functions

The following special issues should be considered when accessing RPC Broker functionality through its DLL:

RPC Results from DLL Calls

GetServerInfo Function and the DLL

Header Files

Header files for using the DLL are provided for C (BAPI32.H), C++ (BAPI32.HPP), and Visual Basic (BAPI32.BAS).

Guidelines for Calling DLL from C++

Guidelines for Calling DLL from C

Guidelines for Calling DLL from Visual Basic

Sample DLL Application

The VB5EGCHO sample application, distributed with the Broker Development Kit, demonstrates use of the RPC Broker 32-bit DLL from Microsoft Visual Basic. The source code is located in the SAMPLES\VB5EGCHO subdirectory of the main BDK32 directory.


RPC Results through the DLL

RPC Results from DLL Calls

When executing an RPC on an M server, results from the RPC are returned as a text stream. This text stream may or may not have embedded <CR><LF> character combinations.

In Delphi, when you call an RPC using the TRPCBroker component directly, the text stream returned from an RPC is automatically parsed and returned in the TRPCBroker component's Results property, either in Results[0] or in multiple Results nodes. If there are no embedded <CR><LF> character combinations in the text stream, only Results[0] is used. If there are embedded <CR><LF> character combinations, results are placed into separate Results nodes based on the <CR><LF> delimiters.

When using the DLL interface, the return value is a text stream, but no processing of the text stream is performed for you. It is up to you to parse out what would have been individual Results nodes in Delphi, based on the presence of any <CR><LF> character combinations in the text stream.

You must create a character buffer large enough to receive the entire return value of an RPC.


GetServerInfo Function and the DLL

When you use the TRPCBroker component for Delphi, you are able to call the GetServerInfo function to retrieve the end-user workstation's server and port settings.

The functionality provided by GetServerInfo is not currently available through the RPC Broker 32-bit DLL interface. A future version of the RPC Broker will provide access to the GetServerInfo functionality for DLL users.

To work around this for now, when using the RPC Broker 32-bit DLL, you should prompt the user directly for the server and port to connect to.


RPCBCall Function

Examples

Executes a remote procedure call, and fills the passed buffer with the data resulting from the call. This is equivalent to the TRPCBroker component's Call method.

Declarations

Delphi	procedure RpcbCall(const RPCBroker: TRPCBroker; CallResult: PChar);
C	char *(__stdcall *RPCBCall) (void *, char *);
C++	char * RPCBCall( char * s);
VB	Sub RpcbCall (ByVal intRpcbHandle As Long, ByVal strCallResult As String)

Parameter Description

RPCBroker Handle of the Broker component which contains the name of the remote procedure and all of the required parameters.

CallResult An empty character buffer that the calling application must create (allocate memory for) before making this call. This buffer is filled with the result of the call.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.


RPCBCreate Function

Examples

Creates a new Broker component for the application, which can then be used to connect to the server and call remote procedures.

Declarations

Delphi	function  RpcbCreate: TRPCBroker;
C	void * (__stdcall *RPCBCreate)(void);
C++	N/A (encapsulated in TRPCBroker class definition)
VB	Function RpcbCreate () As Long
Return Value
A handle for the TRPCBroker component created.


RPCBCreateContext Function

Examples

This procedure calls the TRPCBroker component's CreateContext method to set up the environment on the server for subsequent RPCs.

Declarations

Delphi	function  RpcbCreateContext(const RPCBroker: TRPCBroker; const Context: PChar): boolean;
C	bool (__stdcall *RPCBCreateContext) (void *, char *);
C++	bool RPCBCreateContext ( char * s);
VB	Function RpcbCreateContext (ByVal intRpcbHandle As Long, ByVal strContext As String) As Integer
Return Value
True/1 if context could be created; false/0 if context could not be created.

Parameter Description

RPCBroker Handle of the TRPCBroker component.

Context Null-terminated string identifying the option on the server for which subsequent RPCs are registered.


RPCBFree Function

Examples

Destroys the Broker component and releases associated memory.

Declarations

Delphi	procedure RpcbFree(RPCBroker: TRPCBroker);
C	void (__stdcall *RPCBFree)(void *);
C++	N/A (encapsulated in TRPCBroker class definition)
VB	Sub RpcbFree (ByVal intRpcbHandle As Long)

Parameter Description

RPCBroker Handle of the TRPCBroker component to destroy.


RPCBMultItemGet Function

Examples

Returns a requested item in a TRPCBroker Param property's Mult property.

Declarations

Delphi	procedure RPCBMultItemGet (const RPCBroker: TRPCBroker; ParamIndex: integer; Subscript, Value: PChar);
C	void (__stdcall *RPCBMultItemGet) (void *, int, char *, char *);
C++	void RPCBMultItemGet ( int i, char * s, char * t);
VB	Sub RpcbMultItemGet (ByVal intRpcbHandle As Long, ByVal intParIdx As Integer, ByVal strSubscript As String, ByVal strValue As String)

Parameter Description

RPCBroker Handle of the TRPCBroker component.

ParamIndex Integer index of the parameter which contains the Mult property.

Subscript Null-terminated string identifying the Mult element to get.

Value An empty buffer that the calling application must create (allocate memory for) before making this call. This buffer will be filled with value of the Mult property item.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.


RPCBMultPropGet Function

Examples

Returns a selected property value of a TRPCBroker Param property's Mult property.

Declarations

Delphi	procedure RpcbMultPropGet(const RPCBroker: TRPCBroker; ParamIndex: integer; Prop,Value: PChar);
C	void (__stdcall *RPCBMultPropGet) (void *, int, char *, char *);
C++	void RPCBMultPropGet (int i , char * s, char * t);
VB	Sub RpcbMultPropGet (ByVal intRpcbHandle As Long, ByVal intParIdx As Integer, ByVal strProp As String, ByRef strValue As String)

Parameter Description

RPCBroker Handle of the TRPCBroker component.

ParamIndex Integer index of the parameter which contains the Mult property.

Prop Null-terminated string identifying the name of the TMult property to get.

Value An empty buffer that the calling application must create (allocate memory for) before making this call. This buffer will be filled with value of the Mult property that is in the Prop.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.


RPCBMultSet Function

Examples

Sets an item in a TRPCBroker Param property's Mult property to a value.

Declarations

Delphi	procedure RpcbMultSet(const RPCBroker: TRPCBroker; ParamIndex: integer; Subscript, Value: PChar);
C	void (__stdcall *RPCBMultSet) (void *, int, char *, char *);
C++	void RPCBMultSet ( int i, char * s, char * t);
VB	Sub RpcbMultSet (ByVal intRpcbHandle As Long, ByVal intParIdx As Integer, ByVal strSubscript As String, ByVal strValue As String)

Parameter Description

RPCBroker Handle of the TRPCBroker component.

ParamIndex Integer index of the parameter which contains the Mult property.

Subscript Null-terminated string of the Mult item to set.

Value Null-terminated string containing the value that the Mult item should be set to.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.


RPCBMultSortedSet Function

Examples

Sets the Sorted property of a Mult property. In essence, sorts and keeps the Mult property sorted or just leaves it in the order it is populated.

Declarations

Delphi	procedure RpcbMultSortedSet(const RPCBroker: TRPCBroker; ParamIndex: integer; Value: boolean);
C	void (__stdcall *RPCBMultSortedSet) (void *, int, bool);
C++	void RPCBMultSortedSet (int i, bool v);
VB	Sub RpcbMultSortedSet (ByVal intRpcbHandle As Long, ByVal intParIdx As Integer, ByVal intValue As Integer)

Parameter Description

RPCBroker Handle of the TRPCBroker component.

ParamIndex Integer index of the parameter which contains the Mult property.

Value Can be either a boolean or, if the calling application language does not support boolean type, can be an integer. True or 1 will sort the Mult and keep it sorted thereafter when other elements are added. False or 0 will not sort the Mult and the elements will be stored in the order they are added.


RPCBParamGet Function

Examples

Returns two values in two parameters: the value and the parameter type of a Param item.

You can compare the returned parameter type to the following enumerated values: literal, reference and list.

Declarations

Delphi	procedure RpcbParamGet(const RPCBroker: TRPCBroker; ParamIndex: integer; var ParamType: TParamType; var ParamValue: PChar);
C	void (__stdcall *RPCBParamGet) (void *, int, int, char *);
C++	void RPCBParamGet ( int i, int j, char * s);
VB	Sub RpcbParamGet (ByVal intRpcbHandle As Long, ByVal intParIdx As Integer, ByVal intParTyp As Integer, ByVal intParVal As String)

Parameter Description

RPCBroker Handle of the TRPCBroker component.

ParamIndex Integer index of the parameter to get value of.

ParamType This variable, after making the RPCBParamGet call, is filled with PType property of a Param[ParamIndex].

ParamValue An empty buffer that you must create (allocate memory for) before making this call. This buffer, after making the RPCBParamGet call, is filled with Value of a Param[ParamIndex].

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.


RPCBParamSet Function

Examples

Sets one Param item's Value and PType properties, in a single call.

Declarations

Delphi	procedure RpcbParamSet(const RPCBroker: TRPCBroker; const ParamIndex: integer; const ParamType: TParamType; const ParamValue: PChar);
C	void (__stdcall *RPCBParamSet) (void *, int, int, char *);
C++	void RPCBParamSet ( int i, int j, char * s);
VB	Sub RpcbParamSet (ByVal intRpcbHandle As Long, ByVal intParIdx As Integer, ByVal intParTyp As Integer, ByVal intParVal As String)

Parameter Description

RPCBroker Handle of the TRPCBroker component.

ParamIndex Integer index of the parameter.

ParamType Set to the parameter type for the parameter you are setting. The value should be one of the integer values that are valid as a PType: 0 (literal), 1 (reference) and 2 (list). You can use the enumerated values literal, reference and list, as declared in the C, C++ , or Visual Basic header file.

ParamValue Null-terminated string containing the Value to set.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.


RPCBPropGet Function

Examples

Returns a requested property of a TRPCBroker component.

Declarations

Delphi	procedure RpcbPropGet(const RPCBroker: TRPCBroker; const Prop: PChar; {var} Value: PChar);
C	void (__stdcall *RPCBPropGet) (void *, char *, char *);
C++	void RPCBPropGet ( char * s, char * t);
VB	Sub RpcbPropGet (ByVal intRpcbHandle As Long, ByVal strProp As String, ByVal strValue As String)

Parameter Description

RPCBroker Handle of the TRPCBroker component.

Prop Null-terminated string of the property to get. Not case sensitive. Valid properties to get are: ClearParameters, ClearResults, Connected, DebugMode, ListenerPort, RemoteProcedure, RPCTimeLimit, RPCVersion, and Server.

Value An empty buffer that you must create (allocate memory for) before making this call. After this call, the buffer is filled with value of the property that is in the Prop. This procedure takes care of all the necessary type conversions. Boolean property values are returned as 1 (True) or 0 (False).


RPCBPropSet Function

Examples

Sets a TRPCBroker property to some value.

Declarations

Delphi	procedure RpcbPropSet(const RPCBroker: TRPCBroker; Prop,Value: PChar);
C	void (__stdcall *RPCBPropSet) (void *, char *, char *);
C++	void RPCBPropSet ( char * s, char * t);
VB	Sub RpcbPropSet (ByVal intRpcbHandle As Long, ByVal strProp As String, ByVal strValue As String)

Parameter Description

RPCBroker Handle of the TRPCBroker component.

Prop Null-terminated string of the property to set. Not case-sensitive. Valid properties to set are: ClearParameters, ClearResults, Connected, DebugMode, ListenerPort, RemoteProcedure, RPCTimeLimit, RPCVersion, and Server.

Value Null-terminated string of the value that the Prop property should be set to. This procedure takes care of converting the passed in value to whatever type the property expects. For boolean properties, pass in 1 (True) or 0 (False).


C++ Guidelines

Guidelines for C++ Overview

The BAPI32.HPP header file defines a class "wrapper" around the RPC Broker 32-bit DLL, defining a TRPCBroker C++ class. Objects of this class include all functions exported in the DLL, as methods of the TRPCBroker C++ class.

TRPCBroker C++ class methods.

One feature of wrapping a class around the RPC Broker 32-bit DLL is that all the ordinary details of working with a DLL (loading the DLL, getting the addresses of the functions in the DLL, and freeing the DLL) are done within the class definition. When you initialize the class, all of the details of loading and unloading the detail (LoadLibrary, GetProcAddress, and FreeLibrary) are done for you.

To use objects of the class, simply initialize the class, and then create and destroy objects of the class.

To use the TRPCBroker C++ class that encapsulates BAPI32.DLL:

  1. Initialize the class

  2. Create Broker instances

  3. Connect to the server

  4. Execute RPCs

  5. Destroy Broker instances


C++ View: Methods

C++: TRPCBroker C++ Class Methods

The functions in the RPC Broker 32-bit DLL are encapsulated in the following TRPCBroker C++ class methods:

DLL Function TRPCBroker C++ class method

RpcbCall char * RPCBCall( char * s);

RpcbCreateContext bool RPCBCreateContext ( char * s);

RpcbMultItemGet void RPCBMultItemGet ( int i, char * s, char * t);

RpcbMultPropGet void RPCBMultPropGet (void * ptr, int i , char * s, char * t);

RpcbMultSet void RPCBMultSet ( int i, char * s, char * t);

RpcbMultSortedSet void RPCBMultSortedSet (void * ptr, int i, bool v);

RpcbParamGet void RPCBParamGet ( int i, int j, char * s);

RpcbParamSet void RPCBParamSet ( int i, int j, char * s);

RpcbPropGet void RPCBPropGet ( char * s, char * t);

RpcbPropSet void RPCBPropSet ( char * s, char * t);


C++ View: Initializing RPCBroker Class

C++: Initialize the Class

The first step to using the RPC Broker 32-bit DLL in a C++ program is to load the DLL and get the process addresses for the exported functions.

To initialize access to the Broker DLL functions:

  1. Include bapi32.hpp in your program.
    #include bapi32.hpp

This includes the TRPCBroker C++ class definition in your program. When you (later) create a TRPCBroker C++ class object in your program, the class definition takes care of loading the DLL if not already loaded, mapping the DLL functions if not already mapped, and creating the instance of the TRPCBroker component.


C++ View: Creating Broker Instances

C++: Create Broker Instances

To create instances of TRPCBroker C++ class objects in your C++ program:

  1. Create a variable of type TRPCBroker. This initializes the TRPCBroker class, creates a TRPCBroker C++ class object instance, and creates a TRPCBroker component.
    TRPCBroker RPCInst; //initializes TRPCBroker class

The properties and methods of the created TRPCBroker component can be accessed through the TRPCBroker C++ class object.


C++ View: Connecting to the Server

C++: Connect to the Server

To connect to the server from your C++ program:

  1. Set the server and port to connect to.
    // Set the Server and Port properties to determine where to connect to
RPCInst.RPCBPropSet("Server", server);
RPCInst.RPCBPropSet("ListenerPort", "9200");
  2. Set the Connected property to true; this attempts a connection to the server.
    // Set Connected property to True, to connect
RPCInst.RPCBPropSet("Connected", "1");
  3. Check if you are still connected. If so, you can continue (your connection was made). If not, you should quit or branch accordingly.
    // If still connected, can continue.
RPCInst.RPCBPropGet("Connected", Value);
if (atoi(Value) != 1) return false;
  4. Attempt to create context for your application's "B"-type option. If you can't create context, you should quit or branch accordingly. If RPCBCreateContext returns True, then you are ready to call all RPCs registered to your application's "B"-type option.
    // Create Context for your application's option (in this
// case, XWB EGCHO).
result = RPCInst.RPCBCreateContext("XWB EGCHO");
return result;


C++ View: Executing RPCs

C++: Execute RPCs

If you can make a successful connection to the RPC Broker server, and create an application context, you can execute any RPCs registered to your context.

To execute RPCs from your C++ program:

  1. Create a character buffer large enough to hold your RPC's return value:
    char Value [1024];
  2. Set the RemoteProcedure property of the TRPCBroker component to the RPC to execute.
    RPCInst.RPCBPropSet("RemoteProcedure","XWB GET VARIABLE VALUE");
  3. Set the Param values for any parameters needed by the RPC. In the following example, one TRPCBroker Param node is set (the equivalent of Param[0]):

    a. A value of 0 for parameter 1 denotes the integer index of the Param node being set (Param[0]).

    b. A value of reference for parameter 2 denotes the setting for the equivalent of Param[0].PType. This uses the enumerated values for PType declared in the header file.

    c. A value of "DUZ" for parameter 3 denotes that the equivalent of Param[0].Value is "DUZ".

    RPCInst.RPCBParamSet(0, reference, "DUZ");
  4. Use the RPCBCall method to execute the RPC.
    RPCInst.RPCBCall(Value);

    The return value from the RPC is returned in the first parameter (in this case, the Value character buffer).


C++ View: Destroying Broker Instances

C++: Destroy Broker Instances

You do not need to do anything special to free up memory used by the TRPCBroker component instances and their companion TRPCBroker C++ class objects. They are automatically destroyed when your program terminates, just as normal variables are automatically destroyed.

Also, when your program terminates, the FreeLibrary Windows API call is automatically executed to unload the RPC Broker 32-bit DLL, so there is no need to do this manually.


C Guidelines

Guidelines for C Overview

The BAPI32.H header file defines the function prototypes for all functions exported in the RPC Broker 32-bit DLL.

DLL Exported Functions

To use the DLL Broker functions, using C, exported in BAPI32.DLL:

  1. Initialize - LoadLibrary and GetProcAddress

  2. Create Broker components

  3. Connect to the server

  4. Execute RPCs

  5. Destroy Broker components


C: Initialization - LoadLibrary and GetProcAddress

C: Initialize - LoadLibrary and GetProcAddress

The first step to using the RPC Broker 32-bit DLL in a C program is to load the DLL and get the process addresses for the exported functions.

To initialize access to the Broker DLL functions:

  1. Use the Windows API LoadLibrary function to load the DLL.
    HINSTANCE hLib = LoadLibrary("bapi32.dll");
if((unsigned)hLib<=HINSTANCE_ERROR)
{
   /* add your error handler for case where library fails to load */
   return 1;
}
  2. If you successfully load the DLL, map function pointers to the addresses of the functions in the DLL that you need for your application.
    RPCBCreate = (void *(__stdcall*)()) GetProcAddress(hLib, "RpcbCreate");
RPCBFree = (void (__stdcall*)(void *)) GetProcAddress(hLib, "RpcbFree");
RPCBCall = (char *(__stdcall*)(void *, char *)) GetProcAddress(hLib, "RpcbCall");
RPCBCreateContext = (bool (__stdcall*)(void *, char *)) GetProcAddress(hLib, "RpcbCreateContext");
RPCBMultSet = (void (__stdcall*)(void *, int, char *, char *)) GetProcAddress(hLib, "RpcbMultSet");
RPCBParamGet = (void (__stdcall*)(void *, int, int, char *)) GetProcAddress(hLib, "RpcbParamGet");
RPCBParamSet = (void (__stdcall*)(void *, int, int, char *)) GetProcAddress(hLib, "RpcbParamSet");
RPCBPropGet = (void (__stdcall*)(void *, char *, char *)) GetProcAddress(hLib, "RpcbPropGet");
RPCBPropSet =(void (__stdcall*)(void *, char *, char *)) GetProcAddress(hLib, "RpcbPropSet");
//
// GetProcAddress returns null on failure
//
if( RPCBCreate == NULL || RPCBFree == NULL || RPCBCall == NULL || RPCBCreateContext == NULL
   || RPCBMultSet == NULL || RPCBParamGet == NULL || RPCBParamSet == NULL || RPCBPropGet == NULL
   || RPCBPropSet == NULL)
{
/* add your error handler for case where functions are not found */
   return 1;
}

Now you can use functions exported in the DLL.


C: Creating Broker Components

C: Create Broker Components

To create TRPCBroker components in your C program:

  1. Create a pointer for the TRPCBroker component.

void * RPCBroker; //generic pointer for TRPCBroker component instance

  1. Call the RpcbCreate method to create a TRPCBroker component and return its address into the pointer you created:
    RPCBroker = RPCBCreate(); //create TRPCBroker component instance

Now you can use the pointer to the created Broker component to call its methods.


C: Connecting to the Server

C: Connect to the Server

To connect to the server from your C program:

  1. Set the server and port to connect to.
    // Set the Server and Port properties to determine where to connect to
RPCBPropSet(RPCBroker,"Server", "BROKERSERVER");
RPCBPropSet(RPCBroker, "ListenerPort", "9200");
  2. Set the Connected property to true; this attempts a connection to the server.
    // Set Connected property to True, to connect
RPCBPropSet(RPCBroker, "Connected", "1");
  3. Check if you are still connected. If so, you can continue (your connection was made). If not, you should quit or branch accordingly.
    // If still connected, can continue.
RPCBPropGet(RPCBroker, "Connected", Value);
if (atoi(Value) != 1) return false;
  4. Attempt to create context for your application's "B"-type option. If you can't create context, you should quit or branch accordingly. If RPCBCreateContext returns True, then you are ready to call all RPCs registered to your application's "B"-type option.
    // Create Context for your application's option (in this
// case, XWB EGCHO).
result = RPCBCreateContext(RPCBroker, "XWB EGCHO");
return result;


C: Executing RPCs

C: Execute RPCs

If you can make a successful connection to the RPC Broker server, and create an application context, you can execute any RPCs registered to your context.

To execute RPCs from your C program:

  1. Create a character buffer large enough to hold your RPC's return value:
    static char Value [1024];
  2. Set the RemoteProcedure property of the TRPCBroker component to the RPC to execute.
    RPCBPropSet(RPCBroker, "RemoteProcedure","XWB GET VARIABLE VALUE");
  3. Set the Param values for any parameters needed by the RPC. In the following example, one TRPCBroker Param node is set (the equivalent of Param[0]):

    a. A value of 0 for parameter 2 denotes the integer index of the Param node being set (Param[0]).

    b. A value of reference for parameter 3 denotes the setting for the equivalent of Param[0].PType. This uses the enumerated values for PType declared in the header file.

    c. A value of "DUZ" for parameter 4 denotes that the equivalent of Param[0].Value is "DUZ".

    RPCBParamSet(RPCBroker, 0, reference, "DUZ");
  4. Use the RPCBCall method to execute the RPC.
    RPCBCall(RPCBroker, Value);

    The return value from the RPC is returned in the second parameter (in this case, the Value character buffer).


C: Destroying Broker Components

C: Destroy Broker Components

When you are done using any TRPCBroker component, you should call its destroy method to free it from memory.

To destroy TRPCBroker components from your C program:

  1. Make sure the TRPCBroker component is not connected.
    RPCBPropSet(RPCBroker, "Connected", "0");
  2. Call the RpcbFree method to destroy the object.
    RPCBFree(RPCBroker); //Destroy RPCBroker component instance
  3. When you have destroyed all TRPCBroker components, but before your application terminates, you should call the Windows API FreeLibrary function to unload the DLL.
    FreeLibrary(hLib);


Visual Basic Guidelines

Guidelines for Visual Basic Overview

The BAPI32.BAS header file defines the function prototypes for all functions exported in the RPC Broker 32-bit DLL.

DLL Exported Functions

To use the DLL Broker functions, using Visual Basic, exported in BAPI32.DLL:

  1. Initialize

  2. Create Broker components

  3. Connect to the server

  4. Execute RPCs

  5. Destroy Broker components

Sample DLL Application

The VB5EGCHO sample application, distributed with the Broker Development Kit, demonstrates use of the RPC Broker 32-bit DLL from Microsoft Visual Basic. The source code is located in the SAMPLES\VB5EGCHO subdirectory of the main BDK32 directory.


Visual Basic: Initialization

Visual Basic: Initialize

The first step to using the RPC Broker 32-bit DLL in a Visual Basic program is to load the DLL and get the process addresses for the exported functions.

To initialize access to the Broker DLL functions:

  1. Include BAPI32.BAS as a module in your Visual Basic program.

Visual Basic takes care of loading the DLL and mapping its functions.


Visual Basic: Creating Broker Components

Visual Basic: Create Broker Components

To create TRPCBroker components in your Visual Basic program:

  1. Create a variable to be a handle for the TRPCBroker component.

    Public intRpcbHandle As Long

  2. Call the RpcbCreate method to create a TRPCBroker component and return its address into the variable you created:
    intRpcbHandle = RpcbCreate()

Now you can use the handle to the created Broker component to call its methods.


Visual Basic: Connecting to the Server

Visual Basic: Connect to the Server

To connect to the server from your Visual Basic program:

  1. Set the server and port to connect to.
    Call RpcbPropSet(intRpcbHandle, "Server", "BROKERSERVER")
Call RpcbPropSet(intRpcbHandle, "ListenerPort", "9200")
  2. Set the Connected property to true; this attempts a connection to the server.
    Call RpcbPropSet(intRpcbHandle, "Connected", "1")
  3. Check if you are still connected. If so, you can continue (your connection was made). If not, you should quit or branch accordingly.
    RPCBPropGet(intRpcbHandle, "Connected", strResult)
  4. Attempt to create context for your application's "B"-type option. If you can't create context, you should quit or branch accordingly. If RpcbCreateContext returns True, then you are ready to call all RPCs registered to your application's "B"-type option.
    intResult = RpcbCreateContext(intRpcbHandle, "MY APPLICATION")


Visual Basic: Executing RPCs

Visual Basic: Execute RPCs

If you can make a successful connection to the RPC Broker server, and create an application context, you can execute any RPCs registered to your context.

To execute RPCs from your Visual Basic program:

  1. Create a character buffer large enough to hold your RPC's return value:
    Public strBuffer As String * 40000
  2. Set the RemoteProcedure property of the TRPCBroker component to the RPC to execute.
    Call RpcbPropSet(intRpcbHandle, "RemoteProcedure", "XWB GET VARIABLE VALUE")
  3. Set the Param values for any parameters needed by the RPC. In the following example, one TRPCBroker Param node is set (the equivalent of Param[0]):

    a. A value of 0 for parameter 2 denotes the integer index of the Param node being set (Param[0]).

    b. A value of reference for parameter 3 denotes the setting for the equivalent of Param[0].PType. This uses the enumerated values for PType declared in the header file.

    c. A value of "DUZ" for parameter 4 denotes that the equivalent of Param[0].Value is "DUZ".

    Call RPCBParamSet(intRpcbHandle, 0, reference, "DUZ");
  4. Use the RPCBCall method to execute the RPC.
    Call RpcbCall(intRpcbHandle, strBuffer)

    The return value from the RPC is returned in the second parameter (in this case, the Value character buffer).


Visual Basic: Destroying Broker Components

Visual Basic: Destroy Broker Components

When you are done using any TRPCBroker component, you should call its destroy method to free it from memory.

To destroy TRPCBroker components from your Visual Basic program:

  1. Make sure the TRPCBroker component is not connected.
    Call RpcbPropSet(intRpcbHandle, "Connected", "0")
  2. Call the RpcbFree method to destroy the object.
    RpcbFree(intRpcbHandle)

Visual Basic takes care of the details of unloading the DLL.


Preface

RPC Broker Systems Manual Preface

The Remote Procedure Call (RPC) Broker Systems Manual provides descriptive information and instructions on the use of the RPC Broker (also referred to as "Broker") software within the VA's Veterans Health Information Systems and Technology Architecture (V IST A) client/server environment. The emphasis is on the use of Borland's Delphi software. However, the RPC Broker does support other client environments.

This document is intended for the V IST A development community, the Information Resource Management (IRM) staff, and clinicians using Broker-based client/server applications. A wider audience of technical personnel engaged in operating and maintaining the Department of Veterans Affairs (VA) software may also find it useful as a reference.

The RPC Broker Development Team appreciates and encourages all feedback regarding the Broker and its use. Please include any problems encountered or enhancements you would like incorporated into the Broker software and documentation. Although we can't guarantee their incorporation, the RPC Broker Development Team will consider your suggestions for future versions of the Broker.


(Untitled)

Defaults

Pressing Defaults returns the programmer settings to their default values.


TParams Count example

Count Property Example

The following program code displays the number of parameters in a TParams variable within the caption of a label when the user clicks the CountParameters button:

procedure TForm1.CountParametersClick(Sender: TObject);
begin
  Label1.Caption := 'There are ' + IntToStr(RPCBroker1.Param.Count) +
    ' parameters.';
end;


lstCall Example

The following program code demonstrates the use of the lstCall method in a hypothetical example of bringing back a list of user's keys and automatically filling a list box with data:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RPCBroker1.RemoteProcedure := 'GET MY KEYS';
  RPCBroker1.lstCall(ListBox1.Items);
end;


Server Example

The following program code demonstrates using the Server property:

procedure TForm1.btnConnectClick(Sender: TObject);
begin
  RPCBroker1.ListenerPort := 9200;
  RPCBroker1.Server := 'DHCPSERVER';
  RPCBroker1.Connected := True;
end;


(Untitled)

ClearParameters

If checked, automatically sets the ClearParameters property of a TRPCBroker component to True when you add one to a form.


TParams Property

TParams

Count


(Untitled)

Server

Enter the name or numeric IP address of a server to connect to.

If you enter the name of a server and press Enter, the IP address of the server is resolved and displayed in the IP Addr field.


Order example

Order Method Example

The following program code demonstrates how to get the next and previous elements in a TMult list:

procedure TForm1.Button1Click(Sender: TObject);
var
  Mult: TMult;
  Subscript: string;
begin
  Mult := TMult.Create(Form1);         {Create Mult. Make Form1 its owner}
  Mult['First'] := 'One';
  Mult['Second'] := 'Two';             {Store element pairs one by one}
  Mult['Third'] := 'Three';
  Mult['Fourth'] := 'Four';
  Subscript := Mult.Order('Third',1);  {Subscript will be Fourth}
  Subscript := Mult.Order('Third',-1); {Subscript will be Second}
  Subscript := Mult.Order('THIRD',1);  {Subscript will be ''. THIRD subscript does not exist}
  Subscript := Mult.Order('',1);       {Subscript will be First}
  Subscript := Mult.Order('',-1);      {Subscript will be Fourth}
end;


Count example

Count Property Example

The following program code displays the number of items in a Mult component in the caption of a label when the user clicks the CountItems button:

procedure TForm1.CountItemsClick(Sender: TObject);
begin
  Label1.Caption := 'There are ' + IntToStr(Mult.Count) +
    ' items in the Mult.';
end;


HOSTS

HOSTS File

The HOSTS file is an ASCII text file that contains a list of the servers and their Internet Protocol (IP) addresses. We recommend you put in an entry (i.e., "DHCPSERVER") that points to the main server you intend using with the Broker the majority of the time. In your applications you will be able to specify any server you wish, however, if the Server property = " (i.e., null), you will get an error.


strCall Example

The following program code demonstrates the use of the strCall method in a hypothetical example of bringing back the name of the user currently logged on and automatically displaying it in a label:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RPCBroker1.RemoteProcedure := 'GET CURRENT USER NAME';
  Label1.Caption := RPCBroker1.strCall;
end;


RPCTimeLimit property

RPCTimeLimit Property (available at run-time only)

Example

Applies to

TRPCBroker component

Declaration

property RPCTimeLimit: integer

Description

This property is a public integer property that is available at run-time only. It specifies the length of time a client will wait for a response from an RPC. The default and minimum value of this property is 30 seconds. If an RPC is expected to take more than 30 seconds to complete, adjust the RPCTimeLimit property accordingly. However, it is not advisable to have an RPCTimeLimit that is too long. Otherwise, the client-end of the application will appear to "hang", if the server doesn’t respond in a timely fashion.


RPCTimeLimit Example

The following program code demonstrates using the RPCTimeLimit property:

procedure TForm1.Button1Click(Sender: TObject);
var
  intSaveRPCTimeLimit: integer;
begin
  RPCBroker1.RemoteProcedure := 'GET ALL LAB RESULTS';
  RPCBroker1.Param[0].Value := 'DFN';
  RPCBroker1.Param[0].PType := reference;
  intSaveRPCTimeLimit := RPCBroker1.RPCTimeLimit;  {save off current time limit}
  RPCBroker1.RPCTimeLimit := 60;   {can take up to a minute to complete}
  RPCBroker1.Call;
  RPCBroker1.RPCTimeLimit := intSaveRPCTimeLimit;  {restore previous time limit}

end;


TParams Count

Count Property

Example

Applies to

TParams component

Declaration

property Count: Word;

Description

The Count property contains the number of parameters in a TParams component. If the TParams component is empty, Count will be zero.


TMult Properties

TMult

Count

First

Last

Sorted


Mult

Mult Property

Example

Applies to

TParamRecord component

Declaration

property Mult: TMult;

Description

(Mult is a property of the TParamRecord used in the Param property.)

The Mult property of a TParamRecord component, which is the type of each TRPCBroker component’s Param[x] element, can be used to pass a string-subscripted array of strings to the server. For example, if you need to pass a patient's name and SSN to a remote procedure, you could pass them as two separate parameters as PType literals, or you could pass them in one parameter using the Mult property as a PType list. If one is being sent, a Mult must be the last element in the Param array.


Position Method

Example

Applies to

TMult component

Declaration

function Position(const Subscript: string): longint;

Description

The Position method takes the string subscript of an item in a TMult variable and returns its numeric index position much like a TStringList’s IndexOf method. Because TMult uses a TStringList internally, the IndexOf method is used to implement the Position method. The first position in the TMult is 0. If TMult is empty, or the Subscript does not identify an existing item, Position returns -1.

The Position and Subscript methods are the reciprocals of each other.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TMult component.


RemoteProcedure Example

The following program code demonstrates using the RemoteProcedure property:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RPCBroker1.RemoteProcedure := 'MY APPLICATION REMOTE PROCEDURE';
  RPCBroker1.Call;
end;


TMult example

TMult Component Example

The following program code demonstrates how to store and retrieve elements from a TMult variable:

procedure TForm1.Button1Click(Sender: TObject);
var
  Mult: TMult;
  Subscript: string;
begin
  Mult := TMult.Create(Form1);        {Create Mult. Make Form1 its owner}
  Mult['First'] := 'One';             {Store element pairs one by one}
  Mult['Second'] := 'Two';
  Mult['"First"'] := '"One"';         {Use double quotes for M strings}
  Label1.Caption := Mult['"First"'];  {Label1.Caption will get "One"}
  Label1.Caption := Mult['Third'];    {Error! 'Third' subscripted element was never stored}
end;


TParams Assign example

Assign Method Example

The following program code demonstrates how a TParams assign method can be used to save off the TRPCBroker component parameters and restore them later:

procedure TForm1.Button1Click(Sender: TObject);
var
  SaveParams: TParams;
  SaveRemoteProcedure: string;
begin
  SaveParams := TParams.Create(Self);  {create holding variable with Form1 as owner}
  SaveParams.Assign(RPCBroker1.Param);  {save parameters}
  SaveRemoteProcedure := RPCBroker1.RemoteProcedure;
  RPCBroker1.RemoteProcedure := 'SOME OTHER PROCEDURE';
  RPCBroker1.ClearParameters := True;
  RPCBroker1.Call;
  RPCBroker1.Param.Assign(SaveParams);  {restore parameters}
  RPCBroker1.RemoteProcedure := SaveRemoteProcedure;
  SaveParams.Free;  {release memory}
end;


ClearParameters Example

The following program code sets the ClearParameters property to True:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RPCBroker1.ClearParameters := True;
end;


(Untitled)

ClearResults

If checked, automatically sets the ClearResults property to of a TRPCBroker component to True when you add one to a form.


RemoteProcedure Property

Example

Applies to

TRPCBroker component

Declaration

property RemoteProcedure: TRemoteProc

Description

This property should be set to the name of the remote procedure call entry in the REMOTE PROCEDURE file (#8994).


$ORDER

$ORDER(variable name{,integer code})

Returns the subscript of the previous or next sibling in collating sequence of a specified array node.

To obtain the first subscript of a level, specify a null subscript in the argument.


XUPROGMODE

A security key distributed by Kernel as part of its Menu Manager. This security key enables access to a number of programmer-oriented options in Kernel.


ListenerPort Property

Example

Applies to

TRPCBroker component

Declaration

property ListenerPort: integer;

Description

This property gives the developer the ability to select the Listener port on the server. It must always be set before connecting to the server.

If one server computer has two or more environments (UCIs) which support client/server applications (e.g., Test and Production accounts), the Broker Listener processes must be listening on unique ports. Thus, you must specify which Listener port to use when you start the Listener on the server. Consequently, if you have more than one Listener running on the same server, the application needs to specify the correct Listener for its connection request. This is accomplished using the ListenerPort property.

You can use the Broker Programmer Preferences Editor (BrokerProgPref.Exe) to set the default value for this property when you add a TRPCBroker component to your form.


ClearResults Example

The following program code sets the ClearResults property to True:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RPCBroker1.ClearResults := True;
end;


Position example

Position Method Example

The following program code demonstrates how to get the position of an item in a TMult variable:

procedure TForm1.Button1Click(Sender: TObject);
var
  Mult: TMult;
begin
  Mult := TMult.Create(Form1);          {Create Mult. Make Form1 its owner}
  Label1.Caption := 'The position of the ''Third'' element is ' +
     IntToStr(Mult.Postion('Third'));   {will be -1 since the list is empty}
  Mult['Second'] := 'Two';
  Label1.Caption := 'The position of the ''Third'' element is ' +
     IntToStr(Mult.Postion('Third'));   {will be -1 since 'Third' item does not exit}
  Label1.Caption := 'The position of the ''Second'' element is ' +
     IntToStr(Mult.Postion('Second'));  {will be 0, TMult positions start with 0}
end;


Assign example

Assign Method Example

The following program code demonstrates the use of the TMult assign method to assign listbox items (TStrings) to a TMult:

  1. Start a new application.

  2. Drop one listbox, one memo and one button on the form. Arrange controls as in the figure below.

  3. Copy the following code to the Button1.OnClick event:
    procedure TForm1.Button1Click(Sender: TObject);
var
  Mult1: TMult;
  Subscript: string;
begin
  Mult1 := TMult.Create(Form1);    //Create Mult1. Make Form1 its owner

  ListBox1.Items.Add('One');       //Fill listbox with some strings
  ListBox1.Items.Add('Two');
  ListBox1.Items.Add('Three');
  ListBox1.Items.Add('Four');
  ListBox1.Items.Add('Five');

  Mult1.Assign(ListBox1.Items);    //assign (copy) listbox strings to Mult

  Memo1.Font.Name := 'Courier';    //configure memo box for better display
  Memo1.Lines.Clear;
  Memo1.Lines.Add('TStrings assigned:');

  Subscript := '';                 //set a starting point
  repeat
    Subscript := Mult1.Order(Subscript, 1);  //get next Mult element
    if Subscript <> '' then        //if not the end of list
      Memo1.Lines.Add(Format('%10s', [Subscript]) + ' - ' + Mult1[Subscript])                  //display subscript - value
  until Subscript = '';            //stop when reached the end
end;
  4. Run the project and click on the button.

    Expected output:

Assign Method Example

The following program code demonstrates the use of the TMult assign method to assign one TMult to another:

  1. Start a new application.

  2. Drop one memo and one button on the form. Arrange controls as in the figure below.

  3. Copy the following code to the Button1.OnClick event:
    procedure TForm1.Button1Click(Sender: TObject);
var
  Mult1, Mult2: TMult;
  Subscript: string;
begin
  Mult1 := TMult.Create(Form1);    //Create Mult1. Make Form1 its owner
  Mult2 := TMult.Create(Form1);    //Create Mult2. Make Form1 its owner

  Mult1['First'] := 'One';         //Fill Mult1 with some strings
  Mult1['Second'] := 'Two';
  Mult1['Third'] := 'Three';
  Mult1['Fourth'] := 'Four';
  Mult1['Fifth'] := 'Five';

  Mult2.Assign(Mult1);             //assign (copy) Mult1 strings to Mult2

  Memo1.Font.Name := 'Courier';    //configure memo box for better display
  Memo1.Lines.Clear;
  Memo1.Lines.Add('TMult assigned:');

  Subscript := '';                 //set a starting point
  repeat
    Subscript := Mult2.Order(Subscript, 1);  //get next Mult element
    if Subscript <> '' then        //if not the end of list
      Memo1.Lines.Add(Format('%10s', [Subscript]) + ' - ' + Mult2[Subscript])                  //display subscript - value
  until Subscript = '';            //stop when reached the end
end;
  4. Run the project and click on the button.

    Expected output:

TMult Assign Method Example


RPCVersion Property

Example

Applies to

TRPCBroker component

Declaration

property RPCVersion: string

Description

This property is a published string type property used to pass the version of the RPC. This can be useful for backward compatibility.

As you introduce new functionality into an existing RPC, your RPC can branch into different parts of the code based on the value of the RPCVersion property. The Broker sets the XWBAPVER variable on the server to the contents of the RPCVersion property. This property cannot be empty and defaults to "0" (zero).


Last example

Last Property Example

The following program code displays the subscript and value of the last item in a Mult variable in the caption of a label when the user clicks the GetLast button:

procedure TForm1.GetLastClick(Sender: TObject);
var
  Mult: TMult;
  Subscript: string;
begin
  Mult := TMult.Create(Form1);      {Create Mult. Make Form1 its owner}
  Mult['Fruit'] := 'Apple';
  Mult['Vegetable'] := 'Potato';    {Store element pairs one by one}
  Label1.Caption := 'The subscript of the last element: ' + Mult.Last +
    ', and its value: ' + Mult[Mult.Last];
end;


REMOTE PROCEDURE File

The RPC Broker consists of a single global that stores the REMOTE PROCEDURE file:

File # File Name Global Location

8994 REMOTE PROCEDURE ^XWB(8994,

This is the common file used by all applications to store all remote procedure calls accessed via the Broker. All RPCs used by any site-specific client/server application software using the RPC Broker interface must be registered and stored in this file.

This file is used as a repository of server-based procedures in the context of the Client/Server architecture. By using the Remote Procedure Call (RPC) Broker, applications running on client workstations can invoke (call) the procedures in this file to be executed by the server and the results are returned to the client application.

The RPC subfield (#19.05) of the OPTION File (#19) points to RPC field (#.01) of the REMOTE PROCEDURE file (#8994).


ZDEBUG

A command used to enable or disable debug mode in Digital Standard M (DSM):

>ZDEBUG ON (turns on debugging)

>ZDEBUG OFF (turns off debugging)


ClearParameters Property

Example

Applies to

TRPCBroker component

Declaration

property ClearParameters: Boolean;

Description

This property gives the developer the option to clear the Param property following every invocation of the Call, strCall, or the lstCall methods. Setting ClearParameters to True clears the Param property.

Simple assignment of True to this property clears the Param property after every invocation of the Call, strCall, and lstCall methods. Thus, the parameters need only be prepared for the next call without being concerned about what was remaining from the previous call. By setting ClearParameters to False, the programmer can make multiple calls with the same Param property. It is also appropriate to set this property to False when a majority of the parameters in the Param property should remain the same between calls. However, minor changes to the parameters can still be made.

You can use the Broker Programmer Preferences Editor (BrokerProgPref.Exe) to set the default value for this property when you add a TRPCBroker component to your form.


Results Property

Example

Applies to

TRPCBroker component

Declaration

property Results: TStrings

Description

This property contains the results of a Call method. In the case where the RPC returns a single value, it will be returned in Results[0]. If a call returns a list of values, the Results property will be filled in the order the list collates on the server. The Results property can only contain values of array elements – subscripts are not returned.

For example:

On the server, the M routine constructs the list in the following sequence:

S LIST("CCC")="First"
S LIST(1)="Second"
S LIST("AAA")="Third"
S LIST(2)="Fourth"

Before Broker returns the list to the client, M will re-sort it in alphabetical order:

LIST(1)="Second"
LIST(2)="Fourth"
LIST("AAA")="Third"
LIST("CCC")="First"

On the client, the Results property will contain the following:

RPCBroker1.Results[0]=Second
RPCBroker1.Results[1]=Fourth
RPCBroker1.Results[2]=Third
RPCBroker1.Results[3]=First


Subscript Method

Example

Applies to

TMult component

Declaration

function Subscript(const Position: longint): string;

Description

The Subscript method takes the numeric position of an item in a TMult variable and returns its string subscript. If TMult is empty, or the Position is greater than the number of items in the list, an empty string will be returned.

The Subscript and Position methods are the reciprocals of each other.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TMult component.


TParams Method

TParams

Assign


Value

Value Property

Example

Applies to

TParamRecord component

Declaration

property Value: string;

Description

Use this property to pass to the server either a single string or a single variable reference, depending on the PType.


IP Address

The Internet Protocol (IP) address is the network interface address for a client workstation, server, or device.


TRPCBroker Methods

TRPCBroker

Call

CreateContext

lstCall

strCall


TParamType

Unit
TRPCB

Declaration

TParamType = (literal, reference, list, undefined);

Description

The TParamType type defines the possible values of the RPC parameter type (PType property of TParamRecord component).

Use of the undefined TParamType in applications is not supported. It exists for the RPC Broker’s internal use only.


DebugMode Property

Applies to

TRPCBroker component

Declaration

property DebugMode: Boolean;

Description

This property controls how the server process should be started. The default setting is False.

A setting of False starts the server in the usual manner, as a background process.

For debugging purposes, it can be very helpful to set break points, run the server process interactively, and step through the execution. For those situations, set this property to True. When the TRPCBroker component connects with this property set to True, you get a dialog window indicating your workstation Internet Protocol (IP) address and the port number.

At this point you should switch over to the server, enter any break points that you wish, issue the debug command (e.g., ZDEBUG in DSM), and start the following server process:

>D EN^XWBTCP

You will be prompted for the workstation Internet Protocol (IP) address and the port number. After entering the information, switch over to the client application and click on the OK button of the dialog window.

For more information, see How to Debug Your Application.


Mult Example

The following program code demonstrates how the Mult property can be used to pass several data elements to the server in one parameter:

procedure TForm1.Button1Click(Sender: TObject);
begin
  with RPCBroker1 do begin
    Param[0].PType :=list;
    Param[0].Mult['"NAME"'] := 'DOE,JOHN';
    Param[0].Mult['"SSN"'] := '123456789';
    RemoteProcedure := 'SETUP PATIENT INFO';
    Call;
  end;
end;

Assuming variable P1 is used on the server to receive this array, it would look like the following:

P1("NAME")=DOE,JOHN
P1("SSN")=123456789


strCall Method

Example

function strCall: string;

This method executes a remote procedure on the server and returns the results as a value of a function. The strCall method expects the name of the remote procedure and its parameters to be set up in the RemoteProcedure and Param properties respectively. The Results property is not affected by this call. If ClearParameters is True, then the Param property is cleared after the call finishes.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.

Whenever the Broker makes a call to the server, the cursor is automatically changed to the hourglass symbol as seen in other Microsoft compliant software.


Call Example

The following program code demonstrates the use of the Call method in a hypothetical example of bringing back demographic information for a patient and then displaying the results in a memo box:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RPCBroker1.RemoteProcedure := 'GET PATIENT DEMOGRAPHICS';
  RPCBroker1.Param[0].Value := 'DFN';
  RPCBroker1.Param[0].PType := reference;
  RPCBroker1.Call;
  Memo1.Lines := RPCBroker1.Results;
end;


legend

Accessibility

Run-time only


Windows Registry

Applications built with Version 1.1 of the Broker will now use the Windows Registry to store the available servers and ports accessed via the Broker.

The Windows Registry replaces the [RPCBroker_Servers] section of the VISTA.INI file. The VISTA.INI file will no longer be used by applications built with Version 1.1 of the Broker. However, this file will continue to be used by applications built using version 1.0 of the Broker (e.g., PCMM). During the installation of the Broker relevant data from the VISTA.INI file will be moved to the Windows Registry. Subsequent reads and writes will be done via the Registry.

The VISTA.INI file created with Broker V. 1.0 must not be removed from the Windows directory on the client workstation. It is still required for 16-bit Broker-based applications created using version 1.0 of the Broker (e.g., PCMM).


Order Method

Example

Applies to

TMult component

Declaration

function Order(const StartSubscript: string; Direction: integer): string;

Description

The Order method works very similar to the $ORDER function in M. Using the Order method you can traverse through the list of elements in the Mult property of an RPC parameter.

The StartSubscript parameter is the subscript of the element whose next or previous sibling will be returned. If the Direction parameter is a positive number, then the subscript of the following element will be returned, while if it’s 0 or negative, then the predecessor’s subscript will be returned. If the list is empty or there are no more elements beyond the StartSubscript parameter, then empty string will be returned. You can use the empty string as a StartSubscript parameter, then, depending on the Direction parameter, you will get the subscript of the first or the last element in the list.

There are some important differences between this method and the $ORDER function in M. Unlike the $ORDER function, the Order method requires both parameters to be passed in. If the StartSubscript parameter is not an empty string, it must be equal to one of the subscripts in the list, otherwise an empty string will be returned. It is case sensitive. Unlike arrays in M, elements in TMult may or may not be in alphabetical order, depending on the Sorted property, so Order may not return the next or previous subscript in collating sequence.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TMult component.


Results Example

The following program code demonstrates using the Results property:

procedure TForm1.btnSendClick(Sender: TObject);
begin
  RPCBroker1.ClearResults := True;  {clears Results between calls}

  {the following code returns a single value}
  RPCBroker1.RemoteProcedure := 'SEND BACK SOME SINGLE VALUE';
  RPCBroker1.Call;
  Label1.Caption := 'Value returned is: ' + RPCBroker1.Results[0];

  {the following code returns several values}
  RPCBroker1.RemoteProcedure := 'SEND BACK LIST OF VALUES';
  RPCBroker1.Call;
  ListBox1.Items := RPCBroker.Results;
end;


Param Example

The following program code demonstrates how the Param property of a TRPCBroker component is referenced and filled with two parameters that the remote procedure expects:

procedure TForm1.Button1Click(Sender: TObject);
begin
  {first parameter is a single string}
  RPCBroker1.Param[0].Value := '05/01/97';
  RPCBroker1.Param[0].PType := literal;
  {second parameter is a list}
  RPCBroker1.Param[1].Mult['"NAME"'] := 'SMITH,JOHN';
  RPCBroker1.Param[1].Mult['"SSN"'] := '123-45-6789';
  RPCBroker1.Param[1].PType := list;
end;


TParamRecord Properties

TParamRecord

Mult

PType

Value


(Untitled)

Connect in Delphi IDE

Enables or disables the connection to the M server from within the Borland Integrated Development Environment (IDE). Disabling this is useful when you are developing in an environment without a connection to an M server, because an attempt is made to connect to the Server (if enabled) when certain TRPCBroker component properties are edited.


Sorted example

Sorted Property Example

The following program code demonstrates the effect the Sorted property has on a TMult variable. Notice that setting Sorted back to False does not revert the list to its unsorted order:

  1. Start a new application.

  2. Drop one memo and one button on the form. Arrange controls as in the figure below.

  3. Copy the following code to the Button1.OnClick event:
    procedure TForm1.Button1Click(Sender: TObject);
var
  Mult1: TMult;
  Subscript: string;
begin
  Mult1 := TMult.Create(Form1);    //Create Mult1. Make Form1 its owner

  Mult1['First'] := 'One';         //Fill Mult1 with some strings
  Mult1['Second'] := 'Two';
  Mult1['Third'] := 'Three';
  Mult1['Fourth'] := 'Four';
  Mult1['Fifth'] := 'Five';

  Memo1.Font.Name := 'Courier';    //configure memo box for better display
  Memo1.ScrollBars := ssVertical;
  Memo1.Lines.Clear;
  Memo1.Lines.Add('Natural order:');

  Subscript := '';                 //set a starting point
  repeat
    Subscript := Mult1.Order(Subscript, 1);  //get next Mult element
    if Subscript <> '' then                  //if not the end of list
      Memo1.Lines.Add(Format('%10s', [Subscript]) + ' - ' + Mult1[Subscript])                  //display subscript - value
  until Subscript = '';            //stop when reached the end

  Mult1.Sorted := True;             //list will now be sorted alphabetically
  Memo1.Lines.Add('');
  Memo1.Lines.Add('Sorted order:');

  Subscript := '';                 //set a starting point
  repeat
    Subscript := Mult1.Order(Subscript, 1);  //get next Mult element
    if Subscript <> '' then                  //if not the end of list
      Memo1.Lines.Add(Format('%10s', [Subscript]) + ' - ' + Mult1[Subscript])                  //display subscript - value
  until Subscript = '';            //stop when reached the end

  Mult1.Sorted := False;           //existing entries will remain in sorted order
  Memo1.Lines.Add('');
  Memo1.Lines.Add('Unsorted order:');

  Subscript := '';                 //set a starting point
  repeat
    Subscript := Mult1.Order(Subscript, 1);  //get next Mult element
    if Subscript <> '' then                  //if not the end of list
      Memo1.Lines.Add(Format('%10s', [Subscript]) + ' - ' + Mult1[Subscript])                  //display subscript - value
  until Subscript = '';            //stop when reached the end

end;
  4. Run project and click on the button.

    Expected output:

Sorted Property Example

You may have to scroll up and down to see all of the output.


ListenerPort Example

The following program code demonstrates using the ListenerPort property:

procedure TForm1.btnConnectClick(Sender: TObject);
begin
  RPCBroker1.ListenerPort := 9001;
  RPCBroker1.Connected := True;
end;


Value Example

The following program code demonstrates a couple of different uses of the Value property. Remember that each Param[x] element is really a TParamRecord-type component.

procedure TForm1.Button1Click(Sender: TObject);
begin
  with RPCBroker1 do begin
    RemoteProcedure := 'SET NICK NAME';
    Param[0].Value := 'DUZ';             {A variable reference}
    Param[0].Ptype := reference;
    Param[1].Value := edtNickName.Text;  {A string}
    Param[1].Ptype := literal;
    Call;
  end;
end;


DNS

The Domain Name Service (DNS) is a distributed database that maps names to their Internet Protocol (IP) addresses or IP addresses to their names. A query to this database is used to resolve names and IP addresses.


TRPCBroker Properties

TRPCBroker Legend

ClearParameters

ClearResults

Connected

DebugMode

ListenerPort

Param

RemoteProcedure

Results

RPCTimeLimit

RPCVersion

Server


First example

First Property Example

The following program code displays the subscript and value of the first item in a Mult variable in the caption of a label when the user clicks the GetFirst button:

procedure TForm1.GetFirstClick(Sender: TObject);
var
  Mult: TMult;
  Subscript: string;
begin
  Mult := TMult.Create(Form1);      {Create Mult. Make Form1 its owner}
  Mult['Fruit'] := 'Apple';
  Mult['Vegetable'] := 'Potato';    {Store element pairs one by one}
  Label1.Caption := 'The subscript of the first element: ' + Mult.First + ', and its value: ' + Mult[Mult.First];
end;


PType Example

The following program code demonstrates a couple of different uses of the PType property. Remember that each Param[x] element is really a TParamRecord-type component.

procedure TForm1.Button1Click(Sender: TObject);
begin
  with RPCBroker1 do begin
    RemoteProcedure := 'SET NICK NAME';
    Param[0].Value := 'DUZ';
    Param[0].PType := reference;
    Param[1].Value := edtNickName.Text;
    Param[1].PType := literal;
    Call;
  end;
end;


$JOB

Contains your operating system job number.

On DSM for OpenVMS systems, this is the process identification (PID) number of your process.

On DSM for DEC OSF/1 systems, the job number is the PID of the child process created when you enter the DSM command.


Count Property

Example

Applies to

TMult component

Declaration

property Count: Word;

Description

The Count property contains the number of items in a TMult component. If TMult component is empty, Count will be zero.


First Property

Example

Applies to

TMult component

Declaration

property First: string;

Description

The First property contains the subscript of the first item in a TMult component. The first item is always in the 0th Position. You can think of the First property as a short cut to executing the TMult.Order(‘’,1) method. If a TMult variable does not contain any items, the First property will be empty.


TParamRecord Example

The following program code demonstrates how you can use a TParamRecord variable to save a copy of a single parameter of a TRPCBroker component. This example assumes that prior to calling this procedure, a TRPCBroker variable has been created and some parameters have been set up. Pay close attention to how properties are copied one at a time. This is the only way that a separate copy could be created. If you try to simply assign one of the TRPCBroker parameters to the TParamRecord variable, you’ll simply re-point the TParamRecord variable to that parameter:

procedure TForm1.Button1Click(Sender: TObject);
var
  ParamRecord: TParamRecord;
begin
  ParamRecord := TParamRecord.Create(Form1);  {Create ParamRecord. Make Form1 its owner}
  ParamRecord.Value := RPCBroker.Param[0].Value;  {Store properties one at a time}
  ParamRecord.PType := RPCBroker.Param[0].PType;
  ParamRecord.Mult.Assign(RPCBroker.Param[0].Mult);  {This is how to copy a Mult }
end;


(Untitled)

ListenerPort

Sets the ListenerPort property of a TRPCBroker component to the specified value when you add one to a form.


Connected Property

Example

Applies to

TRPCBroker component

Declaration

property Connected: Boolean;

Description

This property connects your application to the server:

  • Setting this property to True connects the application to the server

  • Setting it to False disconnects the application from the server

It is not necessary for your application to manually establish a connection to the server. This version of the Broker automatically connects and disconnects from the server. When you invoke an RPC, if a connection has not already been established, one will be established for you. However, a user will not be able to run your RPC unless a context has been created with the CreateContext method.

There are other advantages to establishing a connection manually. You can check if a connection is established, and branch accordingly depending on whether a connection was established or not. One good place to do this is in your application form's OnCreate event. For that event, you could include code like the following:

try
RPCBroker1.Connected:=True;
except
On EBrokerError do
begin
ShowMessage('Connection to server could not be established!');
Application.Terminate;
end;
end;

This code sets the TRPCBroker component's Connected property to True to establish a connection. If a Broker exception (i.e., EBrokerError) was raised (in which case the connection wasn't established), it provides a message to the user and calls the Terminate method to exit.

To verify that your application is connected to the server, check the value of the Connected property.

If a connected TRPCBroker component is destroyed (when the application is closed, for example), that component will first disconnect from the server. However, for programming clarity, it is advisable to disconnect your application from the server manually by setting the Connected property to False.

If your application uses more than one Broker component, you should be aware of the component's connect and disconnect behavior.


RPCVersion Example

In the following example, an RPC is first called with two parameters that will be added together and the sum returned to the client. Again, this same RPC is called with the same parameters, however, this time it uses a different RPC version value. Thus, the two numbers are simply concatenated together and the resulting string is returned:

On the client:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RPCBroker1.ClearResults := True;      {make sure the results get cleared}
  RPCBroker1.ClearParameters := False;  {just re-use the same parameters}
  RPCBroker1.RemoteProcedure := 'MY APPLICATION REMOTE PROCEDURE';
  RPCBroker1.Param[0].Value := '333';
  RPCBroker1.Param[0].PType := literal;
  RPCBroker1.Param[1].Value := '444';
  RPCBroker1.Param[1].PType := literal;
  RPCBroker1.Call;
  Label1.Caption := 'Result of the call: ' + RPCBroker1.Results[0];  {the result will be 777}
  RPCBroker1.RPCVersion := '2';
  RPCBroker1.Call;
  Label2.Caption := 'Result of the call: ' + RPCBroker1.Results[0];  {the result will be 333444}
end;

On the server:

TAG(RESULT,PARAM1,PARAM2)	;Code for MY APPLICATION REMOTE PROCEDURE
IF XWBAPVER<2 SET RESULT=PARAM1+PARAM2
ELSE  SET RESULT=PARAM1_PARAM2
QUIT RESULT


Sorted Property

Example

Applies to

TMult component

Declaration

property Sorted: Boolean;

Description

The value of the Sorted property determines the order of the items in a TMult variable. If Sorted is True, the items are sorted in ascending order of their string subscripts. If Sorted is False (default), the items are unsorted, and will appear in the order they were added. Keep in mind that changing Sorted from False to True will irreversibly sort the list so that changing Sorted back to False will not put the list back in its original order, unless the original order was already sorted of course.


Assign Method

Example

Applies to

TMult component

Declaration

procedure Assign(Source: TPersistent);

Description

The Assign method for a TMult component takes either a TStrings, a TStringList, or another TMult. In the case where the source is a TMult, the owner of the Assign method gets the exact copy of the source with all string subscripts and values. In the case where the source is a TStrings or a TStringList, the items are copied such that the strings property of each item becomes the Value, while the index becomes the subscript in the string form.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TMult component.


TRPCBroker Example

The following example demonstrates how a TRPCBroker component can be used to connect to the server, execute various remote procedures, return the results and finally disconnect from the server. This example assumes that a TRPCBroker component already exists on the form:

procedure TForm1.Button1Click(Sender: TObject);
begin
  try
    RPCBRoker1.Connected := True;                          {connect to the server}
    RPCBroker1.RemoteProcedure := 'SOME APPLICATION RPC';  {assign RPC name}
    RPCBroker1.Call;                                       {make the call}
    ListBox1.Items := RPCBroker1.Results;                  {display results}
    RPCBroker1.Connected := False;                         {disconnect from the server}
  except
    {put error handling code here}
  end;
end;


ClearResults Property

Example

Applies to

TRPCBroker component

Declaration

property ClearResults: Boolean;

Description

This property gives the developer the option to clear the Results property prior to every invocation of the Call method. The strCall and lstCall methods are unaffected by this property. Setting ClearResults to True clears the Results property.

If this property is True, then the Results property is cleared before every invocation of the Call method, thus, assuring that only the results of the last call are returned. Conversely, a setting of False accumulates the results of multiple calls in the Results property.

You can use the Broker Programmer Preferences Editor (BrokerProgPref.Exe) to set the default value for this property when you add a TRPCBroker component to your form.


Param property

Param Property (available at run-time only)

Example

Applies to

TRPCBroker component

Declaration

property Param: TParams;

Description

This property is available at run-time only. It holds all of the parameters that the application needs to pass to the remote procedure using the Call, strCall, or lstCall methods.

Param is a zero-based array of TParamRecord. You don't need to explicitly allocate any memory for the Param property. Simple reference to an element or a value assignment ( := ) dynamically allocates memory as needed. You should start with the 0th element and proceed in sequence. Do not skip elements.

Each element in the Param array has the following properties:

Mult
PType
Value

Passing multiple parameters of PType list in one remote procedure call ( RPC) is not supported at this time. Only one list parameter can be passed to an RPC, and it must be the last parameter in the actual list.

The Param relationship to the TRPCBroker component is as follows:

The TRPCBroker component contains the Param property (i.e., TParams component).

The TParams component contains the ParamArray property (array [I:integer]: TParamRecord component).

The TParamRecord component contains the Mult property (i.e., TMult component).

The TMult component contains the MultArray property (array[S: string]: string).

The MultArray property internally uses a TStringList in which each element’s object is a TString.

If the remote procedure on the server does not require any incoming parameters, applications can pass an empty Param property. The client application merely sets the RemoteProcedure property and makes the call. If the Param property retains a value from a previous call, it can be cleared using the ClearParameters property. Thus, it is possible to make a call without passing any parameters.

The following restrictions apply with the Param property:

1. You are not allowed to "skip" passing parameters, such as TAG^ROUTINE(1,,3), where you can skip passing the second parameter in DSM code. If you have fewer elements in your Param array than exist as input parameters in your RPC, the subsequent parameters will not be passed to the RPC.

2. Passing multiple array parameters in one remote procedure call is not supported at this time. Only one array parameter can be passed to an RPC, and it must be the last parameter in the actual list.


Subscript example

Subscript Method Example

The following program code demonstrates how to get the subscript of an item in a TMult variable:

procedure TForm1.Button1Click(Sender: TObject);
var
  Mult: TMult;
begin
  Mult := TMult.Create(Form1); {Create Mult. Make Form1 its owner}
  Label1.Caption := 'The subscript of the item at position 1 is ' +
     Mult.Subscript(1);        {will be empty since the list is empty}
  Mult['Second'] := 'Two';
  Label1.Caption := 'The subscript of the item at position 1 is ' +
     Mult.Subscript(1);        {will be empty. Only one item in list so far at 0th position}
  Mult['Third'] := 'Three';
  Label1.Caption := 'The subscript of the item at position 1 is ' +
     Mult.Subscript(1);        {will be Third}
end;


lstCall Method

Example

procedure lstCall(OutputBuffer: TStrings);

This method executes a remote procedure on the server and returns the results into the passed TStrings- or TStringList-type variable, which you create outside of the call. It is important to free the memory later. lstCall expects the name of the remote procedure and its parameters to be set up in the RemoteProcedure and Param properties respectively. The Results property is not affected by this call. If ClearParameters is True, then the Param property is cleared after the call finishes.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.

Whenever the Broker makes a call to the server, the cursor is automatically changed to the hourglass symbol as seen in other Microsoft compliant software.


TMult Methods

TMult

Assign

Order

Position

Subscript


PType

PType Property

Example

Applies to

TParamRecord component

Declaration

property PType: TParamType;

Description

(PType is a property of the TParamRecord used in the Param property.)

This property determines how the parameter will be interpreted and handled by the Broker.

Value Definition

literal The server receives the contents of the corresponding Value property as one string or one number.

reference The server receives the contents of the corresponding Value property as a name of a variable defined on the server. Using indirection, the Broker on the server will resolve this parameter before handing it off to the application.

list This value is used whenever an application wants to send a list of values to the server. In this case the contents of the corresponding Mult property is sent, while the Value property is ignored.

undefined The Broker uses this value internally. It should not be used by an application.

For instance, if you need to pass an empty string to the remote procedure call (RPC), the Value property should be set to '' (i.e., null) and the PType to literal. Using reference, a programmer can pass an M variable (e.g., DUZ) without even knowing its value. However, If the M variable being referenced is not defined on the server, a run-time error will occur. When passing a list to an RPC: set the PType to list, populate the Mult property, and don't put anything into the Value property (in this case Value is ignored).


CreateContext Example

The following program code demonstrates the use of the CreateContext method:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RPCBroker1.Connected := True;
  if RPCBroker1.CreateContext('MY APPLICATION') then
    Label1.Caption := 'Context MY APPLICATION was successfully created.'
  else
    Label1.Caption := 'Context MY APPLICATION could not be created.';
end;


Connected Example

The following program code sets the Connected property to True:

procedure TForm1.btnConnectClick(Sender: TObject);
begin
  RPCBroker1.Server := txtServer.Text;
  RPCBroker1.ListenerPort := StrToInt(txtPort.Text);
  RPCBroker1.Connected := True;
end;

The Server and ListenerPort properties must be set at design or run-time before setting the Connected property to True.


Last Property

Example

Applies to

TMult component

Declaration

property Last: string;

Description

The Last property contains the subscript of the last item in a TMult component. The last item is always in count-1 Position. You can think of the Last property as a short cut to executing the TMult.Order(‘’,-1) method. If a TMult variable does not contain any items, the Last property will be empty.


TParams Example

The following program code demonstrates how a TParams component can be used to save off the TRPCBroker component parameters and restore them later:

procedure TForm1.Button1Click(Sender: TObject);
var
  SaveParams: TParams;
  SaveRemoteProcedure: string;
begin
  SaveParams := TParams.Create(Self);  {create holding variable with Form1 as owner}
  SaveParams.Assign(RPCBroker1.Param);  {save parameters}
  SaveRemoteProcedure := RPCBroker1.RemoteProcedure;
  RPCBroker1.RemoteProcedure := 'SOME OTHER PROCEDURE';
  RPCBroker1.ClearParameters := True;
  RPCBroker1.Call;
  RPCBroker1.Param.Assign(SaveParams);  {restore parameters}
  RPCBroker1.RemoteProcedure := SaveRemoteProcedure;
  SaveParams.Free;  {release memory}
end;


Call Method

Example

procedure Call;

This method executes a remote procedure on the server and returns the results in the Results property. Call expects the name of the remote procedure and its parameters to be set up in the RemoteProcedure and Param properties respectively. If ClearResults is True, then the Results property is cleared before the call. If ClearParameters is True, then the Param property is cleared after the call finishes.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.

Whenever the Broker makes a call to the server, the cursor is automatically changed to the hourglass symbol as seen in other Microsoft compliant software.


Server Property

Example

Applies to

TRPCBroker component

Declaration

property Server: string

Description

This property contains the name or Internet Protocol (IP) address of the server computer. If the name is used instead of the IP address, Windows Winsock should be able to resolve it. Winsock can resolve a name to an IP address either through the Domain Name Service (DNS) or by looking it up in the HOSTS file on the client workstation. In the case where the same name exists in the DNS and in the HOSTS file, the HOSTS file entry takes precedence. Changing the name of the server while the TRPCBroker component is connected disconnects the TRPCBroker component from the previous server.

You can use the Broker Programmer Preferences Editor (BrokerProgPref.Exe) to set the default value for this property when you add a TRPCBroker component to your form.


CreateContext Method

Example

function CreateContext(strContext: string): boolean;

You can use the CreateContext method of the TRPCBroker component to create a context for your application. To create context, pass an option name in the strContext parameter. If the function returns True, a context was created, and your application can use all RPCs entered in the option's RPC multiple. If the TRPCBroker component is not connected at the time context is created, a connection will be established. If for some reason a context could not be created, the CreateContext method will return False.

Since context is nothing more than a client/server “B”-type option in the OPTION file (#19), standard MenuMan security is applied in establishing a context. Therefore, a context option can be granted to user(s) exactly the same way as regular options are done using MenuMan. Before any RPC can run, it must have a context established for it to on the server. Thus, all RPCs must be registered to one or more “B”-type option(s). This plays a major role in Broker security.

A context can not be established for the following reasons:

  • The user has no access to that option

  • The option is temporarily out of order

An application can switch from one context to another as often as it needs to. Each time a context is created the previous context is overwritten.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TRPCBroker component.

Whenever the Broker makes a call to the server, the cursor is automatically changed to the hourglass symbol as seen in other Microsoft compliant software.


TParams Assign

Assign Method

Example

Applies to

TParams component

Declaration

procedure Assign(Source: TParams);

Description

The Assign method for a TParams component takes another TParams component parameter. The Assign method is useful for copying one TParams component to another. The entire contents of the passed in TParams component are copied into the owner of the assign method. The Assign method first deletes all of the parameters in the receiving component and then copies the parameters from the passed in component, creating a whole duplicate copy.

See RPC Limits for information about the size of parameters and results that can be passed to and returned from the TParams component.


RPCBMultPropGet Examples

C

RPCBMultPropGet(RPCBroker, 0, "Count", Value);

C++

MyInstance.RPCBMultPropGet(0, "Count", Value);

Visual Basic

Call RpcbMultPropGet(intRpcbHandle, 0, "Count", strResult)


RPCBMultSet Examples

C

RPCBMultSet(RPCBroker, 0, "1", "12/19/97");

C++

MyInstance.RPCBMultSet(0, "1", "12/19/97");

Visual Basic

Call RpcbMultSet(intRpcbHandle, 0, "1", "12/19/97")


RPCBFree Examples

C

RPCBFree(RPCBroker); //Destroy TRPCBroker component instance

Visual Basic

RpcbFree (intRpcbHandle)


RPCBParamSet Examples

C

RPCBParamSet(RPCBroker, 0, reference, "DUZ");

C++

MyInstance.RPCBParamSet(0, reference, "DUZ");

Visual Basic

Call RpcbParamSet(intRpcbHandle, 0, literal, Text3.Text)


RPCBPropGet Examples

C

RPCBPropGet(RPCBroker, "Connected", Value);

C++

MyInstance.RPCBPropGet("Connected", Value);

Visual Basic

Call RpcbPropGet(intRpcbHandle, "Server", strResult)


RPCBMultItemGet Examples

C

RPCBMultItemGet(RPCBroker, 0 , "0", Value);
// This corresponds to getting the value of PARAM[0].Mult["0"]

C++

MyInstance.RPCBMultItemGet(0 , "0", Value);

Visual Basic

Call RpcbMultItemGet(intRpcbHandle, 0,  "0", strResult)


RPCBCall Examples

C

RPCBCall(RPCBroker, Value);

C++

MyInstance.RpcbCall( strbuffer);
// where my instance is defined as an instance of TRPCBroker

Visual Basic

Call RpcbCall(intRpcbHandle, strBuffer)


DLL Function Reference

DLL Exported Functions

The following functions for TRPCBroker components are exported in BAPI32.DLL:

RpcbCall Execute an RPC.

RpcbCreate Create a TRPCBroker component.

RpcbCreateContext Create context.

RpcbFree Destroy a TRPCBroker component.

RpcbMultItemGet Get value of a Mult item in a Param.

RpcbMultPropGet Get value of a Mult property in a Param.

RpcbMultSet Set a Mult item in a Param to a value.

RpcbMultSortedSet Sorts a Mult Param property.

RpcbParamGet Get the value of a Param.

RpcbParamSet Set the value of a Param.

RpcbPropGet Get the value of a TRPCBroker component property.

RpcbPropSet Set the value of a TRPCBroker component property.


RPCBMultSortedSet Examples

RPCBMultSortedSet

C

RPCBMultSortedSet(RPCBroker, 0, 1);

C++

MyInstance.RPCBMultSortedSet(0, 1);

Visual Basic

Call RpcbMultPropGet(intRpcbHandle, 0, 1)


RPCBPropSet Examples

C

RPCBPropSet(RPCBroker, "ListenerPort", "9200");

C++

MyInstance.RPCBPropSet("ListenerPort", "9200");

Visual Basic

Call RpcbPropSet(intRpcbHandle, "Server", cboServer.Text)


RPCBCreateContext Examples

C

result = RPCBCreateContext(RPCBroker, "XWB EGCHO");
// where XWB EGCHO is a "B" (Broker) type option in the Option file.

C++

MyInstance.RPCBCreateContext("XWB EGCHO");
// where XWB EGCHO is a "B" (Broker) type option in the Option file.

Visual Basic

intResult = RpcbCreateContext(intRpcbHandle, "MY APPLICATION")
'where MY APPLICATION is a "B" (Broker) type option in the Option file.


RPCBCreate Examples

C

RPCBroker = RPCBCreate(); //create TRPCBroker component instance

Visual Basic

intRpcbHandle = RpcbCreate()


RPCBParamGet Examples

C

RPCBParamGet(RPCBroker, 0, PType, Value);
// where PType and Value are variables to retrieve values into

C++

MyInstance.RPCBParamGet(0, PType, Value);
// where PType and Value are variables to retrieve values into

Visual Basic

Call RPCBParamGet(intRpcbHandle, 0, PType, strResult)
' where PType and strResult are variables to retrieve values into


XWB GET VARIABLE VALUE Example

RPCBroker1.RemoteProcedure := 'XWB GET VARIABLE VALUE';
RPCBroker1.Param[0].Value :='DUZ';
RPCBroker1.Param[0].PType := reference;
try
    RPCBroker1.Call;
except
  On EBrokerError do
    ShowMessage('Connection to server could not be established!');
end;

ShowMessage('DUZ is '+RPCBroker1.Results[0]);


Splash Screen Example

VISTA Splash ScreenExample

uses
  Forms, Unit1 in 'Unit1.pas', SplVista;

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  SplashOpen;
  SplashClose(2000);
  Application.Run;
end.


GetServerInfo Example

procedure TForm1.btnConnectClick(Sender: TObject);
var
  strServer, strPort: string;
begin
  if GetServerInfo(strServer, strPort)<> mrCancel then begin {getsvrinfo}
    RPCBroker1.Server := strServer;
    RPCBroker1.ListenerPort := StrToInt(strPort);
    RPCBroker1.Connected := True;
  end; {getsvrinfo}
end;


M Emulation Examples

Piece Function

Piece3Str:=piece('123^456^789','^',3);

Translate Function

hiStr:=translate('HI','ABCDEFGHI','abcdefghi');


DisconnectMode Property

(being phased out)

Applies to

TRPCBroker component

Declaration

property DisconnectMode: enumerated;

Description

Enhancements to how the Broker manages multiple connections make this property unnecessary. Consequently, it is being phased out. For now it has been "demoted" from published to public declaration. This means that this property will no longer be visible in the Object Inspector, however, the application will still compile. At run-time it is ignored.

If your application uses more than one Broker component, you should be aware of the component's connect and disconnect behavior.

This property was used to set the mode that determines when your application disconnected from the server. It could be set to one of the following values:

ManualDisconnect: With this setting, the TRPCBroker did not try to disconnect from the server when it was destroyed. This setting was used when there were multiple Broker components in your application and it was not the last Broker component to be disconnected.

OnDestroy: This setting was used to disconnect your application from the server when the TRPCBroker component was destroyed. This was used if you only had a single Broker component or it would be the last component to be disconnected when you had multiple Broker components.

The DisconnectMode property that was made available with the RPC Broker Development Kit (BDK), released in October 1995, is now obsolete and slated for removal from the RPC Broker component (i.e., TRPCBroker).


Connect Disconnect Behavior

Component Connect/Disconnect Behavior

Connect

The first time one of the Broker components in your application connects, it will establish an actual connection with the server. The connection record will be added to the list of all active connections for your application. This list is internal to the application and is completely under the control of the Broker component and is transparent to you. If another Broker component tries to connect to the same server/port, the existing connection record will be found in the list and its socket will be shared. The new connection will also be added to this list. This process is repeated with each connection request.

Disconnect

When a Broker component disconnects, its connection record is removed from the internal list of active connections. If it happens to be the last record for the particular server/port combination, the connection is actually closed. This scheme provides the illusion of multiple connections without "clogging up" the server.


ConnectMode Property

(being phased out)

Applies to

TRPCBroker component

Declaration

property ConnectMode: enumerated;

Description

Enhancements to how the Broker manages multiple connections make this property unnecessary. Consequently, it is being phased out. For now it has been "demoted" from published to public declaration. This means that this property will no longer be visible in the Object Inspector, however, the application will still compile. At run-time it is ignored.

If your application uses more than one Broker component, you should be aware of the component's connect and disconnect behavior.

This property was used to set the mode that determines when your application connected to the server. It could be set to one of the following values:

AsNeeded: If the Broker component was not already connected to the server, this established a connection with the server when a call was made. This was the recommended setting. You can still manually connect the Broker component using the Connected property.

ManualConnect: Required the developer to manually connect to the server by setting the Connected property to True.

OnCreate: Connected to the server when the TRPCBroker component was created. This setting was ignored while in Delphi IDE.

The ConnectMode property that was made available with the RPC Broker Development Kit (BDK), released in October 1995, is now obsolete and slated for removal from the RPC Broker component (i.e., TRPCBroker).


Result Property

(removed)

Applies to

TRPCBroker component

Description

The Result property was ambiguous with Delphi's reserved Result variable (i.e., used to return values from functions) and has been removed from this version of the Broker. What previously was returned in the Result property should now be returned in the 0th element of the Results Property referenced as Results[0].

The Result property that was made available with the RPC Broker Development Kit (BDK), released in October 1995, has been removed from this version of the RPC Broker component (i.e., TRPCBroker).

Developer's should not just do a search and replace of the word "Result", however. In some cases the word "Result" being referenced can be Delphi's legitimate use of the reserved word.


ServerJob Property

(removed)

Applies to

TRPCBroker component

Declaration

property ServerJob: string

Description

The original intent of this read-only property was to contain the $JOB of the corresponding process on the server. However, the RPC Broker has never populated this property with a value, and it is not supported in the 32-bit version of the Broker. Therefore, this property has been removed from the TRPCBroker component.

The ServerJob property that was made available with the RPC Broker Development Kit (BDK), released in October 1995, has been removed from this version of the RPC Broker component (i.e., TRPCBroker).


Protocol Property

(removed)

Description

This property was originally put in the TRPCBroker component as a place holder for future development, however, it was never used. Thus, it has been removed from this version of the TRPCBroker component.

The Protocol property that was made available with the RPC Broker Development Kit (BDK), released in October 1995, has been removed from this version of the RPC Broker component (i.e., TRPCBroker).


max number

Maximum number of parameters which can be passed to the M server

The remote procedure calls (RPCs) become M DO procedures on the M server. Since RPCs are communicated to the M server through a message mechanism, additional information is included with the message.

Parameters are processed as PASCAL short strings with a maximum of 255 characters. Each parameter is encoded with a three character length plus a type character. Therefore, every parameter occupies length (parameter) + four. The maximum transmission at this time is 240 characters since additional header information is present with every RPC.

A theoretical maximum, where every parameter was length 1 would give number of parameters = 240/5 or 48 parameters. A single parameter (e.g., a long string) could not exceed 240 – 4, or 236 characters. Future support will be based on the PASCAL 32-bit string, which can, theoretically, reach 2 GB. Limitations on the M server will still limit this to far less, however.


max data

Maximum size of data which can be received in the Windows application from the M server

The M server can transmit very large buffers of data back to the Windows client. The Windows client receives the returned data from an RPC into a 32-bit PASCAL string. RPCs can be written on the M server so that they store their results in an M GLOBAL structure, which can span RAM and disk storage media. This GLOBAL storage could be quite large depending on the assigned system quotas to the M server process. The return of the RPC can deliver this quantity to the Windows client. The actual limit will depend on the capacity the Windows Operating System will allow the client to process. Tests on a 32 megabyte RAM system have allowed buffers of several megabytes of data to be transmitted from the M server to the Windows client.


time limits

RPC Time limits

A public read/write property (i.e., RPCTimeLimit) allows the application to change the network operation timeout prior to a call. This may be useful during times when it is known that a certain RPC, by its nature, can take a significant amount of time to execute. The value of this property is an integer that can not be less than 30 seconds nor greater that 32767 seconds. Care should be taken when altering this value, since the network operation will block the application until the operation finishes or the timeout is triggered.

There is also a Server time limit when for how long to stay connected when the client doesn't respond.


max size

Maximum size of array which can be passed to the M server

Although approximately only 240 characters can be sent to the M server as call parameters, a single array parameter can be passed in with greater capacity. The RPC can carry both literal and array parameters except that literal parameters are placed first and the single array last in order. Arrays are instantiated at the M server and are stored in a local array format. The maximum size will be dependent on the symbol space available to the M server process. The index size and the value size are subject to limitations as follows: Index and value each cannot exceed 255 – 3, or 252 characters approximately for each individual array elements.

At the time of this writing, 30 to 40 K arrays have easily been passed to the M server in a single RPC call.


Broker Errors

Broker Error Messages

The following list of errors/messages are Broker-specific and are not Winsock related:

Error/Message Name Number Description
Insufficient Heap XWB_NO_HEAP 20001 This is a general error condition indicating insufficient memory. It can occur when an application allocates memory for a variable. This error can occur for some of the following reasons:
  • Too many open applications

  • Low physical memory

  • Small virtual memory swap file (if dynamic, maybe low disk space)

  • User selecting too many records

Resolution: Common solutions to this error include the following:

  • Close some or all other applications

  • Install more memory

  • Increase the swap file size or, if dynamic, leave more free space on disk

  • Try working with smaller data sets

  • Reboot the workstation
M Error - Use ^XTER XWB_M_REJECT 20002 The server side of the application errored out. The error has been recorded by the Kernel error trap.

Resolution: Examine the Kernel error trap for more information and specific corrective actions.
Signon was not completed XWB_BadSignOn 20004 This error indicates the user did not successfully signon.

Resolution: Either the Access and Verify codes were incorrect or the user pressed the Cancel button on the signon window.
BrokerConnections list could not be created XWB_BldConnectList 20005 This error is a specific symptom of a low memory condition.

Resolution: Please refer to the "Insufficient Heap" error message for a more detailed explanation and corrective measures.
RpcVersion cannot be empty XWB_NullRpcVer 20006 This error occurs when an RPC does not have an associated version number. Each RPC must have a version number.

Resolution: Contact the developers responsible for the application software to take corrective action.
Remote procedure not registered to application XWB_RpcNotReg 20201 This error indicates the application attempted to execute an RPC which was not entered into the RPC multiple field in the REMOTE PROCEDURE file (#8994) for this application.

Resolution: The developers responsible for the application should be contacted.

As a "last resort" corrective measure, you may try to re-index the cross-reference on the RPC field (#.01) in the REMOTE PROCEDURE file (#8994) with the RPC field (#320) of the OPTION file (#19). Ideally, this should only be attempted during off or low system usage.