Service Registry 3 2005Q4 Developer's Guide

Chapter 3 Querying a Registry

This section describes the interfaces and methods that JAXR provides for querying a registry. The section covers the following topics:

Basic Query Methods

The simplest way for a client to use a registry is to query the registry for information about the objects and data it contains. The QueryManager, BusinessQueryManager, and RegistryObject interfaces support a number of finder and getter methods. These methods allow clients to search for data by using the JAXR information model. Many of the finder methods return a BulkResponse. A BulkResponse is a collection of objects that meets a set of criteria that are specified in the method arguments. The most general of these methods are as follows:

Other finder methods allow you to find specific kinds of objects supported by the JAXR information model. A UDDI registry supports a specific hierarchy of objects: organizations, which contain users, services, and service bindings. In contrast, an ebXML registry permits the storage of freestanding objects of various types that can be linked to each other in various ways. Other objects are not freestanding but are always attributes of another object.

The BusinessQueryManager finder methods are useful primarily for searching UDDI registries. The more general findObjects method and the RegistryObject getter methods are more appropriate for Service Registry.

To execute queries, you do not need to log in to the Registry. By default, an unauthenticated user has the identity of the user named “Registry Guest.”

JAXR Information Model Interfaces

Table 3–1 lists the main interfaces supported by the JAXR information model. All these interfaces extend the RegistryObject interface.

For more details, and for a figure that illustrates the relationships among these interfaces, see the API documentation for the javax.xml.registry.infomodel package at http://java.sun.com/j2ee/1.4/docs/api/javax/xml/registry/infomodel/package-summary.html.

Table 3–1 JAXR RegistryObject Subinterfaces

Interface Name 

Description 

Association

Defines a relationship between two objects.  

Getter and finder methods: RegistryObject.getAssociations, BusinessQueryManager.findAssociations, BusinessQueryManager.findCallerAssociations.

AuditableEvent

Provides a record of a change to an object. A collection of AuditableEvent objects constitutes an object’s audit trail.

Getter method: RegistryObject.getAuditTrail.

Classification

Classifies an object by using a ClassificationScheme.

Getter method: RegistryObject.getClassifications.

ClassificationScheme

Represents a taxonomy used to classify objects. In an internal ClassificationScheme, all taxonomy elements are defined in the registry as Concept instances. In an external ClassificationScheme, the values are not defined in the registry as Concept instances but instead are referenced by their String representations.

Finder methods: BusinessQueryManager.findClassificationSchemes, BusinessQueryManager.findClassificationSchemeByName.

Concept

Represents a taxonomy element and its structural relationship with other elements in an internal ClassificationScheme. Called a ClassificationNode in the ebXML specifications.

Finder methods: BusinessQueryManager.findConcepts, BusinessQueryManager.findConceptByPath.

ExternalIdentifier

Provides additional information about an object by using String values within an identification scheme (an external ClassificationScheme). Examples of identification schemes are DUNS numbers and Social Security numbers.

Getter method: RegistryObject.getExternalIdentifiers.

ExternalLink

Provides a URI for content that resides outside the registry.  

Getter method: RegistryObject.getExternalLinks.

ExtrinsicObject

Provides metadata that describes submitted content whose type is not intrinsically known to the registry and that therefore must be described by means of additional attributes, such as MIME type.  

No specific getter or finder methods. 

Organization

Provides information about an organization. May have a parent, and may have one or more child organizations. Always has a User object as a primary contact, and may offer Service objects. 

Finder method: BusinessQueryManager.findOrganizations.

RegistryPackage

Represents a logical grouping of registry objects. A RegistryPackage may have any number of RegistryObjects.

Getter and finder methods: RegistryObject.getRegistryPackages, BusinessQueryManager.findRegistryPackages.

Service

Provides information on a service. May have a set of ServiceBinding objects.

Finder method: BusinessQueryManager.findServices.

ServiceBinding

Represents technical information on how to access a Service.

Getter and finder methods: Service.getServiceBindings, BusinessQueryManager.findServiceBindings.

Slot

Provides a dynamic way to add arbitrary attributes to RegistryObject instances.

Getter methods: RegistryObject.getSlot, RegistryObject.getSlots.

SpecificationLink

Provides the linkage between a ServiceBinding and a technical specification that describes how to use the service by using the ServiceBinding.

Getter method: ServiceBinding.getSpecificationLinks.

User

Provide information about registered users within the registry. User objects are affiliated with Organization objects.

Getter methods: Organization.getUsers, Organization.getPrimaryContact.

Table 3–2 lists the other interfaces supported by the JAXR information model. These interfaces provide attributes for the main registry objects. These interfaces do not extend the RegistryObject interface.

Table 3–2 JAXR Information Model Interfaces Used as Attributes

Interface Name 

Description 

EmailAddress

Represents an email address. A User can have an EmailAddress.

Getter method: User.getEmailAddresses.

InternationalString

Represents a String that can be internationalized into several locales. Contains a Collection of LocalizedString objects. The name and description of a RegistryObject are InternationalString objects.

Getter methods: RegistryObject.getName, RegistryObject.getDescription.

Key

An object that identifies a RegistryObject. Contains a unique identifier value that must be a DCE 128 UUID (Universal Unique IDentifier).

Getter method: RegistryObject.getKey.

LocalizedString

A component of an InternationalString that associates a String with its Locale.

Getter method: InternationalString.getLocalizedStrings.

PersonName

Represents a person’s name. A User has a PersonName.

Getter method: User.getPersonName.

PostalAddress

Represents a postal address. An Organization or User can have one or more PostalAddress objects.

Getter methods: Organization.getPostalAddress, OrganizationImpl.getPostalAddresses (implementation-specific), User.getPostalAddresses.

TelephoneNumber

Represents a telephone number. An Organization or a User can have one or more TelephoneNumber objects.

Getter methods: Organization.getTelephoneNumbers, User.getTelephoneNumbers.

