Author Topic: How to handle-if config server sends EventObjectsSent response to RequestReadObj  (Read 5548 times)

Offline Vegeta

  • Newbie
  • *
  • Posts: 23
  • Karma: 0
Hi Genesys Wizards,

Request your help in understanding how to handle the below Scenario , I am trying to do some sequence of events as below.
Connect to Config server
Get the DBID of a user from CFGperson then get corresponding tenant_dbid / login code of that person ... I have pasted the code that I am using for the same.

Please bear any fatal flaws in method invocation procedures ,  I am just beginning to learn to work with Genesys SDKs , please advice.


[code]

/// Step 1 Opening a connection ////

                confServerProtocol.Open(); // opening a connection


///Step 2 Authenticating a Username and password of a User whose details are available in CME ... ///

            RequestAuthenticate RequestAuthenticateObj = RequestAuthenticate.Create(AgentName, Agentpassw);
            confServerProtocol.Send(RequestAuthenticateObj);

/// Step 3 Once authenticated I am trying to get the DBID of that User from Cfgperson ... the user who is authenticated above ///
/// and  once done I am trying to further fetch his Login code from CfgAgentLogin ///

KeyValueCollection filterKey = new KeyValueCollection();
            filterKey.Add("user_name", username); // passing the username authenticated via Request Authenticate

                RequestReadObjects requestFilterQuery = RequestReadObjects.Create((int)CfgObjectType.CFGPerson, filterKey);
                confServerProtocol.Send(requestFilterQuery);

            IMessage respondingEvent = confServerProtocol.Receive();
            EventObjectsRead objectsRead = (EventObjectsRead)respondingEvent;
           
                StringBuilder xmlAsText = new StringBuilder();
                XmlWriterSettings xmlSettings = new XmlWriterSettings();
                xmlSettings.Indent = true;

                using (XmlWriter xmlWriter =
                    XmlWriter.Create(xmlAsText, xmlSettings))
                {
                    XDocument resultDocument = objectsRead.ConfObject;

                var DBIDValue = (from d in resultDocument.Descendants()
                                    where d.Name.LocalName == "DBID"
                                    select d.Attribute("value").Value).First();

                      DBID = Convert.ToInt32(lDBIDValue);

            }
/// Step 4  pass a filter query again with the DBID obtained from previous step.. to get his tenant id / logithis time I am getting below exception
        KeyValueCollection getlocid = new KeyValueCollection();
            getlocid.Add("dbid",DBID);

            RequestReadObjects requestFilterQuerylogincode = RequestReadObjects.Create((int)CfgObjectType.CFGAgentLogin, getlocid);
          confServerProtocol.Send(requestFilterQuerylogincode); /////// as seen the filter value sent is...  Filter = {KVList:'dbid' [int] = 119}

            IMessage message = confServerProtocol.Receive();

            EventObjectsRead objectsRead2 =(EventObjectsRead)message; //////////////////////////- Exception Here...
[/code]

Exception :
{"Unable to cast object of type 'Genesyslab.Platform.Configuration.Protocols.ConfServer.Events.EventObjectsSentData' to type 'Genesyslab.Platform.Configuration.Protocols.ConfServer.Events.EventObjectsRead'."}


Offline spin

  • Newbie
  • *
  • Posts: 7
  • Karma: 2
Have a read of the SDK Documentation around Event Handling.  The short version is Configuration Server will send back many messages including EventObjectsSent and one or more EventObjectsRead for your request , and you're 'Receive' needs to work with all of those.  At the moment it looks like you're assuming it'll give you back an EventObjectsRead but you're actually getting the EventObjectsSent - causing the cast error.




Offline hsujdik

  • Hero Member
  • *****
  • Posts: 541
  • Karma: 30
I don't currently have Visual Studio installed, so I didn't test the code below, but I feel that would be way easier if you used ConfService. You would get rid of all the XmlDocument manipulation hell. For example:


[code]

/// Step 1 Opening a connection ////

// HSUJDIK: create the ConfService before opening the ConfServerProtocol:
EventBrokerService brokerService = BrokerServiceFactory.CreateEventBroker(protocol);
ConfService service = ConfServiceFactory.CreateConfService(confServerProtocol, brokerService);

                confServerProtocol.Open(); // opening a connection


///Step 2 Authenticating a Username and password of a User whose details are available in CME ... ///

            RequestAuthenticate RequestAuthenticateObj = RequestAuthenticate.Create(AgentName, Agentpassw);
            // HSUJDIK: use the method .Request instead of .Send so you will get the message back
            // without need to use the method .Receive()
            (Message) authResponse = confServerProtocol.Request(RequestAuthenticateObj);
            // HSUJDIK: check if EventAuthenticated or EventError was returned.
           

/// Step 3 Once authenticated I am trying to get the DBID of that User from Cfgperson ... the user who is authenticated above ///
/// and  once done I am trying to further fetch his Login code from CfgAgentLogin ///

// HSUJDIK:
CfgPersonQuery query = new CfgPersonQuery(confservice);
query.UserName("user_name");

CfgPerson person = null;

