locked
finding implementers of generic contract RRS feed

  • Question

  • So, I hear the API for this is about to change, but I'm going to ask anyway, and if the new documentation for the new API answers the question before anyone can give me the answer under the old API, so much the better...but I'd rather not sit around waiting. 

    I've got a simple GenericSensor generic service, and two services, Sensor3 and Sensor4, that implement the GenericSensor contract on an alternate service port.

    Now I'm trying to implement a SensorFinder service that looks for any services that implement the GenericSensor contract.  It will then do some processing on the list of results and choose one to start up.  My understanding is that I want to use a QueryServiceContract message to the ContractDirectory service, but I haven't found enough documentation or examples to know quite how.  Here's what I've got so far:

    public IEnumerator<ITask> QueryDirectory()
            {
                Console.WriteLine("Starting Directory Query");
               
                cd.ContractResults results = null;
                cd.QueryRequest body = new cd.QueryRequest();
               
                body.DssContract = GenericSensor.Proxy.Contract.Identifier;
                body.SearchAlternateContracts = true;
               
                body.IncludeReferencedContracts = true;
                body.RequiredResults = cd.RequiredResults.Any;

                body.ResultTypes = cd.ResultTypes.Simple;
                cd.QueryServiceContract query = new cd.QueryServiceContract(body);
               
                _contractDir.Post(query);
               
                yield return Arbiter.Choice(
                    query.ResponsePort,
                    delegate(cd.ContractResults res) { results = res; },
                    delegate(Fault f) { LogInfo(new Exception("fault"));}
                    );

                if (results != null)
                {
                    Console.WriteLine(String.Format("{0} services found", results.ServicesFound));
                    Console.WriteLine(String.Format("{0} service summaries", results.ServiceSummaries.Count));
                    Console.WriteLine(String.Format("{0} related services", results.RelatedServices));
                    foreach (ServiceSummary ss in results.ServiceSummaries)
                    {
                        Console.WriteLine("Name: " + ss.Name);
                        Console.WriteLine("Contract: " + ss.DssContract);
                        Console.WriteLine("SourceAssembly: " + ss.SourceAssembly);
                    }
                }
                else Console.WriteLine("FAIL!");
            }

    (sorry about the lack of formatting -- the in-browser editor is broken...)

    When I run this I get:
    1 services found
    1 service summaries
    2 related services
    Name:
    Contract: http://schemas.robotics.umass.edu/2008/07/genericsensor.html
    SourceAssembly: GenericSensor.Y2008.M07

    It finds the GenericSensor, and I strongly suspect those 2 related services are Sensor3 and Sensor4.  But I would have expected '
    body.SearchAlternateContracts = true;' would result in services implementing the sought contract as alternate contracts to be included in the search results.  How do I:
    1. get the information I need about Sensor3 and Sensor4, ideally in the list of results returned?
    and, if possible,
    2. /exclude/ the GenericSensor service from the list of results, since it can't be instantiated?

    Thanks in advance,
    Andrew Stout

    Thursday, July 17, 2008 4:48 AM

Answers

  • Hi Andrew, the compile errors are becaus ein CTP2 the ServiceSummary type has new fields. Please look at the type in VisualStudio or (my preferred way) look at the generated XML when you run DssInfo on any service. It will contain a serialized service summary.

     

    Now, on the actual issue: You have found a regression. Indeed you *cant* find alternate contract implementation in CTP2 using this api. We will fix this.

     

    What you can do:

     

    1) QueryByContract, set Contract = null, this will return all service summaries. Then search through them(under the ServiceSummary alternaet contract field) to find the ones that match

    2) Use the Category attribute on your new service, then QueryByCategery

     

    hope this helps and thank you for reporting this. We do have tests that are suppoosed to verify Alternate contract searching so i will look into why they didnt catch this

    Friday, July 25, 2008 7:14 PM

