Traversing the Tree: Using the get_relatedCategories API in UDDI Services

 

Karsten Januszewski
Microsoft Corporation

November 2002

Applies to:
   UDDI Specification
   UDDI Business Registry
   UDDI Services in Microsoft® Windows® Server 2003

Summary: Karsten Januszewski explains how and why to use the get_relatedCategories API, an extension API for accessing and retrieving a list of values within a given categorization scheme in a Microsoft UDDI node. (13 printed pages)

Contents

Introduction
Scenarios for Using the get_relatedCategories API
An Example Categorization Scheme
Taking a Closer Look at the get_relatedCategories API
Using the get_relatedCategories API: WSDL and Sample Code
Conclusion
For More Information:

Introduction

The ability to use categorization schemes to classify data in Universal Description Discovery and Integration (UDDI) is key to the UDDI mission of description and discovery. While the ability to categorize UDDI entries is a core part of the UDDI specification, the specification provides no API facility for querying to retrieve a list of values within a given categorization scheme.

In order to address this need, Microsoft UDDI nodes (both the publicly available UDDI Business Registry node as well as private UDDI Services nodes available in Microsoft® Windows® Server 2003) provide an extension API for accessing this information called the get_relatedCategories API. This paper explains how and why to use this API.

Scenarios for Using the get_relatedCategories API