try {
person = query.ExecuteSingleResult();
} catch (Exception e) {
// ERROR TRYING TO GET THE USER PROPERTIES. Proceed as you wish
}

List<CfgAgentLogin> agentLogins = person.AgentInfo.AgentLogins;

foreach (CfgAgentLogin agentLogin in agentLogins) {

// HSUJDIK: Do whatever you need with each CfgAgentLogin

}


/// Step 4  pass a filter query again with the DBID obtained from previous step.. to get his tenant id / logithis time I am getting below exception

// HSUJDIK:
int dbid = person.Tenant.DBID;

[/code]

Offline Vegeta

  • Newbie
  • *
  • Posts: 23
  • Karma: 0
Hi hsujdik,

Thanks for your time for such a useful piece of code snippet.

I set out to try it as adviced , but in my previous connection opening I tried adding brokerservice below

[code]           
///////// Arul's code trial //////////////////

ConfServerProtocol confServerProtocol = new ConfServerProtocol(new Endpoint(Host, port));

            confServerProtocol.ClientApplicationType = (int)PsdkCustomization.CustomOption("Samples.CS.ClientType", 19);
                confServerProtocol.ClientName = userName;
                confServerProtocol.UserName = userName;
                confServerProtocol.UserPassword = password;

///////////But if I pass ConfServerProtocol in CreateEventBroker ... constructor it fails ///////////////
EventBrokerService brokerService = BrokerServiceFactory.CreateEventBroker(confServerProtocol);
///////// Arul's code trial //////////////////
[/code]

So after referring to the Developers guide , I thought of using a ProtocolManagementService , I get a message saying ' ProtocolManagementService' is going to be depreciated , and use warmstandby instead.. is it possible to use warmstandy along with CreateEventBroker ?

Please suggest if there is a better way or we can still stick to ProtocolManagementService' at this point.

Thanks
Arul

Offline Vegeta

  • Newbie
  • *
  • Posts: 23
  • Karma: 0