All replies

  • Querying using the Contract identifier, and enabling search for alternate contracts will give you all services (generic definition plus 1 or more implementations). To distinguish if a service has an implementation or not, or if its a pure contract, in the new ServiceSummary type look for the implementation class type name. If its missing your contract is a generic contract.

     

    g

    Tuesday, July 22, 2008 4:48 AM
  • Arrg.  I'm still not getting anything but the generic contract.  I've migrated my code to the July CTP, and I'm using George's example from here, but I'm still getting the same results.  To make things a little simpler, I've written a Sensor5, which does nothing but says it implements the generic sensor contract.

    Here's my current version of the query:

    public IEnumerator<ITask> QueryDirectory()
            {
                Console.WriteLine("Starting Directory Query");

                cd.ContractResults results = null;
                var body = new cd.QueryByContractRequest();
                body.Contract = GenericSensor.Proxy.Contract.Identifier;
                body.SearchAlternateContracts = true;
                cd.QueryByContract query = new cd.QueryByContract(body);
                query.TimeSpan = DsspOperation.DefaultLongTimeSpan;
                _contractDir.Post(query);

                yield return Arbiter.Choice(
                    query.ResponsePort,
                    delegate(cd.ContractResults res) { results = res; },
                    delegate(Fault f)
                    { //start.ResultPort.Post(new Exception("fault"));
                        LogInfo(new Exception("fault"));
                    }
                );
                if (results != null)
                {
                    //Console.WriteLine(String.Format("{0} services found", results.ServicesFound));
                    Console.WriteLine(String.Format("{0} service summaries", results.ServiceSummaries.Count));
                    //Console.WriteLine(String.Format("{0} related services", results.RelatedServices));
                    //foreach (ServiceSummary ss in results.ServiceSummaries)
                    foreach (var ss in results.ServiceSummaries)
                    {
                        Console.WriteLine("Name: " + ss.Name);
    // these have disappeared from the API?
                        //Console.WriteLine("Contract: " + ss.DssContract);
                        //Console.WriteLine("SourceAssembly: " + ss.SourceAssembly);
                    }
                }
                else Console.WriteLine("FAIL!");

            }


    and here's the first part of my definition of Sensor 5.  I've checked, the .dlls are in the bin directory like they should be.

    using generic = Robotics.GenericSensor.Proxy;

    namespace Robotics.Sensor5
    {
        [Contract(Contract.Identifier)]
        [AlternateContract(generic.Contract.Identifier)]
        [DisplayName("Sensor5")]
        [Description("Sensor5 service (no description provided)")]
        class Sensor5Service : DsspServiceBase
        {
            /// <summary>
            /// Service state
            /// </summary>
            [ServiceState]
            generic.GenericSensorState _state = new generic.GenericSensorState();

            /// <summary>
            /// Main service port
            /// </summary>
            [ServicePort("/Sensor5", AllowMultipleInstances = true)]
            generic.GenericSensorOperations _mainPort = new generic.GenericSensorOperations();

    I'm still just getting "1 service summaries".  Can someone see what I'm doing wrong?

    (Also, I'm assuming this is just a CTP growing pain, but now the line
    using Microsoft.Dss.Services.ContractModel;
    gets me this compiler error:
    Error    1    The type or namespace name 'ContractModel' does not exist in the namespace 'Microsoft.Dss.Services' (are you missing an assembly reference?)    C:\Documents and Settings\Andrew Stout\Microsoft Robotics Dev Studio 2008\path\to\SensorFinder\SensorFinder.cs    17    30    SensorFinder
    when I comment that line out, it no longer knows about some of the (previously available) properties of the service summary object that I get back in results.  The lines commented out above give this compiler error:
    Error    1    'Microsoft.Dss.Core.ContractModel.ServiceSummary' does not contain a definition for 'SourceAssembly' and no extension method 'SourceAssembly' accepting a first argument of type 'Microsoft.Dss.Core.ContractModel.ServiceSummary' could be found (are you missing a using directive or an assembly reference?)    C:\Documents and Settings\Andrew Stout\Microsoft Robotics Dev Studio 2008\cbapi\prototypes\SensorFinder\SensorFinder.cs    133    63    SensorFinder
    if I leave them commented out, it compile and runs, but only gives me the generic service, not the implementing services.)

    thanks,
    Andrew
    Wednesday, July 23, 2008 5:06 AM
  • Hi Andrew, the compile errors are becaus ein CTP2 the ServiceSummary type has new fields. Please look at the type in VisualStudio or (my preferred way) look at the generated XML when you run DssInfo on any service. It will contain a serialized service summary.

     

    Now, on the actual issue: You have found a regression. Indeed you *cant* find alternate contract implementation in CTP2 using this api. We will fix this.

     

    What you can do:

     

    1) QueryByContract, set Contract = null, this will return all service summaries. Then search through them(under the ServiceSummary alternaet contract field) to find the ones that match

    2) Use the Category attribute on your new service, then QueryByCategery

     

    hope this helps and thank you for reporting this. We do have tests that are suppoosed to verify Alternate contract searching so i will look into why they didnt catch this

    Friday, July 25, 2008 7:14 PM