Finding Objects by Unique Identifier

Every object in the Registry has two identifiers, a unique identifier (also called a Key) and a logical identifier. Often, the unique identifier is the same as the logical identifier. However, when an object exists in more than one version, the unique identifiers are different for each version, but the logical identifier remains the same. (See Retrieving the Version of an Object.)

If you know the value of the unique identifier for an object, you can retrieve the object by calling the QueryManager.getRegistryObject method with the String value as an argument. For example, if bqm is your BusinessQueryManager instance and idString is the String value, the following line of code retrieves the object:

RegistryObject obj = bqm.getRegistryObject(idString);

After you have the object, you can obtain its type, name, description, and other attributes.

Finding Objects by Unique Identifier: Example

For an example of finding objects by unique identifier, see JAXRSearchById.java in the directory <INSTALL>/registry/samples/search-id/src, which searches for objects that have a specified unique identifier.

ProcedureTo Run the JAXRSearchById Example

Steps
  1. Go to the directory <INSTALL>/registry/samples/search-id.

  2. Type the following command:


    asant run -Did=urn_value
    

    For example, if you specify the following ID, you retrieve information on the ObjectType classification scheme.


    urn:oasis:names:tc:ebxml-regrep:classificationScheme:ObjectType

Finding Objects by Name

To search for objects by name, you normally use a combination of find qualifiers and name patterns. Find qualifiers affect sorting and pattern matching. Name patterns specify the strings to be searched. The BusinessQueryManagerImpl.findObjects method takes a collection of FindQualifier objects as its second argument and takes a collection of name patterns as its third argument. The method signature is as follows:

public BulkResponse findObjects(java.lang.String objectType,
        java.util.Collection findQualifiers,
        java.util.Collection namePatterns,
        java.util.Collection classifications,
        java.util.Collection specifications,
        java.util.Collection externalIdentifiers,
        java.util.Collection externalLinks)
    throws JAXRException

For the first argument, the object type, you normally specify one of a set of string constants that are defined in the LifeCycleManager interface.

You can use wildcards in a name pattern. Use percent signs (%) to specify that the search string occurs at the beginning, middle, or end of the object name. Here are some examples:

You can also use an underscore (_) as a wildcard to match a single character. For example, the search string _us_ would match objects named Aus1 and Bus3.

For example, the following code fragment finds all the organizations in the Registry whose names begin with a specified string, searchString, and sorts them in alphabetical order.

// Define find qualifiers and name patterns
Collection findQualifiers = new ArrayList();
findQualifiers.add(FindQualifier.SORT_BY_NAME_ASC);
Collection namePatterns = new ArrayList();
namePatterns.add(searchString + "%");

// Find organizations with name that starts with searchString
BulkResponse response =
     bqm.findObjects("Organization", findQualifiers,
         namePatterns, null, null, null, null);
Collection orgs = response.getCollection();

The findObjects method is not case-sensitive, unless you specify FindQualifier.CASE_SENSITIVE_MATCH. In the previous fragment, the first argument could be either "Organization" or "organization", and the name pattern matches names regardless of case.

The following code fragment performs a case-sensitive search for all registry objects whose names contain the string searchString and sorts the objects in alphabetical order.

Collection findQualifiers = new ArrayList();
findQualifiers.add(FindQualifier.CASE_SENSITIVE_MATCH);
findQualifiers.add(FindQualifier.SORT_BY_NAME_ASC);
Collection namePatterns = new ArrayList();
namePatterns.add("%" + searchString + "%");

// Find objects with name that contains searchString
BulkResponse response =
     bqm.findObjects("RegistryObject", findQualifiers,
         namePatterns, null, null, null, null);
Collection orgs = response.getCollection();

The percent sign matches any number of characters in the name. To match a single character, use the underscore (_). For example, to match both “Arg1” and “Org2” you would specify a name pattern of _rg_.

Finding Objects by Name: Example

For an example of finding objects by name, see JAXRSearchByName.java in the directory <INSTALL>/registry/samples/search-name/src.

ProcedureTo Run the JAXRSearchByName Example

Steps
  1. Go to the directory <INSTALL>/registry/samples/search-name.

  2. Type the following command, specifying a string value:


    asant run -Dname=string
    

    The program performs a case-insensitive search, returning all objects whose names contain the specified string. The program also displays the object’s classifications, external identifiers, external links, slots, and audit trail.

Finding Objects by Type

To find all objects of a specified type, specify only the first argument of the BusinessQueryManagerImpl.findObjects method and, optionally, a collection of FindQualifier objects. For example, if typeString is a string whose value is either "Service" or "service", the following code fragment finds all services in the Registry and sorts them in alphabetical order.

Collection findQualifiers = new ArrayList();
findQualifiers.add(FindQualifier.SORT_BY_NAME_ASC);

BulkResponse response = bqm.findObjects(typeString,
     findQualifiers, null, null, null, null, null);

You cannot use wildcards in the first argument to findObjects.

Finding Objects by Type: Example

For an example of finding objects by type, see JAXRSearchByObjectType.java in the directory <INSTALL>/registry/samples/search-object-type/src.

ProcedureTo Run the JAXRSearchByObjectType Example

Steps
  1. Go to the directory <INSTALL>/registry/samples/search-object-type.

  2. Type the following command, specifying a string value:


    asant run -Dtype=type_name
    

    The program performs a case-insensitive search, returning all objects whose type is type_name and displaying their names, descriptions, and unique identifiers. Specify the exact name of the type, not a wildcard, as in the following command line:


    asant run -Dtype=federation
    

Finding Objects by Classification

To find objects by classification, you first establish the classification within a particular classification scheme. Then you specify the classification as an argument to the BusinessQueryManagerImpl.findObjects method.

To establish the classification within a particular classification scheme, you first find the classification scheme. Then you create a Classification object to be used as an argument to the findObjects method or another finder method.

