3D PLM Enterprise Architecture |
User Interface - Dialogs |
Sending a Data Message to an Interactive ApplicationUsing the backbone to send a message with data |
Use Case |
AbstractThis article shows how to make two interactive applications communicate, and how one of them can send a data message that conveys a text, and how the other can receive the message. |
This use case is intended to show you how an interactive 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 message taken as an example conveys a text.
[Top]
CAADlgBBSender and CAADlgBBReceiver are use cases of the CAADialog.edu framework that illustrates the Dialog and System frameworks capabilities.
[Top]
This use case illustrates two interactive applications. One behaves as a message sender, and the other as a message receiver. The message is a data message that conveys a text. The message sender displays an entry field in which the end user types the message text and clicks the Send button to send the message. The message receiver displays a field in which the text of the received message is printed.
![]() |
![]() |
Both the message sender and the message receiver are interactive applications launched by instantiating a class that derives from CATInteractiveApplication. To send the message, the message sender connects to the backbone bus, declares itself, instantiates the message component using the text entered in the text field of its window, 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. In addition, the message receiver subscribes to a notification that the message handler will request a message manager to dispatch along with the message text. To receive the message, the message receiver connects to the backbone bus, declares itself, declares the message to receive, instantiates the message handler, associates itself with the message to receive and with the message handler. As soon as the message is sent, it is retrieved by the message handler that requests the message manager to dispatch a notification that carries the message text, and to which the message receiver has subscribed. The message receiver called back method extract the message text from the notification and prints it in the window text field.
Compared to batch applications that intend to receive messages [1] [2], there is no need to create and enter a waiting loop, since the interactive application includes one already. The message conveys data [5] made of a text. It is not described.
[Top]
To launch CAADlgBBSender and CAADlgBBReceiver, you will need to set up the build time environment, then compile CAADlgBBSender and CAADlgBBReceiver 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:
CAADlgBBSender CAADlgBBReceiver
CAADlgBBSender & CAADlgBBReceiver &
Type a text in the Backbone Sender window text field, and click Send. The text is printed in the Backbone Receiver window text field.
[Top]
The CAADlgBBSender and CAADlgBBReceiver use case are made of several classes located in the CAADlgBBSender.m and CAADlgBBReceiver.m module of the CAADialog.edu framework:
Windows | InstallRootDirectory\CAADialog.edu\CAADlgBBSender.m\ |
Unix | InstallRootDirectory/CAADialog.edu/CAADlgBBSender.m/ |
where InstallRootDirectory
is the directory where the CAA CD-ROM
is installed.
The message component is made of several classes located in the CAADlgBBMessage.m module of the CAADialog.edu framework, and in addition implements the CAAIDlgDataRequest interface located in the PrivateInterfaces directory and in the CAADlgBBMessageInt.m module of the CAADialog.edu framework. They are not described in this article. Refer to the messages described in the CAASystem.edu framework [4] [5].
[Top]
To create interactive applications that send and receive a data message, there are seven main steps:
[Top]
The message sender is an interactive application whose class is CAADlgBBSender.
Its main method is BeginApplication
where the application window is
instantiated. The window class is CAADlgBBSenderWindow whose Build
method connects to the backbone bus by calling its BackboneInit
method before creating the controls and setting a callback to react when the
Send button is clicked. Below is the BackboneInit
method
... HRESULT CAADlgBBSenderWindow::BackboneInit() { HRESULT rc = E_FAIL; // Retrieves an instance of a backbone bus (default bus) _pICommunicator = ::CATGetBackboneConnection(); if ( NULL != _pICommunicator ) { CATApplicationClass ApplicationSenderId = "CAADlgBBSender"; rc =_pICommunicator->Declare(ApplicationSenderId); ... //Process failing declaration } return rc; } ... |
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 stored in the _pICommunicator
data member. Then, the message sender creates its application class identifier
and declares it to the backbone bus using the method Declare
.
[Top]
The message is sent by the callback set to the push button activation.
... void CAADlgBBSenderWindow::PushSend(CATCommand * iSendingCommand, CATNotification * iSentNotification, CATCommandClientData iUsefulData) { CATUnicodeString Line; _pEditor->GetLine(Line); CAAIDlgDataRequest * pIDataRequest = NULL; HRESULT rc = ::CATInstantiateComponent("CAADlgBBEditorMessage", IID_CAAIDlgDataRequest, (void **)&pIDataRequest); if ( SUCCEEDED(rc) ) { pIDataRequest->SetData(Line.CastToCharPtr()); CATICommMsg * pICommMsg =NULL; rc = pIDataRequest->QueryInterface(IID_CATICommMsg,(void**)&pICommMsg); if ( SUCCEEDED(rcb) ) { CATApplicationClass ReceiverApplicationId = "CAADlgBBReceiver"; rc = _pICommunicator->SendRequest(ReceiverApplicationId, pICommMsg); pICommMsg->Release(); pICommMsg = NULL; } pIDataRequest->Release(); pIDataRequest = NULL; } } ... |
When you click Send, this method is called, and the message sender can send
the message. It first retrieves the text entered in the text field, a CATDlgEditor
instance, thanks to the GetLine
method. Then it instantiates the
message component CAADlgBBEditorMessage using the CATInstantiateComponent
global function, which returns a pointer to CAAIDlgDataRequest interface.
This interface is created for this message to enable it to set and get its data,
that is, the message text. The message text is passed to the message component
thanks to the SetData
method of CAAIDlgDataRequest, and then
the message is sent using the SendRequest
method of CATICommunicator,
specifying the target message receiver identifier and the message to send as a
pointer to CATICommMsg. This message receiver identifier must be the same
than the one declared by the message receiver itself in its own BackboneInit
method.
[Top]
#include "CATBaseUnknown.h" //Needed to derive from CATBaseUnknown class CATICommMsg; class CAADlgBBEditorMessageHandler : public CATBaseUnknown { CATDeclareClass; public: CAADlgBBEditorMessageHandler(); virtual ~CAADlgBBEditorMessageHandler(); // CATIMessageReceiver Interface void HandleMessage(CATICommMsg * iMessage); private: CAADlgBBEditorMessageHandler(const CAADlgBBEditorMessageHandler &iObjectToCopy); }; |
The CAADlgBBEditorMessageHandler 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 "CAADlgBBEditorMessageHandler.h" #include <CATErrorDef.h> // for the SUCCEEDED macro #include "CAAIDlgDataRequest.h" #include "CAADlgBBMessageManager.h" #include "TIE_CATIMessageReceiver.h" TIE_CATIMessageReceiver(CAADlgBBEditorMessageHandler); CATImplementClass(CAADlgBBEditorMessageHandler, Implementation, CATBaseUnknown, CATNull); CAADlgBBEditorMessageHandler::CAADlgBBEditorMessageHandler(){} CAADlgBBEditorMessageHandler::~CAADlgBBEditorMessageHandler(){} void CAADlgBBEditorMessageHandler::HandleMessage(CATICommMsg* iMessage) { if ( NULL != iMessage ) { CAAIDlgDataRequest * pIRequest = NULL; HRESULT rcb = iMessage->QueryInterface(IID_CAAIDlgDataRequest,(void**) &pIRequest); if ( SUCCEEDED(rcb) ) { char * Text = NULL; pIRequest->GetData(&Text); pIRequest->Release(); pIRequest= NULL; CAADlgBBMessageManager * pManager = CAADlgBBMessageManager::GetManager(); pManager->EventToDispatch(Text); delete [] Text; Text = NULL; pManager->Release(); pManager= NULL; } } } |
The CAADlgBBEditorMessageHandler class states that it implements the CATIMessageReceiver
interface thanks to the TIE_CATIMessageReceiver
macro. The CATImplementClass
macro declares that the CAADlgBBEditorMessageHandler class is a component
main class thanks the Implementation
keyword, and that the
component OM-derives [6] from CATBaseUnknown.
Any component main class declared as an Implementation
must
C++-derive and OM-derive from the same class. The CATIMessageReceiver
interface HandleMessage
method is called by the backbone bus and a
pointer to the message is passed. A pointer to CAAIDlgDataRequest is
retrieved from the message to get the message text. Then, the message manager of
the message receiver application is retrieved. The message text is passed to the
message manager thanks to the EventToDispatch
method.
The framework interface dictionary is updated to declare that CAADlgBBEditorMessageHandler implements the CATIMessageReceiver interface in the libCAADlgBBReceiver shared library or DLL. This interface dictionary is a file located in the CNext\code\dictionary directory, and is named CAADialog.edu.dico. There is one and only one interface dictionary per framework, named using the framework name suffixed by dico.
... CAADlgBBEditorMessageHandler CATIMessageReceiver libCAADlgBBReceiver ... |
[Top]
The message manager is a component that dispatches a notification that carries the message text.
#include <CAADlgBBMessageManager.h> #include <CAADlgBBMessageNotification.h> #include "CATCallbackManager.h" CATImplementClass(CAADlgBBMessageManager,Implementation,CATBaseUnknown,CATNull); CAADlgBBMessageManager * CAADlgBBMessageManager::_Manager = NULL; CAADlgBBMessageManager::CAADlgBBMessageManager() {} CAADlgBBMessageManager::~CAADlgBBMessageManager() {} void CAADlgBBMessageManager::EventToDispatch(char * iText) { CATCallbackManager * pCBManager = ::GetDefaultCallbackManager(this); if ( NULL != pCBManager ) { CAADlgBBMessageNotification * pNotification = new CAADlgBBMessageNotification(iText); pCBManager->DispatchCallbacks(pNotification, this); pNotification->Release(); pNotification = NULL; } } CAADlgBBMessageManager * CAADlgBBMessageManager::GetManager() { if ( NULL == _Manager ) { _Manager = new CAADlgBBMessageManager(); } _Manager->AddRef(); return _Manager; } ... |
The message manager is created as a component and is unique. It is
instantiated by the GetManager
static method. The EventToDispatch
method retrieves the default callback manager associated with any component,
instantiates a CAADlgBBMessageNotification class that takes the message
text as a data member, and request the default callback manager to dispatch this
notification, to which the message receiver application will subscribe.
[Top]
The message receiver is an interactive application. It has a window, instance
of the class CAADlgBBReceiverWindow, that carries out the main tasks of
connecting to the backbone bus and receiving the message. Below is the Build
method of CAADlgBBReceiverWindow.
void CAADlgBBReceiverWindow::Build() { HRESULT Init = BackboneInit(); if ( SUCCEEDED(Init) ) { CATDlgFrame * pFrame = new CATDlgFrame(this, "FrameId", CATDlgFraNoFrame | CATDlgGridLayout ); CATDlgLabel * pLabel = new CATDlgLabel (pFrame,"LabelEditorId"); pLabel->SetGridConstraints(0,0,1,1,CATGRID_LEFT); _pEditor = new CATDlgEditor(pFrame,"EditorId",CATDlgEdtReadOnly); _pEditor->SetGridConstraints(0,1,1,1,CATGRID_LEFT); _pMessageManager = CAADlgBBMessageManager::GetManager(); ::AddCallback(this, _pMessageManager, "CAADlgBBMessageNotification", (CATSubscriberMethod)&CAADlgBBReceiverWindow::ModifyEditor, NULL); } AddAnalyseNotificationCB(this, GetWindCloseNotification(), (CATCommandMethod)&CAADlgBBReceiverWindow::Exit, NULL); } ... |
The Build
method first call the BackboneInit
method, and if this method succeeds, creates the controls. Then it retrieves the
message manager thanks to the static method GetManager
of CAADlgBBMessageManager,
and sets a callback, that is, subscribes to an event, using the AddCallback
global function whose arguments are:
this |
The event subscriber, that is, the message receiver application window |
_pMessageManager |
The event publisher, which is here the message manager |
CAADlgBBMessageNotification |
The event to subscribe. It is the class name of the notification that is sent by the message manager |
(CATSubscriberMethod)&CAADlgBBReceiverWindow::ModifyEditor |
The method to call back when such a notification is received |
NULL |
Possible useful data that could be sent with the notification |
The BackboneInit
method is as follows.
HRESULT CAADlgBBReceiverWindow::BackboneInit() { HRESULT rc = E_FAIL; _pICommunicator = ::CATGetBackboneConnection(); if ( NULL == _pICommunicator ) ... // Process failure else { CATApplicationClass ReceiverApplicationId = "CAADlgBBReceiver"; rc= _pICommunicator->Declare( ReceiverApplicationId ); if ( FAILED(rc) ) ... // Process failure else { CATMessageClass MessageClassName = "CAADlgBBEditorMessage"; CAADlgBBEditorMessageHandler * pHandlerForMessage = NULL; pHandlerForMessage = new CAADlgBBEditorMessageHandler(); if ( NULL != pHandlerForMessage ) { rc = pHandlerForMessage->QueryInterface(IID_CATIMessageReceiver, (void**)& _pIMessageReceiver); if ( SUCCEEDED(rc) ) { rc = _pICommunicator->AssociateHandler(ReceiverApplicationId, MessageClassName, _pIMessageReceiver); ... // Process failure } pHandlerForMessage->Release(); pHandlerForMessage = NULL; } } } return rc; } ... |
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 receiver sets its application identifier and declares
it to the backbone bus using the method Declare
. Note that this
identifier is used by the message sender when sending the message using the SendRequest
method. Then the message receiver instantiates the message handler, asks the
message handler for a 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]
The message is received thanks to the message handler that retrieves the
message manager, and requests it to dispatch a notification that carries the
message text. The message receiver has subscribed to this notification, and the
callback method designated is then called. This method is the ModifyEditor
method below.
... void CAADlgBBReceiverWindow::ModifyEditor(CATCallbackEvent ievent, void *ipublisher, CATNotification *iNotification, CATSubscriberData iData, CATCallback iCallback) { char * Text = NULL; CAADlgBBMessageNotification * iNotif = (CAADlgBBMessageNotification*) iNotification; iNotif->GetText(&Text); _pEditor->SetLine(Text); delete [] Text; } ... |
ModifyEditor
retrieves the message text from the notification,
and assigns it to the editor thanks to the SetLine
method.
[Top]
The message handler should be removed when no messages are to be received any longer. This is done here in the message receiver application window destructor.
... CAADlgBBReceiverWindow::~CAADlgBBReceiverWindow() { _pApplication = NULL; _pEditor = NULL; if ( NULL != _pICommunicator ) { if ( NULL != _pIMessageReceiver ) { CATMessageClass MessageClassName = "CAADlgBBEditorMessage"; _pICommunicator->RemoveHandler("CAADlgBBReceiver", MessageClassName, _pIMessageReceiver); _pIMessageReceiver->Release(); _pIMessageReceiver = NULL; } _pICommunicator->Release(); _pICommunicator = NULL; } if ( NULL != _pMessageManager ) { _pMessageManager->Destroy(); _pMessageManager = NULL; } } ... |
The data members are released and nullified. The message handler is removed
thanks to the RemoveHandler
method of CATICommunicator. Its
arguments are:
CAADlgBBReceiver |
The message receiver identifier |
MessageClassName |
The message class name to which the message handler is dedicated |
_pIMessageReceiver |
The message handler |
[Top]
This use case shows how to create interactive applications that send and receive backbone messages. The receiving application identifier must be known by the message sender.
[Top]
Version: 1 [Jul 2000] | Document created |
[Top] |
Copyright © 2000, Dassault Systèmes. All rights reserved.