[quote author=spin link=topic=9642.msg43601#msg43601 date=1465333179]
Have a read of the SDK Documentation around Event Handling.  The short version is Configuration Server will send back many messages including EventObjectsSent and one or more EventObjectsRead for your request , and you're 'Receive' needs to work with all of those.  At the moment it looks like you're assuming it'll give you back an EventObjectsRead but you're actually getting the EventObjectsSent - causing the cast error.
[/quote]

Hi Spin -- Thanks for pointing me towards the Eventhadling stuff ..
But I still have a doubt .. even if I handle the ..EventObjectsSent .. I can open a handler and to capture that and avoid case but still is there any other better methods which I can raise from this event handler to extract the one/more messages other way around.
Sorry I have no clue how to do that.. :( hence the ask.

Also I have started trying out hsujdik's option to see if I can get the details I wanted to retrieve.

Thanks

Offline Vegeta

  • Newbie
  • *
  • Posts: 23
  • Karma: 0
[quote author=hsujdik link=topic=9642.msg43602#msg43602 date=1465338666]
I don't currently have Visual Studio installed, so I didn't test the code below, but I feel that would be way easier if you used ConfService. You would get rid of all the XmlDocument manipulation hell. For example:


[code]

/// Step 1 Opening a connection ////

// HSUJDIK: create the ConfService before opening the ConfServerProtocol:
EventBrokerService brokerService = BrokerServiceFactory.CreateEventBroker(protocol);
ConfService service = ConfServiceFactory.CreateConfService(confServerProtocol, brokerService);

                confServerProtocol.Open(); // opening a connection


///Step 2 Authenticating a Username and password of a User whose details are available in CME ... ///

            RequestAuthenticate RequestAuthenticateObj = RequestAuthenticate.Create(AgentName, Agentpassw);
            // HSUJDIK: use the method .Request instead of .Send so you will get the message back
            // without need to use the method .Receive()
            (Message) authResponse = confServerProtocol.Request(RequestAuthenticateObj);
            // HSUJDIK: check if EventAuthenticated or EventError was returned.
           

/// Step 3 Once authenticated I am trying to get the DBID of that User from Cfgperson ... the user who is authenticated above ///
/// and  once done I am trying to further fetch his Login code from CfgAgentLogin ///

// HSUJDIK:
CfgPersonQuery query = new CfgPersonQuery(confservice);
query.UserName("user_name");

CfgPerson person = null;

try {
person = query.ExecuteSingleResult();
} catch (Exception e) {
// ERROR TRYING TO GET THE USER PROPERTIES. Proceed as you wish
}

List<CfgAgentLogin> agentLogins = person.AgentInfo.AgentLogins;

foreach (CfgAgentLogin agentLogin in agentLogins) {

// HSUJDIK: Do whatever you need with each CfgAgentLogin

}


/// Step 4  pass a filter query again with the DBID obtained from previous step.. to get his tenant id / logithis time I am getting below exception

// HSUJDIK:
int dbid = person.Tenant.DBID;

[/code]
[/quote]
********************************************************************************

Hi Hsujdik

I tried your method to remove those XML handling and tried with Confservice.
I am seeing one odd event .. the 2nd  var Agentinfo = queryforLoginID.Execute();    for agentloginQuery is returning null

please advice

      [code]    //  CfgAgentLoginQuery query = new CfgAgentLoginQuery(service);
            var query = new CfgPersonQuery(service) { UserName = AgentName };
           
            //testing  Dbid = DBID UserName = AgentName

            // retrieve all persons with given parameter UserName
            var readedPersons = query.Execute();
            if ((readedPersons != null) && (readedPersons.Count > 0))
            {
                foreach (CfgPerson readedPerson in readedPersons)
                {
                    // notify to a view that person has been read
                    MessageBox.Show(readedPerson.DBID.ToString());
                    DBID = readedPerson.DBID;
                }
            }

            var queryforLoginID = new CfgAgentLoginQuery(service) { Dbid = DBID };
            //retrieve all persons with given parameter UserName
            var Agentinfo = queryforLoginID.Execute();                                                  //// I am seeing that this query is returning null value.. am I missing something  :(
            // List<CfgAgentLogin> Agentinfo = queryforLoginID.Execute();
            if ((Agentinfo != null) && (Agentinfo.Count > 0))
            {
                foreach (CfgAgentLogin info in Agentinfo)
                {
                    // notify to a view that person has been read
                    MessageBox.Show(info.LoginCode.ToString());

                }
            }
[/code]

Offline hsujdik

  • Hero Member
  • *****
  • Posts: 541
  • Karma: 30
For the CfgPersonQuery, I would use the ExecuteSingleResult method... as far as I know (assuming single tenant environment) you cannot have more than one person with the same username on the environment. So, there would be no need to loop for each person once you will have only one result...

Also, you are querying the AgentLogin with the DBID of the person. Note that they are different.

Agent can have the DBID "1" whereas its AgentLogin may have DBID "2", for instance.

If you use properly, you don't even need to perform a second Query. All the info you will get from the first query. Like this (based on your last code):




[code]

            var query = new CfgPersonQuery(service) { UserName = AgentName };
           
            // retrieve THE ONLY person with given parameter UserName
            var readedPerson = query.ExecuteSingleResult();
            if (readedPerson != null)
            {
                foreach (CfgAgentLogin info in readedPerson.LoginInfo.AgentLogins)
                {
                    // notify the Login Infos
                    MessageBox.Show(info.LoginCode.ToString());
                }
            }


[/code]


Offline spin

  • Newbie
  • *
  • Posts: 7
  • Karma: 2
[quote author=Vegeta link=topic=9642.msg43652#msg43652 date=1465567320]

But I still have a doubt .. even if I handle the ..EventObjectsSent .. I can open a handler and to capture that and avoid case but still is there any other better methods which I can raise from this event handler to extract the one/more messages other way around.
Sorry I have no clue how to do that.. :( hence the ask.

Thanks
[/quote]

Hello - if you do async messaging you can just have a sub to do the message handling.  Something like this (vb)

[code]
    Imports Genesyslab.Platform.Commons.Protocols

    Private Sub ConfMessageReceived(ByVal sender As Object, ByVal e As EventArgs) Handles ConfProtocol.Received

        Dim y As MessageEventArgs = TryCast(e, MessageEventArgs)

        If (IsNothing(y) = False) Then

            Select Case y.Message.Name
                Case "EventObjectsRead"
                    'do stuff
                    ASubThatHandlesIMessage(y.Message)
                Case "EventObjectsSent"
                    'don't do stuff
                Case "AnotherEvent"
                    'do something else
            End Select

        End If

    End Sub

[/code]

   


Offline Vegeta

  • Newbie
  • *
  • Posts: 23
  • Karma: 0
[quote author=hsujdik link=topic=9642.msg43669#msg43669 date=1465847994]
For the CfgPersonQuery, I would use the ExecuteSingleResult method... as far as I know (assuming single tenant environment) you cannot have more than one person with the same username on the environment. So, there would be no need to loop for each person once you will have only one result...

Also, you are querying the AgentLogin with the DBID of the person. Note that they are different.

Agent can have the DBID "1" whereas its AgentLogin may have DBID "2", for instance.

If you use properly, you don't even need to perform a second Query. All the info you will get from the first query. Like this (based on your last code):




[code]

            var query = new CfgPersonQuery(service) { UserName = AgentName };
           
            // retrieve THE ONLY person with given parameter UserName
            var readedPerson = query.ExecuteSingleResult();
            if (readedPerson != null)
            {
                foreach (CfgAgentLogin info in readedPerson.LoginInfo.AgentLogins)
                {
                    // notify the Login Infos
                    MessageBox.Show(info.LoginCode.ToString());
                }
            }


[/code]
[/quote]

Thanks so much Hsujdik, I am able to retrieve the value  8) for login code.

[code]  var query = new CfgPersonQuery(service) { UserName = AgentName };
                  var readedPerson = query.ExecuteSingleResult();
                if (readedPerson != null)
                {
                    foreach (CfgAgentLoginInfo info in readedPerson.AgentInfo.AgentLogins)
                    {
                        // notify the Login Infos
                        MessageBox.Show(info.AgentLogin.LoginCode.ToString());
                    }
                }}[/code]