The following code fragment finds all organizations that correspond to a particular classification within the ISO 3166 country codes classification system that is maintained by the International Organization for Standardization (ISO). See http://www.iso.org/iso/en/prods-services/iso3166ma/index.html for details. This classification scheme is provided in the sample database that is included with the Registry.

ClassificationScheme cScheme =
     bqm.findClassificationSchemeByName(null,
         "iso-ch:3166:1999");

Classification classification =
     blcm.createClassification(cScheme, "United States", "US");
Collection classifications = new ArrayList();
classifications.add(classification);
// perform search
BulkResponse response = bqm.findObjects("Organization", null,
    null, classifications, null, null, null);
Collection orgs = response.getCollection();

The ebXML Registry Information Model Specification requires a set of canonical classification schemes to be present in an ebXML registry. Each scheme also has a set of required concepts (which are called ClassificationNode objects in the ebXML specifications). The primary purpose of the canonical classification schemes is not to classify objects but to provide enumerated types for object attributes. For example, the EmailType classification scheme provides a set of values for the type attribute of an EmailAddress object.

Table 3–3 lists and describes these canonical classification schemes.

Table 3–3 Canonical Classification Schemes

Classification Scheme 

Description 

AssociationType

Defines the types of associations between RegistryObjects.

ContentManagementService

Defines the types of content management services. 

DataType

Defines the data types for attributes in classes defined by the specification. 

DeletionScopeType

Defines the values for the deletionScope attribute in the RemoveObjectsRequest protocol message.

EmailType

Defines the types of email addresses. 

ErrorHandlingModel

Defines the types of error handling models for content management services. 

ErrorSeverityType

Defines the different error severity types encountered by the registry during processing of protocol messages. 

EventType

Defines the types of events that can occur in a registry. 

InvocationModel

Defines the different ways that a content management service may be invoked by the registry. 

NodeType

Defines the different ways in which a ClassificationScheme may assign the value of the code attribute for its ClassificationNodes.

NotificationOptionType

Defines the different ways in which a client may be notified by the registry of an event within a Subscription.

ObjectType

Defines the different types of RegistryObjects a registry may support.

PhoneType

Defines the types of telephone numbers. 

QueryLanguage

Defines the query languages supported by a registry. 

ResponseStatusType

Defines the different types of status for a RegistryResponse.

StatusType

Defines the different types of status for a RegistryObject.

SubjectGroup

Defines the groups that a User may belong to for access control purposes.

SubjectRole

Defines the roles that may be assigned to a User for access control purposes.

To find objects that use the canonical classification schemes and their concepts, you can look up the objects by using string constants that are defined in the package org.freebxml.common.CanonicalConstants. The constants are listed in Constants for Classification Schemes.

First, you look up the classification scheme by using the value of its unique identifier:

String schemeId = 
    CanonicalConstants.CANONICAL_CLASSIFICATION_SCHEME_ID_SubjectRole;
ClassificationScheme cScheme = 
    (ClassificationScheme) bqm.getRegistryObject(schemeId);
String schemeName = getName(cScheme);

Then you look up the concept in the same way and create a classification from it:

String concId = 
    CanonicalConstants.CANONICAL_SUBJECT_ROLE_ID_RegistryAdministrator;
Concept concept = (Concept) bqm.getRegistryObject(concId);
Classification classification = 
    blcm.createClassification(concept);

Finally, you search for objects in the same way you do with a non-canonical classification scheme:

Collection classifications = new ArrayList();
classifications.add(classification);
BulkResponse response = bqm.findObjects("RegistryObject", 
    null, null, classifications, null, null, null);
Collection objects = response.getCollection();

For a sample program that displays all the canonical classification schemes and their concepts, see JAXRGetCanonicalSchemes.java in the directory <INSTALL>/registry/samples/classification-schemes/src.

ProcedureTo Run the JAXRGetCanonicalSchemes Example

Steps
  1. Go to the directory <INSTALL>/registry/samples/classification-schemes.

  2. Type the following command:


    asant get-schemes
    

Finding Objects by Classification: Examples

For examples of finding objects by classification, see JAXRSearchByClassification.java and JAXRSearchByCountryClassification.java in the directory <INSTALL>/registry/samples/search-classification/src. The first example searches for objects that use the canonical classification scheme SubjectRole, while the other example searches for organizations that use a geographical classification.

ProcedureTo Run the JAXRSearchByClassification and JAXRSearchByCountryClassification Examples

Before You Begin

To obtain results from the JAXRSearchByCountryClassification example, you must publish an object that uses the specified classifications. Run the example in either Adding Classifications: Example or Creating an Organization: Examples first.

Steps
  1. Go to the directory <INSTALL>/registry/samples/search-classification.

  2. Type either of the following commands:


    asant search-class
    asant search-geo
    

    The search-class target typically returns one result. The search-geo target returns results if you have run the run target in Adding Classifications: Example or the pub-org target in Creating an Organization: Examples.

Finding Objects by External Identifier

Finding objects by external identifier is similar to finding objects by classification. You first find the classification scheme, then create an ExternalIdentifier object to be used as an argument to the BusinessQueryManagerImpl.findObjects method or another finder method.

The following code fragment finds all registry objects that contain the Sun Microsystems stock ticker symbol as an external identifier. You need to create an external classification scheme named NASDAQ for this example to work. See Adding External Identifiers to Objects for details on how to perform this task.

The collection of external identifiers is supplied as the next-to-last argument of the findObjects method.

ClassificationScheme cScheme = null;
cScheme =
     bqm.findClassificationSchemeByName(null, "NASDAQ");

ExternalIdentifier extId =
     blcm.createExternalIdentifier(cScheme, "%Sun%",
        "SUNW");
Collection extIds = new ArrayList();
extIds.add(extId);
// perform search
BulkResponse response = bqm.findObjects("RegistryObject",
     null, null, null, null, extIds, null);