There are several reasons why one might want to gain access to the set of values of a categorization scheme in UDDI.

  1. Writing custom user interfaces to UDDI. A Web user interface accompanies each instance of a Microsoft UDDI implementation that will meet most needs. Occasionally, a custom user interface is required. For a custom user interface, the user might need categorization information as well. Thus, being able to present categorization information to the user for both publish and search operations becomes critical.
  2. Providing categorization metadata when installing applications that register themselves in UDDI. Consider the case when the installation procedure for a piece of software requires registration in a UDDI Services node. The installation wizard might want to allow the user to categorize the application with the custom classification schemes that are unique to the organization. By using this API, the installation wizard could dynamically present those schemes to the user.
  3. Using UDDI to dynamically configure applications. One scenario for using UDDI is as an abstract layer between Web services and their clients. (For more on this design methodology, see Using UDDI at Run Time, Part I and Part II. In particular, clients might query UDDI at run time to determine the best service to bind to. Because those queries may be based on categorization information, the client may need to dynamically navigate a categorization scheme to discover services.

An Example Categorization Scheme

In order to best understand how to use the get_relatedCategories API, we will look at some samples at the XML level. First, we will look at the XML representation of a categorization scheme and then look at the different API calls that might be issued to retrieve pieces of the categorization scheme.

Consider the creation of a geographical classification scheme for a university. A fragment of such a scheme might look as follows:

Figure 1.

This scheme uses Main Campus as a root node, with each building on the campus as a child. Then, of course, each building has rooms, which are represented as children of the building. Below is a sample of an XML file that represents this scheme in UDDI Services. It looks as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Sample categorization scheme -->
<resources xmlns="urn:uddi-microsoft-com:api_v2_extensions" xmlns:uddi="urn:uddi-org:api_v2" >
   <categorizationSchemes>
      <categorizationScheme checked="false">
         <uddi:tModel 
tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc">
            <uddi:name>Sample Geographic Categorization Scheme</uddi:name>
            <uddi:description xml:lang="en">This categorization scheme is 
                  intended for describing buildings and rooms on a campus.
</uddi:description>
            <uddi:categoryBag>
               <uddi:keyedReference 
tModelKey="uuid:c1acf26d-9672-4404-9d70-39b756e62ab4" keyName="types" 
                              keyValue="categorization"/>
            </uddi:categoryBag>
         </uddi:tModel>
         <categoryValue keyValue="0" keyName="Main Campus" isValid="false" 
                              parentKeyValue=""/>
         <categoryValue keyValue="1" keyName="Building 1" isValid="false" 
parentKeyValue="0"/>
         <categoryValue keyValue="2" keyName="Building 2" isValid="false" 
parentKeyValue="0"/>
         <categoryValue keyValue="3" keyName="Building 3" isValid="false" 
parentKeyValue="0"/>
         <categoryValue keyValue="1/10" keyName="Room 10" isValid="true" parentKeyValue="1"/>
         <categoryValue keyValue="1/11" keyName="Room 11" isValid="true" parentKeyValue="1"/>
         <categoryValue keyValue="1/12" keyName="Room 12" isValid="true" parentKeyValue="1"/>
      </categorizationScheme>
   </categorizationSchemes>
</resources>

For a complete decomposition of the different elements and attributes of this scheme, see The Importance of Metadata: Categorization, Reification and UDDI.

Taking a Closer Look at the get_relatedCategories API

The next step is to look at how we might access the information in this scheme. Imagine writing a UI that presents classification schemes to a user. In order to write such a UI, we might want to ask the following kinds of questions at an API level to the UDDI server:

  1. What are all the classification schemes available for browsing within UDDI Services? After all, a client user interface may not know that this Campus Map classification scheme even exists.
  2. Once the UI discovers the taxonomy, how can it navigate to the top-level element of the taxonomy? For example, in the taxonomy presented above, how can one get to the root value of Main Campus so that we can begin to walk the tree and present it to the user?
  3. What are all the children of a given node in the taxonomy? For example, given that we know of the Main Campus node, how can we present its children?

Let's tackle how to get answers to these questions one at a time. The first question—how can one discover all the classification schemes available for browsing—can be answered using the UDDI API. The XML representation of this call would look like this:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <find_tModel generic="2.0" xmlns="urn:uddi-org:api_v2">
         <categoryBag>
            <keyedReference 
tModelKey="uuid:c1acf26d-9672-4404-9d70-39b756e62ab4"
keyValue="categorization"/>
         </categoryBag>
      </find_tModel>
   </Body>
</Envelope>

This query looks for all tModels that have been categorized using the canonical uddi-org:types taxonomy as a classification scheme. Issuing this query will return a list of tModels that represent classification schemes. Two are returned in the example below:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <tModelList generic="2.0" operator="UDDI Sandbox" truncated="false" 
                  xmlns="urn:uddi-org:api_v2">
      <tModelInfos>
        <tModelInfo tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc">
          <name>Sample Geographic Categorization Scheme</name>
        </tModelInfo>
        <tModelInfo tModelKey="uuid:4c1f2e1f-4b7c-44eb-9b87-6e7d80f82b3e">
          <name>microsoft-com:visualstudio-net</name>
        </tModelInfo>
      </tModelInfos>
    </tModelList>
  </soap:Body>
</soap:Envelope>

We can then use the tModelKeys of these tModels to find out more about the value sets they represent. However, calling get_tModelDetail through the UDDI API provided in the UDDI specification (within the urn:uddi-org:api or urn:uddi-org:api_v2 namespaces) will only provide additional information such as a description and an overview URL; this API will not provide the value set of the classification scheme.

Thus, the remainder of our questions will be answered through a Microsoft extension API entitled the get_relatedCategories API (within the urn:uddi-microsoft-com:api_v2_extensions namespace). This API, offered as a Web service available on all Microsoft UDDI Services installations, provides a single method called get_relatedCategories. The WSDL and XSD schema for this Web service provide a complete signature for how to call this API. It can be accessed at the Microsoft UBR node or from a private instance of UDDI Services at http://<server name>/uddi/extension.asmx or http://<server name>/uddipublic/extension.asmx (depending on which authentication style).

Fundamentally, the API works as follows: the client can pass a collection of category arguments, each of which represents a different classification scheme. Each category argument contains a tModelKey attribute, the unique GUID that identifies that scheme in the UDDI registry. Additionally, the category argument specifies the kind of nodes from the taxonomy that should be returned. This is done using an enumeration of three values: root, parent or child. Declaring the root value in the enumeration returns the foundational values of the taxonomy. One does not have to declare a relative value from which to navigate with root. Child returns the values below a given value while parent returns the values above a given value.

Using the get_relatedCategories API, answers to our remaining questions can be determined. Recall question #2, how to determine the root nodes of a classification scheme. Once we have the tModelKey, we can get the root node of a taxonomy with the get_relatedCategories API as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <get_relatedCategories 
xmlns="urn:uddi-microsoft-com:api_v2_extensions"
xmlns:uddi="urn:uddi-org:api_v2" >
         <category tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc">
            <relationshipQualifier>root</relationshipQualifier>
         </category>
      </get_relatedCategories>
   </Body>
</Envelope>

This message states, "Get the root node for the taxonomy represented by the tModelKey, uuid:08499e35-1c8f-489b-9b0b-504eb50947cc," which happens to be the Sample Geographic Classification Scheme. The return message would look as follows:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <categoryList truncated="false" operator="UDDI Services" 
                  xmlns="urn:uddi-microsoft-com:api_v2_extensions">
      <categoryInfo tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc" 
                  isValid="false">
        <rootRelationship>
          <categoryValue keyName="Main Campus" keyValue="0" 
                  parentKeyValue="" isValid="false" />
        </rootRelationship>
      </categoryInfo>
    </categoryList>
  </soap:Body>
</soap:Envelope>

One can see that a rootRelationship element is returned, containing the keyValue and keyName of the root of this taxonomy, in this case the value 0, which correlates to the top-level value in our sample Campus Map scheme. Because this is a root element, the parentKeyValue is set to an empty string. The isValid attribute indicates that this value is not available for categorization purposes by a user, but is only to be used for navigating to other values.

Now, consider the next question—asking for all the child values of this root value. Instead of passing the value root in the relationshipQualifier element, the value child is passed along with the value to work from, in this case, the keyValue 0.

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <get_relatedCategories 
xmlns="urn:uddi-microsoft-com:api_v2_extensions"
xmlns:uddi="urn:uddi-org:api_v2" >
         <category tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc" keyValue="0">
            <relationshipQualifier>child</relationshipQualifier>
         </category>
      </get_relatedCategories>
   </Body>
</Envelope>

Note how the keyValue of the categorization scheme was added as an attribute to the query. Also, note how a different relationshipQualifier was passed, indicating that the children of this node were requested. The response message would be as follows:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <categoryList truncated="false" operator="UDDI Services" 
                  xmlns="urn:uddi-microsoft-com:api_v2_extensions">
      <categoryInfo tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc" 
                  keyName="Main Campus" keyValue="0" isValid="false">
        <childRelationship>
          <categoryValue keyName="Building 1" keyValue="1" 
                  parentKeyValue="0" isValid="false" />
          <categoryValue keyName="Building 2" keyValue="2" 
                  parentKeyValue="0" isValid="false" />
          <categoryValue keyName="Building 3" keyValue="3" 
                  parentKeyValue="0" isValid="false" />
        </childRelationship>
      </categoryInfo>
    </categoryList>
  </soap:Body>
</soap:Envelope>

What if we wanted to ask for the parent of a value as well as the children? For example, what is the parent of Building 1 and what are Building 1's children? In this case, we pass two relationshipQualifier elements, one specifying child and one specifying root:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <get_relatedCategories 
xmlns="urn:uddi-microsoft-com:api_v2_extensions"
xmlns:uddi="urn:uddi-org:api_v2" >
         <category tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc" keyValue="1">
            <relationshipQualifier>child</relationshipQualifier>
            <relationshipQualifier>parent</relationshipQualifier>
         </category>
      </get_relatedCategories>
   </Body>
</Envelope>

In this instance, both the parent and child relationship collection is returned:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <categoryList truncated="false" operator="UDDI Services" 
                  xmlns="urn:uddi-microsoft-com:api_v2_extensions">
      <categoryInfo tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc" 
                  keyName="Building 1" keyValue="1" isValid="false">
        <parentRelationship>
          <categoryValue keyName="Main Campus" keyValue="0" parentKeyValue="" isValid="false" />
        </parentRelationship>
        <childRelationship>
          <categoryValue keyName="Room 10" keyValue="1/10" parentKeyValue="1" isValid="true" />
          <categoryValue keyName="Room 11" keyValue="1/11" parentKeyValue="1" isValid="true" />
          <categoryValue keyName="Room 12" keyValue="1/12" parentKeyValue="1" isValid="true" />
        </childRelationship>
      </categoryInfo>
    </categoryList>
  </soap:Body>
</soap:Envelope>

Finally, it should be noted that multiple category entities can be passed in a single API call, so as to avoid roundtrips. Thus, we can submit a message that asked for the children of Building 1, Building 2 and Building 3 as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <get_relatedCategories 
xmlns="urn:uddi-microsoft-com:api_v2_extensions"
xmlns:uddi="urn:uddi-org:api_v2" >
         <category tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc" keyValue="1">
            <relationshipQualifier>child</relationshipQualifier>
         </category>
         <category tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc" keyValue="2">
            <relationshipQualifier>child</relationshipQualifier>
         </category>
         <category tModelKey="uuid:08499e35-1c8f-489b-9b0b-504eb50947cc" keyValue="3">
            <relationshipQualifier>child</relationshipQualifier>
         </category>
      </get_relatedCategories>
   </Body>
</Envelope>

Using the get_relatedCategories API: WSDL and Sample Code

At present, this API is not supported in the beta versions of UDDI .NET SDK. However, it will be supported in the Version 2 release of the SDK, with complete documentation.

If you'd like to start using this API today, a WSDL file is available. Use either Add Web Reference in Visual Studio .NET to create a proxy class for this Web Service or the WSDL.exe tool that comes with the .NET Framework SDK.

Once a proxy class is generated, set the access point for this proxy, pointing either to the Microsoft UBR node or your own instance of UDDI Services (http://<server name>/uddi/extension.asmx or http://<server name>/uddipublic/extension.asmx).

The following code sample shows this proxy class in action. To run the sample, create a new console application in C#. Then, add a Web Reference, pointing to the WSDL file. Cut and paste the code below and you should be good to go. The application will query the Microsoft node of the UBR and display all the values in the Microsoft® Visual Studio® .NET Web Service Categorization Scheme:

using System;
namespace ConsoleApplication
{
   class Class1
   {
      [STAThread]
      static void Main(string[] args)
      {

         //create an instance of the proxy
         extensions_binding proxy = new extensions_binding();
         //set the URL to the UBR extensions.asmx URL
         proxy.Url = "http://uddi.microsoft.com/extension.asmx";
         //create a new category object
         get_relatedCategoriesCategory grcc = new get_relatedCategoriesCategory();
         //set the tModelKey to the GUID of the VS.NET taxonomy
         grcc.tModelKey = "uuid:4c1f2e1f-4b7c-44eb-9b87-6e7d80f82b3e";
         //create a relationshipQualifierType array with one value from 
                  the enumeration
         relationshipQualifiersType[] rqt =  { relationshipQualifiersType.root };
         //add that array to the relationshipQualifier array
         grcc.relationshipQualifier = rqt;
         //add our category object to the an array of category objects
         get_relatedCategoriesCategory[] grccarray = { grcc };
         try
         {
            //add our array to the proxy class object, which will send the 
                  request over the wire
            categoryList cl = proxy.get_relatedCategories( grccarray );

            //walk the returned categoryInfo – the first object in the 
                  array since we only asked for one – we also know we want 
                     the rootRelationship array of this object since we 
                        specified the root enum in our request message
            for ( int i = 0; i < cl.categoryInfo[0].rootRelationship.Length; i++ )
            {
               //print the keyName and keyValue to the console
               Console.WriteLine ( "{0} \t {1}", 
                  cl.categoryInfo[0].rootRelationship[i].keyValue, 
                     cl.categoryInfo[0].rootRelationship[i].keyName );
            }
         }
         catch (Exception e)
         {
            Console.WriteLine ( e );
         }
         Console.ReadLine();
      }
   }
}

Conclusion

The get_relatedCategories API is a powerful enhancement to UDDI provided with the Microsoft UDDI Services shipping with Windows Server 2003. It allows developers to access and traverse the hierarchy of a taxonomy that has been imported into a UDDI Services instance, giving developers the freedom to create applications that take advantage of the UDDI metadata strategy.

For More Information

To read my Web log on UDDI, check out the GotDotNet Web site for various musings and meditations on UDDI.

Show: