3D PLM Enterprise Architecture |
Middleware Abstraction |
Sending a Backbone Simple Message to an ApplicationUsing the backbone to send a message without data |
Use Case |
AbstractThis article shows how to make two applications communicate, and how one of them can send a simple message, that is, a message that doesn't convey any data, to the other. |
This use case is intended to show you how an application can declare that it will send or receive messages, how to filter the messages to receive, and how to send and receive messages using the backbone objects of the System framework. The messages don't convey any data with them. Another use case also shown by CAASysBackboneBasic uses messages that convey data [1].
[Top]
CAASysBackboneBasic is a use case of the CAASystem.edu framework that illustrates the System framework capabilities.
[Top]
This use case illustrates two applications seen as processes. One behaves as a message sender, and the other as a message receiver. The message sender creates and sends a simple message. The message receiver receives it, and just acknowledge receipt of it using a trace. Both the message sender and the message receiver are simple processes launched from a main program.
The message sender connects to the backbone bus, declares itself, instantiates the message component and sends it. The message receiver needs to instantiate a message handler to receive the message. Such a message handler is a component that implements the CATIMessageReceiver interface. The message receiver connects to the backbone bus, declares itself, instantiates the message handler, associates itself with the message to receive and with the message handler, and enters a loop thanks to the CATICommunicator interface implemented by the backbone bus that the receiver can use to create the loop, and waits for the message. As soon as the message is sent, it is retrieved by the message handler that prints a trace to acknowledge receipt of the message.
The message is an instance of a component named CAASysSimpleMessage that implements the CATICommMsg interface, among others [2].
[Top]
To launch CAASysBackboneBasic, you will need to set up the build time environment, then compile CAASysBackboneBasic along with its prerequisites, set up the run time environment [3] in two different windows, and then execute the use case.
To execute the use case, type in the first window command line:
CAASysBackboneBasic receiver
And type in the second window command line:
CAASysBackboneBasic sender
[Top]
The CAASysBackboneBasic use case is made of several classes located in the CAASysBackboneBasic.m module of the CAASystem.edu framework:
Windows | InstallRootDirectory\CAASystem.edu\CAASysBackboneBasic.m\ |
Unix | InstallRootDirectory/CAASystem.edu/CAASysBackboneBasic.m/ |
where InstallRootDirectory
is the directory where the CAA CD-ROM
is installed.
[Top]
To create applications that send and receive a simple message, there are six main steps:
# |
Step |
---|---|
1 | Create the message sender |
2 | Send the message |
3 | Create the message handler component |
4 | Create the message receiver |
5 | Receive the message |
6 | Remove the message handler |
[Top]
The message sender is a process whose main program is contained in the CodeForSenderCase
global function.
int CodeForSenderCase() { // Retrieves an instance of a backbone bus (default bus) CATICommunicator * pICommunicator = NULL; pICommunicator = ::CATGetBackboneConnection(); ... // return if the backbone bus cannot be retrieved ... |
First, a connection to the backbone bus must be established. This is possible
thanks to the global function CATGetBackboneConnection
that returns
a pointer to the CATICommunicator interface.
... // Declares CAASysSenderAppli CATApplicationClass SenderApplicationId = "CAASysSenderAppli"; HRESULT rc = pICommunicator->Declare(SenderApplicationId); ... // return if the declaration fails CATApplicationClass ReceiverApplicationId = "CAASysReceiverAppli"; ... |
Once the connection is established, the message sender sets its application
class identifier and declares it to the backbone bus using the method Declare
.
[Top]
... if ( SUCCEEDED(rc) ) { CATICommMsg * pICommMsg =NULL; rc = ::CATInstantiateComponent("CAASysSimpleMessage", IID_CATICommMsg, (void**)&pICommMsg); if ( SUCCEEDED(rc) ) { rc = pICommunicator->SendRequest(ReceiverApplicationId, pICommMsg); pICommMsg->Release(); pICommMsg = NULL; } } pICommunicator->Release(); pICommunicator = NULL; ... // return } |
Now, the message sender can send a message. It first creates an instance of
the message component and retrieves a pointer to CATICommMsg on the
message component thanks to the CATCreateClassInstance
global
function. Then it sends the message using the SendRequest
method of
CATICommunicator, specifying the target message receiver and the message
to send.
[Top]
#include "CATBaseUnknown.h" //Needed to derive from CATBaseUnknown class CATICommMsg; class CAASysSimpleMessageHandler : public CATBaseUnknown { CATDeclareClass; public: CAASysSimpleMessageHandler(); virtual ~CAASysSimpleMessageHandler(); // CATIMessageReceiver Interface void HandleMessage(CATICommMsg * iMessage); private: CAASysSimpleMessageHandler(const CAASysSimpleMessageHandler &iObjectToCopy); }; |
The CAASysSimpleMessageHandler class belongs to a component, thanks to
the CATDeclareClass
macro, C++ derives from CATBaseUnknown,
and implements CATIMessageReceiver, whose single method is HandleMessage
.
Note that the copy constructor is set as private, and is not implemented in the
source file. This prevents the compiler from creating the copy constructor as
public without you know.
#include "CAASysSimpleMessageHandler.h" extern int EndConditionLoop; #include "TIE_CATIMessageReceiver.h" TIE_CATIMessageReceiver(CAASysSimpleMessageHandler); CATImplementClass(CAASysSimpleMessageHandler, Implementation, CATBaseUnknown, CATNull); CAASysSimpleMessageHandler::CAASysSimpleMessageHandler() {} CAASysSimpleMessageHandler::~CAASysSimpleMessageHandler() {} void CAASysSimpleMessageHandler::HandleMessage(CATICommMsg* iMessage) { // The process can be stopped EndConditionLoop ++; } |
The CAASysSimpleMessageHandler class states that it implements the CATIMessageReceiver
interface thanks to the TIE_CATIMessageReceiver
macro. The CATImplementClass
macro declares that the CAASysSimpleMessageHandler class is a component
main class thanks the Implementation
keyword, and that the
component OM-derives [4] from CATBaseUnknown.
Any component main class declared as an Implementation
must
C++-derive and OM-derive from the same class. HandleMessage
needs
only a simple implementation. It is called by the backbone bus and a pointer to
the message is passed. The action undertaken is to simply to make the receiver
get out of the loop by incrementing EndConditionLoop
.
Top]
The message receiver is a process whose main program is contained in the CodeForReceiverCase
global function.
int CodeForReceiverCase() { int ReturnCode = 1; CATIMessageReceiver * pIMessageReceiver = NULL; CATApplicationClass ReceiverApplicationId = "CAASysReceiverAppli"; CATMessageClass SimpleMessClassName = "CAASysSimpleMessage"; HRESULT rc= E_FAIL; // Retrieves an instance of a backbone bus (default bus) CATICommunicator * pICommunicator = NULL; pICommunicator = ::CATGetBackboneConnection(); ... // return if the backbone bus cannot be retrieved ... // Declares CAASysReceiverAppli on the backbone bus rc = pICommunicator->Declare(ReceiverApplicationId); ... // return if the declaration fails ... |
First, a connection to the backbone bus must be established. This is possible
thanks to the global function CATGetBackboneConnection
that returns
a pointer to the CATICommunicator interface. Once the connection is
established, the message sender sets its application class identifier and
declares it to the backbone bus using the method Declare
.
... if ( SUCCEEDED(rc) ) { CAASysSimpleMessageHandler * pHandler = NULL; pHandler = new CAASysSimpleMessageHandler(); if ( NULL != pHandler ) { rc = pHandler->QueryInterface(IID_CATIMessageReceiver, (void**)&pIMessageReceiver); if ( SUCCEEDED(rc) ) { rc=pICommunicator->AssociateHandler(ReceiverApplicationId, SimpleMessClassName, pIMessageReceiver); ... // error if the association fails } pHandler->Release(); pHandler = NULL; } } ... |
The message receiver instantiates the message handler, asks the message
handler for an pointer to CATIMessageReceiver, and declares to the
backbone bus that it will receive the declared messages using the designated
handler, thanks to the AssociateHandler
method.
[Top]
Now the message receiver can create and enter a loop to wait for messages.
... if ( SUCCEEDED(rc) ) { CATICommunicatorLoop * pILoop = NULL; pICommunicator->QueryInterface(IID_CATICommunicatorLoop, (void**)&pILoop); if ( SUCCEEDED(rc) ) { EndConditionLoop = -2; pILoop->WaitingLoop(-1, 6000 , &EndConditionLoop); pILoop ->Release(); pILoop = NULL; // OK ReturnCode = 0; } } ... |
A pointer to CATICommunicatorLoop is retrieved from the backbone bus
using the pointer to CATICommunicator retrieved when establishing the
connection. Then, a loop is created by calling WaitingLoop
of CATICommunicator.
The first parameter must be set to -1, the second is the maximum waiting time
expressed in milliseconds, and the third is a flag to get out of the loop before
the time set is over. This flag must be set to a non null value. Setting it to
null makes the process get out of the loop.
[Top]
... if ( NULL != pIMessageReceiver ) { // No more need of the handler for the first event pICommunicator->RemoveHandler(ReceiverApplicationId, SimpleMessClassName, pIMessageReceiver); pIMessageReceiver->Release(); pIMessageReceiver = NULL; } ... if ( NULL != pICommunicator ) { pICommunicator->Release(); pICommunicator = NULL; } return ReturnCode; } |
Once a message is received, or once the time set is over, the process gets
out of the loop, removes its handler thanks to the RemoveHandler
method that uses the same arguments than the AssociatedHandler
method, and stops.
[Top]
This use case shows how two processes or applications can communicate using simple messages, that is, messages that don't convey any data.
[Top]
[1] | Sending a Data Message to an Application |
[2] | Creating a Backbone Simple Message |
[3] | Building and Launching a CAA V5 Use Case |
[4] | Object Modeler Component and Implementation Inheritance |
[Top] |
Version: 1 [Jul 2000] | Document created |
[Top] |
Copyright © 2000, Dassault Systèmes. All rights reserved.