Collection objects = response.getCollection();

Finding Objects by External Identifier: Example

For an example of finding objects by external identifier, see JAXRSearchByExternalIdentifier.java in the directory <INSTALL>/registry/samples/search-external-identifier/src, which searches for objects that use the NASDAQ classification scheme.

ProcedureTo Run the JAXRSearchByExternalIdentifier Example

Before You Begin

To obtain results from this example, first run the publish-object example described in Adding Classifications: Example.

Steps
  1. Go to the directory <INSTALL>/registry/samples/search-external-identifier.

  2. Type the following command:


    asant run
    

Finding Objects by External Link

Finding objects by external link does not require the use of a classification scheme, but it does require you to specify a valid URI. The arguments to the createExternalLink method are a URI and a description.

If the link you specify is outside your firewall, you must also specify the system properties http.proxyHost and http.proxyPort when you run the program so that JAXR can determine the validity of the URI.

The following code fragment finds all organizations that have a specified ExternalLink object.

ExternalLink extLink =
     blcm.createExternalLink("http://java.sun.com/",
         "Sun Java site");

Collection extLinks = new ArrayList();
extLinks.add(extLink);
BulkResponse response = bqm.findObjects("Organization",
     null, null, null, null, null, extLinks);
Collection objects = response.getCollection();

Finding Objects by External Link: Example

For an example of finding objects by external link, see JAXRSearchByExternalLink.java in the directory<INSTALL>/registry/samples/search-external-link/src, which searches for objects that have a specified external link. The http.proxyHost and http.proxyPort properties are specified in the run target in the build.xml file.

ProcedureTo Run the JAXRSearchByExternalLink Example

Before You Begin

To obtain results from this example, first run the publish-object example described in Adding Classifications: Example.

Steps
  1. Go to the directory <INSTALL>/registry/samples/search-external-link.

  2. Type the following command:


    asant run
    

Finding Objects You Published

You can retrieve all objects that you published to the Registry. Alternatively, can narrow the search to retrieve only the objects that you published that are of a particular object type. To retrieve all the objects that you have published, use the no-argument version of the QueryManager.getRegistryObjects method. The name of this method is misleading, because the method returns only objects that you have published, not all registry objects.

For example, if bqm is your BusinessQueryManager instance, use the following line of code:

BulkResponse response = bqm.getRegistryObjects();

To retrieve all the objects of a particular type that you published, use QueryManager.getRegistryObjects with a String argument:

BulkResponse response = bqm.getRegistryObjects("Service");

This method is case-sensitive, so the object type must be capitalized.

The sample programs JAXRGetMyObjects and JAXRGetMyObjectsByType show how to use these methods.

Finding Objects You Published: Examples

For examples of finding objects by classification, see JAXRGetMyObjects.java and JAXRGetMyObjectsByType.java in the directory <INSTALL>/registry/samples/get-objects/src. The first example, JAXRGetMyObjects.java, retrieves all objects you have published. The second example, JAXRGetMyObjectsByType.java, retrieves all the objects you have published of a specified type.

ProcedureTo Run the JAXRGetMyObjects and JAXRGetMyObjectsByType Examples

Steps
  1. Go to the directory <INSTALL>/registry/samples/get-objects.

  2. To find all the objects that you have published, type the following command:


    asant get-obj
    
  3. To find all the objects that you have published of a specified type, type the following command, where type_name is case-sensitive:


    asant get-obj-type -Dtype=type_name
    

Retrieving Information About an Object

After you have retrieved the object or objects you are searching for, you can also retrieve the object’s attributes and other objects that belong to it:

For an organization, you can also retrieve the following:

For a service, you can retrieve the service bindings.

For any object, you can also retrieve the audit trail, which contains the events that have changed the object’s state, and the version. You can also retrieve an object’s version number, which is updated whenever a change is made to one of the object’s attributes.

This section covers the following topics:

Retrieving the Identifier Values for an Object

The unique identifier for an object is contained in a Key object. A Key is a structure that contains the identifier in the form of an id attribute that is a String value. To retrieve the identifier, call the method RegistryObject.getKey().getId().

The JAXR provider also has an implementation-specific method for retrieving the logical identifier, which is called a lid. The lid is a String attribute of a RegistryObject. To retrieve the lid, call RegistryObjectImpl.getLid. The method has the following signature:

public java.lang.String getLid()
    throws JAXRException

For an example of the use of this method, see JAXRSearchOrg.java in the directory <INSTALL>/registry/samples/organizations/src. For more information on this example, see Retrieving Organization Attributes: Example.

Retrieving the Name or Description of an Object

The name and description of an object are both InternationalString objects. An InternationalString object contains a set of LocalizedString objects. The methods RegistryObject.getName and RegistryObject.getDescription return the LocalizedString object for the default locale. You can then retrieve the String value of the LocalizedString object. The following code fragment uses these methods:

String name = ro.getName().getValue();
String description = ro.getDescription().getValue();

Call the getName or getDescription method with a Locale argument to retrieve the value for a particular locale.

Many of the examples contain private utility methods that retrieve the name, description, and unique identifier for an object. See, for example, JAXRGetMyObjects.java in the directory <INSTALL>/registry/samples/get-objects/src.

Retrieving the Type of an Object

If you have searched the Registry without specifying a particular object type, you can retrieve the type of the objects returned by the search. Use the RegistryObject.getObjectType method, which returns a Concept value. You can then use the Concept.getValue method to obtain the String value of the object type. The following code fragment uses these methods:

Concept objType = object.getObjectType();
System.out.println("Object type is " + objType.getValue());

The concept will be one of those in the canonical classification scheme ObjectType. For an example of this code, see JAXRSearchByName.java in the directory <INSTALL>/registry/samples/search-name/src.

Retrieving the Classifications for an Object

