postmessage

Send a message from one component instance to another.

postmessage  Destination,MessageId,MessageData

The Destination is of the form: {InstancePath:}InstanceName

The InstancePath is a network connector string:

NetworkMnemonic: { HostId }{+PortNumber} |UserName||SymbolicName

Parameters

Parameters
Parameter Data Type Description
Destination String Component instance that will receive the message.
MessageId String Identifier for the message; must contain at least one non-blank character and be no more than 32 characters in total.
MessageData String Message data sent with the message. The amount of data that can be sent is limited only by the memory resources available on the machines.
InstancePath String Network connector string to the application running the target instance. If omitted, InstanceName is assumed to be in the current application.
InstanceName String Name of an instance in the component pool.
NetworkMnemonic String Three-letter connector code; usually TCP
HostId String Host name or IP address where the Uniface Router is running. If omitted, the default is localhost ( the current machine). The format of HostID determines the TCP protocol version to be used. For more information, see Host Identification for TCP/IP and TLS.
PortNumber String Port number on which the Uniface Router is listening. If omitted, the default value is 13001.
UserName String User name under which the target application is running
SymbolicName String Application identifier of an application registered with the Uniface Router

Return Values

Values returned in $status
Value Meaning
0 Message for InstanceName successfully placed in event queue; this does not mean that the message was actually delivered, only that it has been posted.
-2 InstanceName is not correct: field or variable not found, or the string is not a valid instance name.
-3 MessageId is not correct: field or variable not found, or the string is not a valid message identifier.
Values commonly returned by $procerror following postmessage
Value Error constant Meaning
-16 through -30 <UNETERR_*> Errors during network I/O.
-57 <UACTERR_NO_INSTANCE> The named instance cannot be found in the component pool. For example, the name is an empty string ("").
-159 <UACTERR_QUEUE> Message could not be delivered to requested queue.
-1105 <UPROCERR_INSTANCE> The instance name provided is not valid. For example, the argument contains incorrect characters. For more information, see newinstance.
-1107 <UPROCERR_PATH> The path name is not correct or the path does not exist, for example, no assignment is found for the path.
-1111 <UPROCERR_MESSAGE> The message identifier is not valid; the field or variable was not found, or the string is not a valid message identifier.

Use

Allowed in all component types.

Description

The postmessage statement sends a message to the specified component instance. It is typically used for asynchronous communication between component instances running in the same or in a different process. For example, it can be used for communication between master and detail component instances, or to a remote service.

Tip: If you need synchronous communication, you should use the activate statement.

Unlike the activate command, the postmessage command does not automatically create a new instance. The receiving instance must already exist; postmessage just posts the message to an event queue of the receiving instance.

Message Queuing and Dispatching

When a postmessage statement is encountered during ProcScript execution, the presence or absence of an InstancePath in the Destination parameter determines how the message is handled:

  • If an InstancePath is specified in the Destination, the message is first sent to the Uniface Router, which then dispatches it to the specified component instance. This may be a remote component running in a Uniface Server, a component running in a different application, or a component running in the same application as the sending instance.

    Communication is always asynchronous, regardless of whether the messages are handled in-process or by the Uniface Router.

  • If InstancePath is omitted, the receiving instance is assumed to be in the same process.

    In a client application, the message is placed in the Uniface message queue and delivered to the target component instance when the current ProcScript module or keystrokes are finished.

    In a Uniface Server, the message is converted to a synchronous send message. This is because the Uniface Server does not have the queuing functionality provided by the structure editor or the Uniface Router.

    Note:  A UTIMER component running in a Uniface Server actually runs in a separate thread from the main userver process, so this behavior is not applicable. For more information, see UTIMER.

Note:  When a postmessage statement is encountered in the Debugger, it is also treated synchronously, and the receiveMessage trigger of the target instance is activated immediately.

Message Reception

When the message reaches the top of the input queue, the receiveMessage trigger associated with receiving component is activated. This may be the component-level trigger or the application-level trigger.

  • The component-level receiveMessage trigger of the target instance is activated if it contains ProcScript.
  • The application-level receiveMessage trigger is activated if the component-level trigger is empty, or if the specified target instance is not found. The application is the one that is the target of InstancePath.
  • If the application-level trigger is empty, there is no further action.

The sending instance does not automatically receive an acknowledgment that the message has been received. If this behavior is required, an acknowledgment must be explicitly returned by the receiving instance. For example:

trigger receiveMessage
  postmessage $msginfo("SRC"),"MSG001", %\
  "Reply to sender: message received."
end; receiveMessage

Message Content

When a receiveMessage trigger is activated by postmessage, the $result ProcScript function contains the string "message" and the function $msginfo contains MessageId, MessageData, and other information about the message.

The information returned in $msginfo is available using the individual functions $instancename, $instancepath, $msgdata, $msgdst, $msgid, and $msgsrc. For more information, see $msginfo.

Communicating Between Master List and Detail Forms

A common construction in client applications is a parent component that displays a list of records, which has child components the enable the user to create new records or update existing ones. In the following example, the parent component (RCP_LIST) can have multiple child component instances of RCP_UPDATE (and RCP_NEW).

Master Component with Two Non-modal Components

Master form with list of recipes (RCP_LST), and two non-modal forms (RCP_UPDATE), each
    containing the details of a recipe

When a store is performed in one of the child instances, it uses postmessage to notify RCP_LIST that the recipe has been updated:

; RCP_UPDATE component
trigger  store 
store
if ($status <0)
   message $text(1500)
   rollback
   commit
else
   if ($status = 1)
     message $text(1723
   else
      commit
      if ($status < 0)
        rollback
        commit
      else
        message $text(1805)
; Statements added to default store trigger:
        postmessage "RCP_LIST", $componentname, RCP_NR.RECIPES Callout 1
        setformfocus "RCP_LIST" Callout 2
     endif
  endif
endif

end; store trigger
  1.  Send a message to RCP_LIST with the name of the current component as MessageId, and the primary key of the updated record (RCP_NR.RECIPES) as the MessageData.
  2.  Return focus to the list of recipes so that the user can quickly select another to edit.

The receiveMessage trigger of RCP_LIST handles messages from the instances and updates the list of recipes:

; RCP_LIST component
trigger  receiveMessage
RCP_NR = $msgdata Callout 3
if ( $msgid = "RCP_UPDATE" ) Callout 4
   reload/nolock "RECIPES"
endif
if ( $msgid = "RCP_NEW" ) Callout 5
   retrieve/x "RECIPES"
endif
if ( $msgid = "RCP_UPDATE" | $msgid = "RCP_NEW") Callout 6
   sort "RECIPES", "RCP_NAME:A"
   retrieve/o "RECIPES"
endif
end ; receivemMessage
  1.  Assign the record number provided in the message data to the RCP_NR field to use as the search profile.
  2.  If the sender was an instance of RCP_UPDATE, RPC_LIST, reload the data
  3.  If the sender was an instance of RCP_NEW, retrieve the new data
  4.  In either case, sort the data and make the updated or new occurrence the current one

Related Topics