3D PLM Enterprise Architecture |
Middleware Abstraction - ENOVIA Event Model |
Subscribing Automatically to Login Session EventsWorking with events and subscribers |
Use Case |
AbstractThis article discusses the CAAVpiAutomaticSubscription2 use case, which is a particular case of the CAAVpiAutomaticSubscription use case. Indeed, this use case explains how to subscribe automatically to events raised by the Login Session itself, via the ENOVIEventPlugin interface. Note that those events cannot be subscribed to in the method Init of the plug-in, since the Login Session object is not accessible at that time. Only a subscription to event CreateLoginSession step After is allowed there. The main purpose of this use case is hence to show how you can do it. |
This use case is intended to show you the recommanded method to be used to automatically subscribe to the events raised by the Login Session itself. It also shows how to implement the dedicated callback interfaces to handle these events when they are raised.
[Top]
CAAVpiAutomaticSubscription2 is a use case of the CAAVPMInterfaces.edu framework that illustrates VPMInterfaces framework capabilities.
[Top]
The CAAVpiAutomaticSubscription2 use case processes to a subscription at the opening of the Login Session through the dedicated plug-in functionality illustrated by the CAAVpiAutomaticSubscription use case. The subscription is done on the step After of the event CreateLoginSession. Then in the associated callback interface, a second subscription is done on the steps Before and After of the event SaveLoginSession. Finally, the main program raises the event that has been subscribed to and the corresponding subscriber is called back.
The CAAVpiAutomaticSubscription2 use case is related to the CAAVpiEventObjects.m module where the following classes are defined:
[Top]
To launch CAAVpiAutomaticSubscription2, you will need to set up the build time environment, then to compile CAAVpiAutomaticSubscription2 along with its prerequisites, to set up the run time environment, and then to execute the use case [1].
Launch the use case as follows:
e:>CAAVpiAutomaticSubscription2 |
$ CAAVpiAutomaticSubscription2 |
[Top]
The CAAVpiAutomaticSubscription2 use case is made of a main named CAAVpiAutomaticSubscription2.cpp located in the CAAVpiAutomaticSubscription2.m module and two classes named CAAVpiListenAndSubscribe and CAAVpiPlugin4Subscribing2Session located in the CAAVpiEventObjects.m module of the CAAVPMInterfaces.edu framework.
Windows | InstallRootDirectory\CAAVPMInterfaces.edu\CAAVpiAutomaticSubscription2.m\(main) InstallRootDirectory\CAAVPMInterfaces.edu\CAAVpiEventObjects.m\(plugin+listener class) |
Unix | InstallRootDirectory/CAAVPMInterfaces.edu/CAAVpiAutomaticSubscription2.m/(main) InstallRootDirectory/CAAVPMInterfaces.edu/CAAVpiEventObjects.m/(plugin+listener class) |
where InstallRootDirectory is the directory where the CAA CD-ROM is installed.
[Top]
We can divide this use case in three distinct main parts:
There are three main steps in the first part of the CAAVpiAutomaticSubscription2 Use Case: Implementation of ENOVIEventPlugin
There are two main steps in the second part of the CAAVpiAutomaticSubscription2 Use Case: Implementation of ENOVISessionEvent
There are four main steps in the third part of the CAAVpiAutomaticSubscription2 Use Case:
We will now comment each of these sections in detail.
[Top]
In this use case, the automatic subscription is made through a plug-in functionality. To use this functionality the class CAAVpiPlugin4Subscribing2Session has to implement the ENOVIEventPlugin interface which declares a unique method : Init. Then, during the creation of the Login Session, each implementation of the ENOVIEventPlugin interface is called on the method Init where the code can carry out the subscription on event CreateLoginSession step After only.
We first do some object modeler declarations:
... // Object modeler declarations CATImplementClass( CAAVpiPlugin4Subscribing2Session, DataExtension, CATBaseUnknown, T_CAAVpiPlugin4Subscribing2Session ); #include "TIE_ENOVIEventPlugin.h" TIE_ENOVIEventPlugin( CAAVpiPlugin4Subscribing2Session ); // Init implementation HRESULT CAAVpiPlugin4Subscribing2Session::Init( const ENOVIEventManager_var &spEventManager ) { // code... } ... |
To finalize the implementation of the plug-in interface, we do not forget to complete the object modeler dictionary properly by adding the line:
T_CAAVpiPlugin4Subscribing2Session ENOVIEventPlugin libCAAVpiEventObjects
to the file CAAVPMInterfaces.edu.dic located in the directory CAAVPMInterfaces.edu/CNext/code/dictionary
Then, the first step in the Init method is to create an instance of the subscriber. As soon as the subscriber is created, a query interface is carried out to retrieve the appropriate smart pointers the Subscribe method is waiting for.
... // // ----------------------------------- // --> 1. Plugin Subscriber creation // ----------------------------------- // CAAVpiListenAndSubscribe* pCAAVpiListenAndSubscribe = new CAAVpiListenAndSubscribe(); // ENOVISessionEvent* piENOVISessionEvent = NULL; Rc = pCAAVpiListenAndSubscribe->QueryInterface( IID_ENOVISessionEvent, (void**)& piENOVISessionEvent ); pCAAVpiListenAndSubscribe->Release(); pCAAVpiListenAndSubscribe = NULL; if ( FAILED(Rc) ) { cout<<"Unable to get a handler on Plugin Subscriber"<<endl; return Rc; } cout << ">>plugin: Get a ENOVISessionEvent handler on Plugin Subscriber done " << endl; // CATBaseUnknown_var spPluginSubscriber = piENOVISessionEvent; piENOVISessionEvent->Release(); piENOVISessionEvent = NULL; if ( NULL_var == spPluginSubscriber ) { cout<<"Unable to get a handler on Plugin Subscriber"<<endl; return E_FAIL; } cout << ">>plugin: Get a CATBaseUnknown handler on Plugin Subscriber done " << endl; ... |
[Top]
This step is the subscription itself thanks to the Event Manager. It is referred to as a type subscription since the argument for the publisher is the string VPMSession itself.
... // // ---------------------------------------- // --> 4. Subscribe on After Create Login Session event // EARLY MODE Subscription on type VPMSession // ---------------------------------------- // CATUnicodeString EventName ( "CreateLoginSession" ); CATUnicodeString EventPublisherType ( "VPMSession" ); unsigned long cookie = 0; Rc = spEventManager->Subscribe( EventName, EventPublisherType, spPluginSubscriber, IID_ENOVISessionEvent, &cookie, ENOVIEvent::EventFireAfter ); if ( FAILED(Rc) ) { cout<<"Unable to subscribe on CreateLoginSession"<<endl; return Rc; } cout << ">>plugin: Subscribe on CreateLoginSession (after) done " << endl; ... |
[Top]
Finally the last step of this first part is to declare our plug-in implementation through the creation of a resource file. To do this, in the directory CAAVPMInterfaces.edu/CNext/resources/msgcatalog, a file named CAAVpiPluginList2.CATRsc has been created and just contains the line:
T_CAAVpiPlugin4Subscribing2Session = "0";
which simply states that the late type
However, at runtime, a new step is also required to declare the resource file name to be looked for, i.e.
export VPM_PLUGIN_OBJECTS_LIST=CAAVpiPluginList2
This completes the first part of the CAAVpiAutomaticSubscription2 use case.
[Top]
Now begins the second part of this use case in which we will implement ENOVISessionEvent.
The CAAVpiListenAndSubscribe class is an early subscriber that implements the callback interface ENOVISessionEvent since we are interested in Login Session events.
We hence begin with object modeler declarations.
... // Object modeler declarations CATImplementClass( CAAVpiListenAndSubscribe, Implementation, CATBaseUnknown, CATNull ); #include "TIE_ENOVISessionEvent.h" TIE_ENOVISessionEvent( CAAVpiListenAndSubscribe ); ... |
To finalize the implementation of the callback interface, we do not forget to
complete the object modeler dictionary properly by adding the line:
CAAVpiListenAndSubscribe ENOVISessionEvent libCAAVpiEventObjects
to the file CAAVPMInterfaces.edu.dic located in the directory
CAAVPMInterfaces.edu/CNext/code/dictionary.
We can now implement the ENOVISessionEvent methods and first of all the method onAfterCreateLoginSession. We will be called back here at the end of the Login Session creation since we subscribed to this event via the plug-in. In this method we can subscribe to the event SaveLoginSession since the Login Session is now fully available.
The subscription looks like the subscription shown in the first step above. However we have first to get the VPMSession, then the Login Session, and finally the Event Manager to do the subscription. Note that the subscriber instance is the instance of CAAVpiListenAndSubscribe itself (i.e. this).
... ENOVISessionEvent* piENOVISessionEvent = NULL; Rc = QueryInterface( IID_ENOVISessionEvent, (void**)& piENOVISessionEvent ); if ( FAILED(Rc) ) { cout<<"Unable to get a handler on Plugin Subscriber"<<endl; return Rc; } cout<<">>plugin listener: Get a ENOVISessionEvent handler on Plugin Subscriber done"<<endl; // CATBaseUnknown_var spPluginSubscriber = piENOVISessionEvent; piENOVISessionEvent->Release(); piENOVISessionEvent = NULL; if ( NULL_var == spPluginSubscriber ) { cout<<"Unable to get a handler on Plugin Subscriber"<<endl; return E_FAIL; } cout<<">>plugin listener: Get a CATBaseUnknown handler on Plugin Subscriber done"<<endl; // // ---------------------------------------- // --> 4. Subscribe on Save login Session event (before & after) // EARLY MODE Subscription on instance of LoginSession // ---------------------------------------- // CATUnicodeString EventName ( "SaveLoginSession" ); CATIVpmLoginSession_var oLoginSession = NULL_var; pSession->GetLoginSession( oLoginSession ); ENOVIPublisher_var spSessionPublisher = oLoginSession; unsigned long cookie = 0; Rc = spEventManager->Subscribe( EventName, spSessionPublisher, spPluginSubscriber, IID_ENOVISessionEvent, &cookie, ENOVIEvent::EventFireBefore ); if ( FAILED(Rc) ) { cout<<"Unable to subscribe on Save login Session"<<endl; return Rc; } cout << ">>plugin listener: Subscribe on Save login Session (before) done " << endl; // Etc. Idem for step after ... |
[Top]
Finally we can implement the two methods related to the Save Login Session event in which we will be called back thanks to the above subscription. For example, a sample code will look like the following.
... HRESULT CAAVpiListenAndSubscribe::onBeforeSaveLoginSession(const ENOVIEvent_var& iRaisedEvent, HRESULT& ioNotifyReturnCode) { HRESULT Rc = S_OK; CATUnicodeString iEventName; Rc = iRaisedEvent->GetName( iEventName ); if( SUCCEEDED(Rc) ) // etc. ioNotifyReturnCode = S_OK; return Rc ; } ... |
Note that not all the methods of ENOVISessionEvent have to be implemented since the class CAAVpiListenAndSusbcribe derives from the adapter class ENOVPackageListener as recommended.
[Top]
Now begins the third and last part of this use case, which describes the main program. The first thing to do in any Enovia program is to create the VPM Session. Here is the code to do it:
... // // --------------------------- // --> 1. Open a VPM Session // --------------------------- // cout << "main: Open VPM Session ... " << endl; VPMSession* pSession = VPMSession::OpenSession(); if ( NULL == pSession ) { cout << "Unable to Open a VPM Session" << endl; return 1; } cout << "main: Open VPM Session done " << endl << endl; ... |
[Top]
Then we have to create the Login Session. During its creation the plug-in
will be called and the subscription to event CreateLoginSession step After will
be made.
The interest of this step is also to see the traces at execution time: you
should see the listener being called back after the creation of the Login
Session and doing the subscriptions.
... // // ------------------------------- // --> 2. Login Session creation // ------------------------------- // cout << "main: Create LoginSession ... " << endl; const int NetWorkCommunication = 0; CATIVpmLoginSession_var spLoginSession; Rc = pSession->CreateLoginSession( "MyUserID", "MyPassword", "MyRoleName", NetWorkCommunication, spLoginSession ); if ( FAILED(Rc) ) { cout<<"Unable to Create Login Session"<<endl; VPMSession::CloseSession(); return 2; } cout << "main: Create LoginSession done " << endl << endl; ... |
[Top]
Now we are ready to fire SaveLoginSession event and to look at the traces to see if our subscriber is actually called back.
... // // --------------------------------------- // --> 3. Fire Save Login Session // --------------------------------------- // cout << "main: Save Login Session ... " << endl; Rc = spLoginSession->Save(); if ( FAILED(Rc) ) { cout<<"Unable to Save Login Session"<<endl; VPMSession::CloseSession(); return 3; } cout << "main: Save Login Session done " << endl << endl; ... |
[Top]
Each opened session must be closed as followed:
... // -------------------------------------------- // --> 4. Close Login Session and VPM Session // -------------------------------------------- // Rc = spLoginSession->Close(); if ( FAILED(Rc) ) { cout<<"Unable to Close Login Session"<<endl; return 4; } cout << "main: Close Login Session done " << endl; VPMSession::CloseSession(); cout << "main: Close VPM Session done " << endl; ... |
This step concludes the third part of the CAAVpiAutomaticSubscription2 use case.
[Top]
This use case has demonstrated the way to automatically subscribe to Login Session events via the ENOVIEventPlugin interface and how to be called back when they are raised.
[Top]
[1] | Building and Launching a CAA V5 Use Case |
[2] | The ENOVIA Event Model |
[Top] |
Version: 2 [Oct 2003] | Document updated for new interface ENOVIEventPlugin |
Version: 1 [Mar 2003] | Document created |
[Top] |
Copyright © 2003, Dassault Systèmes. All rights reserved.