Use the RegistryObject.getClassifications method to retrieve a Collection of the object’s classifications. For a classification, the important attributes are its value and the classification scheme to which it belongs. Often, a classification has no name or description. The following code fragment retrieves and displays an object’s classifications.

Collection classifications = object.getClassifications();
Iterator classIter = classifications.iterator();
while (classIter.hasNext()) {
    Classification classification =
         (Classification) classIter.next();
    String name = classification.getName().getValue();
    System.out.println("  Classification name is " + name);
    System.out.println("  Classification value is " +
        classification.getValue());
    ClassificationScheme scheme =
         classification.getClassificationScheme();
    System.out.println("  Classification scheme for " +
        name + " is " + scheme.getName().getValue());
}

Some of the examples have a showClassifications method that uses code similar to this. See, for example, JAXRSearchByName.java in the directory <INSTALL>/registry/samples/search-name/src.

Retrieving the External Identifiers for an Object

Use the RegistryObject.getExternalIdentifiers method to retrieve a Collection of the object’s external identifiers. For each identifier, you can retrieve its name, value, and the classification scheme to which it belongs. For an external identifier, the method that retrieves the classification scheme is getIdentificationScheme. The following code fragment retrieves and displays an object’s external identifiers.

Collection exIds = object.getExternalIdentifiers();
Iterator exIdIter = exIds.iterator();
while (exIdIter.hasNext()) {
    ExternalIdentifier exId =
         (ExternalIdentifier) exIdIter.next();
    String name = exId.getName().getValue();
    System.out.println("  External identifier name is " +
        name);
    String exIdValue = exId.getValue();
    System.out.println("  External identifier value is " +
         exIdValue);
    ClassificationScheme scheme =
         exId.getIdentificationScheme();
    System.out.println("  External identifier " +
         "classification scheme is " +
         scheme.getName().getValue());
}

Some of the examples have a showExternalIdentifiers method that uses code similar to this. See, for example, JAXRSearchByName.java in the directory <INSTALL>/registry/samples/search-name/src.

Retrieving the External Links for an Object

Use the RegistryObject.getExternalLinks method to retrieve a Collection of the object’s external links. For each external link, you can retrieve its name, description, and value. For an external link, the name is optional. The following code fragment retrieves and displays an object’s external links.

Collection exLinks = obj.getExternalLinks();
Iterator exLinkIter = exLinks.iterator();
while (exLinkIter.hasNext()) {
    ExternalLink exLink = (ExternalLink) exLinkIter.next();
    String name = exLink.getName().getValue();
    if (name != null) {
        System.out.println("  External link name is " + name);
    }
    String description = exLink.getDescription().getValue();
    System.out.println("  External link description is " +
        description);
    String externalURI = exLink.getExternalURI();
    System.out.println("  External link URI is " +
         externalURI);
}

Some of the examples have a showExternalLinks method that uses code similar to this. See, for example, JAXRSearchByName.java in the directory <INSTALL>/registry/samples/search-name/src.

Retrieving the Slots for an Object

Slots are arbitrary attributes that you can create for an object. Use the RegistryObject.getSlots method to retrieve a Collection of the object’s slots. For each slot, you can retrieve its name, values, and type. The name of a Slot object is a String, not an InternationalString, and a slot has a Collection of values. The following fragment retrieves and displays an object’s slots:

Collection slots = object.getSlots();
Iterator slotIter = slots.iterator();
while (slotIter.hasNext()) {
    Slot slot = (Slot) slotIter.next();
    String name = slot.getName();
    System.out.println("  Slot name is " + name);
    Collection values = slot.getValues();
    Iterator valIter = values.iterator();
    int count = 1;
    while (valIter.hasNext()) {
        String value = (String) valIter.next();
        System.out.println("  Slot value " + count++ +
             ": " + value);
    }
    String type = slot.getSlotType();
    if (type != null) {
        System.out.println("  Slot type is " + type);
}

Some of the examples have a showSlots method that uses this code. See, for example, JAXRSearchByName.java in the directory <INSTALL>/registry/samples/search-name/src.

Retrieving the Attributes of an Organization or User

Every Organization object can have one postal address and multiple telephone numbers in addition to the attributes that are available to all other objects. Every organization also has a User object as a primary contact. The organization can have additional affiliated User objects.

The attributes for a User object include a PersonName object, which has a different format from the name of an object. A user can have multiple postal addresses as well as multiple telephone numbers. A user can also have multiple email addresses.

To retrieve the postal address for an organization, call the Organization.getPostalAddress method as follows (org is the organization):

PostalAddress pAd = org.getPostalAddress();

After you retrieve the address, you can retrieve the address attributes as follows:

System.out.println(" Postal Address:\n  " +
    pAd.getStreetNumber() + " " + pAd.getStreet() +
    "\n  " + pAd.getCity() + ", " +
    pAd.getStateOrProvince() + " " +
    pAd.getPostalCode() + "\n  " + pAd.getCountry() +
    "(" + pAd.getType() + ")");

To retrieve the primary contact for an organization, call the Organization.getPrimaryContact method as follows (org is the organization):

User pc = org.getPrimaryContact();

To retrieve the postal addresses for a user, call the User.getPostalAddresses method and extract the Collection values as follows (pc is the primary contact):

Collection pcpAddrs = pc.getPostalAddresses();
Iterator pcaddIter = pcpAddrs.iterator();
while (pcaddIter.hasNext()) {
    PostalAddress pAd = (PostalAddress) pcaddIter.next();
    /* retrieve attributes */
}

To retrieve the telephone numbers for either an organization or a user, call the getTelephoneNumbers method. In the following code fragment, org is the organization. The code retrieves the country code, area code, main number, and type of the telephone number.

Collection orgphNums = org.getTelephoneNumbers(null);
Iterator orgphIter = orgphNums.iterator();
while (orgphIter.hasNext()) {
    TelephoneNumber num = (TelephoneNumber) orgphIter.next();
    System.out.println(" Phone number: " +
         "+" + num.getCountryCode() + " " +
        "(" + num.getAreaCode() + ") " +
        num.getNumber() + " (" + num.getType() + ")");
}

A TelephoneNumber can also have an extension, retrievable through the getExtension method. If the number can be dialed electronically, it can have a url attribute, retrievable through the getUrl method.

To retrieve the name of a user, call the User.getPersonName method. A PersonName has three attributes that correspond to the given name, middle name(s), and surname of a user. In the following code fragment, pc is the primary contact.

PersonName pcName = pc.getPersonName();
System.out.println(" Contact name: " +
    pcName.getFirstName() + " " +
    pcName.getMiddleName() + " " +
    pcName.getLastName());

To retrieve the email addresses for a user, call the User.getEmailAddresses method. An EmailAddress has two attributes, the address and its type. In the following code fragment, pc is the primary contact.

Collection eAddrs = pc.getEmailAddresses();
Iterator eaIter = eAddrs.iterator();
while (eaIter.hasNext()) {
    EmailAddress eAd = (EmailAddress) eaIter.next();
    System.out.println("  Email address: " +
        eAd.getAddress() + " (" + eAd.getType() + ")");
}

The attributes for PostalAddress, TelephoneNumber, PersonName, and EmailAddress objects are all String values. As noted in JAXR Information Model Interfaces, these objects do not extend the RegistryObject interface, so they do not have the attributes of other registry objects.

Retrieving Organization Attributes: Example

For an example of retrieving the attributes of an organization and the User that is its primary contact, see JAXRSearchOrg.java in the directory <INSTALL>/registry/samples/organizations/src, which displays information about an organization whose name contains a specified string.

ProcedureTo Run the JAXRSearchOrg Example

Steps
  1. Go to the directory <INSTALL>/registry/samples/organizations.

  2. Type the following command:


    asant search-org -Dorg=string
    

Retrieving the Services and Service Bindings for an Organization

Most organizations offer services. JAXR has methods that retrieve the services and service bindings for an organization.

A Service object has all the attributes of other registry objects. In addition, it normally has service bindings, which provide information about how to access the service. A ServiceBinding object, along with its other attributes, normally has an access URI and a specification link. The specification link provides the linkage between a service binding and a technical specification that describes how to use the service through the service binding. A specification link has the following attributes:

You can use the Service.getProvidingOrganization method to retrieve the organization that provides a service, and you can use the ServiceBinding.getService method to retrieve the service for a service binding.

The following code fragment retrieves the services for the organization org. Then it retrieves the service bindings for each service and, for each service binding, its access URI and specification links.

Collection services = org.getServices();
Iterator svcIter = services.iterator();
while (svcIter.hasNext()) {
    Service svc = (Service) svcIter.next();
    System.out.println(" Service name: " + getName(svc));
    System.out.println(" Service description: " +
        getDescription(svc));

    Collection serviceBindings = svc.getServiceBindings();
    Iterator sbIter = serviceBindings.iterator();
    while (sbIter.hasNext()) {
        ServiceBinding sb = (ServiceBinding) sbIter.next();
        System.out.println("  Binding name: " +
            getName(sb));
        System.out.println("  Binding description: " +
            getDescription(sb));
        System.out.println("  Access URI: " +
            sb.getAccessURI());

        Collection specLinks = sb.getSpecificationLinks();
        Iterator slIter = specLinks.iterator();
        while (slIter.hasNext()) {
            SpecificationLink sl =
                 (SpecificationLink) slIter.next();
            RegistryObject ro = sl.getSpecificationObject();
            System.out.println("Specification link " +
                "object of type " + ro.getObjectType());
            System.out.println("Usage description: " +
                sl.getUsageDescription().getValue());
            Collection ups = sl.getUsageParameters();
            Iterator upIter = ups.iterator();
            while (upIter.hasNext()) {
                String up = (String) upIter.next();
                System.out.println("Usage parameter: " +
                     up);
             }
        }
    }
}

The example Retrieving Organization Attributes: Example also displays the services and service bindings for the organizations it finds.

Services often exist independent of an organization. You can search for services directly using the BusinessQueryManagerImpl.findObjects method.

Retrieving an Organization Hierarchy

JAXR allows you to group organizations into families. One organization can have other organizations as its children. The child organizations can also have children. Therefore, any given organization can have a parent, children, and descendants.

The Organization.getParentOrganization method retrieves an organization’s parent. In the following fragment, chorg is a child organization.

Organization porg = chorg.getParentOrganization();

The Organization.getChildOrganizations method retrieves a Collection of the organization’s children. In the following fragment, org is a parent organization.

Collection children = org.getChildOrganizations();

The Organization.getDescendantOrganizations method retrieves multiple generations of descendants, while the Organization.getRootOrganization method retrieves the parentless ancestor of any descendant.

For an example of retrieving an organization hierarchy, see Creating and Retrieving an Organization Hierarchy: Examples.

Retrieving the Audit Trail of an Object

Whenever an object is published to the Registry, and whenever it is modified in any way, the JAXR provider creates another object, called an AuditableEvent. The JAXR provider adds the AuditableEvent object to the audit trail for the published object. The audit trail contains a list of all the events for that object. To retrieve the audit trail, call RegistryObject.getAuditTrail. You can also retrieve the individual events in the audit trail and find out their event types. JAXR supports the event types listed in Retrieving the Audit Trail of an Object.

Table 3–4 AuditableEvent Types

Event Type 

Description 

EVENT_TYPE_CREATED

Object was created and was published to the registry. 

EVENT_TYPE_DELETED

Object was deleted using one of the LifeCycleManager or BusinessLifeCycleManager deletion methods.

EVENT_TYPE_DEPRECATED

Object was deprecated using the LifeCycleManager.deprecateObjects method.

EVENT_TYPE_UNDEPRECATED

Object was undeprecated using the LifeCycleManager.unDeprecateObjects method.

EVENT_TYPE_VERSIONED

A new version of the object was created. This event typically happens when any of the object’s attributes changes. 

EVENT_TYPE_UPDATED

Object was updated. 

EVENT_TYPE_APPROVED

Object was approved using the LifeCycleManagerImpl.approveObjects method (implementation-specific).

EVENT_TYPE_DOWNLOADED

Object was downloaded (implementation-specific). 

EVENT_TYPE_RELOCATED

Object was relocated (implementation-specific). 

The following code fragment retrieves the audit trail for a registry object, displaying the type and timestamp of each event:

Collection events = obj.getAuditTrail();
String objName = obj.getName().getValue();
Iterator eventIter = events.iterator();
while (eventIter.hasNext()) {
    AuditableEventImpl ae = (AuditableEventImpl) eventIter.next();
    int eType = ae.getEventType();
    if (eType == AuditableEvent.EVENT_TYPE_CREATED) {
        System.out.print(objName + " created ");
    } else if (eType == AuditableEvent.EVENT_TYPE_DELETED) {
        System.out.print(objName + " deleted ");
    } else if (eType == AuditableEvent.EVENT_TYPE_DEPRECATED) {
        System.out.print(objName + " deprecated ");
    } else if (eType == AuditableEvent.EVENT_TYPE_UNDEPRECATED) {
        System.out.print(objName + " undeprecated ");
    } else if (eType == AuditableEvent.EVENT_TYPE_UPDATED) {
        System.out.print(objName + " updated ");
    } else if (eType == AuditableEvent.EVENT_TYPE_VERSIONED) {
        System.out.print(objName + " versioned ");
    } else if (eType == AuditableEventImpl.EVENT_TYPE_APPROVED) {
        System.out.print(objName + " approved ");
    } else if (eType == AuditableEventImpl.EVENT_TYPE_DOWNLOADED) {
        System.out.print(objName + " downloaded ");
    } else if (eType == AuditableEventImpl.EVENT_TYPE_RELOCATED) {
        System.out.print(objName + " relocated ");
    } else {
        System.out.print("Unknown event for " + objName + " ");
    }System.out.println(ae.getTimestamp().toString());
}

Some of the examples have a showAuditTrail method that uses code similar to this. See, for example, JAXRSearchByName.java in the directory <INSTALL>/registry/samples/search-name/src.

See Changing the State of Objects in the Registry for information on how to change the state of registry objects.

Retrieving the Version of an Object

If you modify the attributes of a registry object, the Registry creates a new version of the object. For details on how versioning happens, see Changing the State of Objects in the Registry. When you first create an object, the object has a version of 1.1.

To retrieve the version of an object, use the implementation-specific getVersionInfo method for a registry object, which returns a VersionInfoType object. The method has the following signature:

public VersionInfoType getVersionInfo()
    throws JAXRException

For example, to retrieve the version number for the organization org, cast org to a RegistryObjectImpl when you call the method. Then call the VersionInfoType.getVersionName method, which returns a String.

import org.oasis.ebxml.registry.bindings.rim.VersionInfoType;
...
VersionInfoType vInfo =
     ((RegistryObjectImpl)org).getVersionInfo();
if (vInfo != null) {
    System.out.println("Org version: " +
        vInfo.getVersionName());
}

Some of the examples use code similar to this. See, for example, JAXRSearchByName.java in the directory <INSTALL>/registry/samples/search-name/src.

Using Declarative Queries

Instead of the BusinessQueryManager interface, you can use the DeclarativeQueryManager interface to create and execute queries to the Registry. If you are familiar with SQL, you might prefer to use declarative queries. The DeclarativeQueryManager interface depends on another interface, Query.

The DeclarativeQueryManager interface has two methods, createQuery and executeQuery. The createQuery method takes two arguments, a query type and a string that contains the query. The following code fragment creates an SQL query that asks for a list of all Service objects in the Registry. Here, rs is a RegistryService object.

DeclarativeQueryManager qm = rs.getDeclarativeQueryManager();
String qString = "select s.* from Service s";
Query query = qm.createQuery(Query.QUERY_TYPE_SQL, qString);

After you create the query, you execute it as follows:

BulkResponse response = qm.executeQuery(query);
Collection objects = response.getCollection();

You then extract the objects from the response just as you do with ordinary queries.

For more information on SQL query syntax and for examples, see Chapter 6, “Query Management Protocols,” of the ebRS 3.0 specification, especially Section 6.6.

Using Declarative Queries: Example

For examples of the use of declarative queries, see JAXRQueryDeclarative.java and JAXRGetAllSchemes.java in the directory <INSTALL>/registry/samples/query-declarative/src. Both examples create and execute a SQL query. The query strings are defined in the JAXRExamples.properties file.

The SQL query string for JAXRQueryDeclarative is as follows (all on one line):


SELECT ro.* from RegistryObject ro, Name nm, Description d 
WHERE upper(nm.value) LIKE upper(’%free%’) AND upper(d.value) 
LIKE upper(’%free%’) AND (ro.id = nm.parent AND ro.id = d.parent)

This query finds all objects that have the string "free" in both the name and the description attributes.

The SQL query string for JAXRGetAllSchemes is as follows:


SELECT * FROM ClassScheme s order by s.id

This query finds all the classification schemes in the Registry.

ProcedureTo Run the JAXRQueryDeclarative Example

Steps
  1. Go to the directory <INSTALL>/registry/samples/query-declarative.

  2. To run the JAXRQueryDeclarative example, type the following command:


    asant get-free
    
  3. To run the JAXRGetAllSchemes example, type the following command:


    asant get-schemes
    

Using Iterative Queries

If you expect a declarative query to return a very large result set, you can use the implementation-specific iterative query feature. The DeclarativeQueryManagerImpl.executeQuery method can take an argument that specifies a set of parameters. This method has the following signature:

public BulkResponse executeQuery(Query query,
        java.util.Map queryParams,
        IterativeQueryParams iterativeParams)
    throws JAXRException

You can specify parameters that cause each query to request a different subset of results within the result set. Instead of making one query return the entire result set, you can make each individual query return a manageable set of results.

Suppose you have a query string that you expect to return up to 100 results. You can create a set of parameters that causes the query to return 10 results at a time. First, you create an instance of the class IterativeQueryParams, which is defined in the package org.freebxml.omar.common. The two fields of the class are startIndex, the starting index of the array, and maxResults, the maximum number of results to return. You specify the initial values for these fields in the constructor.

int maxResults = 10;
int startIndex = 0;
IterativeQueryParams iterativeQueryParams =
     new IterativeQueryParams(startIndex, maxResults);

Execute the queries within a for loop that terminates with the highest number of expected results and that advances by the maxResults value for the individual queries. Increment the startIndex field at each loop iteration.

for (int i = 0; i < 100; i += maxResults) {
    // Execute query with iterative query params
    Query query = dqm.createQuery(Query.QUERY_TYPE_SQL,
        queryStr);
     iterativeQueryParams.startIndex = i;
    BulkResponse br = dqm.executeQuery(query, null,
        iterativeQueryParams);
    Collection objects = br.getCollection();
    // retrieve individual objects ...
}

The Registry is not required to maintain transactional consistency or state between iterations of a query. New objects might be added to the complete result set between iterations, or existing objects might be removed from the result set. Therefore, you might notice that a result set element is skipped or duplicated between iterations.

Using Iterative Queries: Example

For an example of the use of an iterative query, see JAXRQueryIterative.java in the directory <INSTALL>/registry/samples/query-iterative/src. This program finds all registry objects whose names match a given string and then iterates through the first 100 of them.

ProcedureTo Run the JAXRQueryIterative Example

Steps
  1. Go to the directory <INSTALL>/registry/samples/query-iterative.

  2. Type the following command, specifying a string value:


    asant run -Dname=string
    

Invoking Stored Queries

The implementation-specific AdhocQueryImpl class, which extends RegistryObjectImpl, allows you to invoke queries that are stored in the Registry. The Registry has several default AdhocQueryImpl objects that you can invoke. The most useful are named FindAllMyObjects and GetCallersUser:

The simplest way to find a stored query is to look the query up by its unique identifier. The GetCallersUser query has a canonical constant defined for it (see Constant for Stored Query). You can use the string value of the unique identifier to locate queries that do not have canonical constants.

String queryId = 
    CanonicalConstants.CANONICAL_QUERY_GetCallersUser;
AdhocQueryImpl aq = 
    (AdhocQueryImpl) bqm.getRegistryObject(queryId);

Then find the query string associated with the AdhocQuery and use the string to create and execute a query, this time by using DeclarativeQueryManager methods.

if (aq != null) {
        int qType = aq.getType();
    String qString = aq.toString();
    Query query = dqm.createQuery(qType, qString);

    BulkResponse br = dqm.executeQuery(query);
    Collection objects = br.getCollection();
    ...

Invoking Stored Queries: Example

For an example of the use of a stored query, see JAXRQueryStored.java in the directory <INSTALL>/registry/samples/query-stored/src. This example authenticates the user, so it returns the user’s registry login name.

ProcedureTo Run the JAXRQueryStoredExample

Steps
  1. Go to the directory <INSTALL>/registry/samples/query-stored.

  2. Type the following command:


    asant run
    

Querying a Registry Federation

If the registry you are querying is part of one or more registry federations (see About Registries and Repositories), you can perform declarative queries on all registries in all federations of which your registry is a member, or on all the registries in one federation.

To perform a query on all registries in all federations of which your registry is a member, call the implementation-specific setFederated method on a QueryImpl object. The method has the following signature:

public void setFederated(boolean federated)
    throws JAXRException

You call the method as follows:

QueryImpl query = (QueryImpl)
    dqm.createQuery(Query.QUERY_TYPE_SQL, qString);
query.setFederated(true);

If you know that your registry is a member of only one federation, this method is the only one you need to call before you execute the query.

To limit your query to the registries in one federation, you need to call an additional implementation-specific method, setFederation. This method takes as its argument the unique identifier of the federation you want to query:

public void setFederation(java.lang.String federationId)
    throws JAXRException

Therefore, before you can call this method, you must obtain the unique identifier value. To do so, first call BusinessQueryManagerImpl.findObjects to locate the federation by name. In this code, you would substitute the actual name of the federation for the string "NameOfFederation".

Collection namePatterns = new ArrayList();
namePatterns.add("NameOfFederation");

// Find objects with name NameOfFederation
BulkResponse response =
    bqm.findObjects("Federation", null, namePatterns,
         null, null, null, null);

Then, iterate through the collection (which should have only one member) and retrieve the key value:

String fedId = federation.getKey().getId();

Finally, create the query, call setFederated and setFederation, and execute the query:

QueryImpl query = (QueryImpl)
    dqm.createQuery(Query.QUERY_TYPE_SQL, qString);
query.setFederated(true);
query.setFederation(fedId);
response = dqm.executeQuery(query);

Using Federated Queries: Example

For an example of the use of a federated query, see JAXRQueryFederation.java in the directory <INSTALL>/registry/samples/query-federation/src. This example performs two queries, a declarative query and a stored query, on every federation it finds (the database provided with the Registry contains only one).

The declarative query is the query that is performed in Using Declarative Queries: Example. The stored query is the FindAllMyObjects query. Because this example does not authenticate the user, the user that makes the query is RegistryGuest. The user RegistryGuest owns only one object, itself. Therefore, the FindAllMyObjects query returns only one result, the user RegistryGuest.

ProcedureTo Run the JAXRQueryFederationExample

Steps
  1. Go to the directory <INSTALL>/registry/samples/query-federation.

  2. Type the following command:


    asant run