Service Registry 3.1 Developer's Guide

Chapter 3 Querying a Registry

This chapter describes the interfaces and methods that JAXR provides for querying a registry. The chapter 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 for unrestricted objects (see Getting Access to the Registry), 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. The table indicates objects specific to the Service Registry implementation of JAXR.

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 

AdhocQuery

(Implementation-specific) Represents an ad hoc query expressed in a query syntax. AdhocQuery objects are stored in the Registry and are used for discovery of registry objects. AdhocQuery objects are similar in purpose to the concept of stored procedures in relational databases.

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. 

Federation

(Implementation-specific) Represents an affiliated group of registries. 

No specific getter or finder methods. 

Notification

(Implementation-specific) Represents a notification from the registry regarding an event that matches a Subscription.

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.

Registry

(Implementation-specific) Represents a registry. 

No specific getter or finder methods. 

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.

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.

Subscription

(Implementation-specific) Defines a User's interest in certain types of AuditableEvent objects.

No specific getter or finder methods. 

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 unique URN, such as 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.

Slot

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

Getter methods: RegistryObject.getSlot, RegistryObject.getSlots.

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 identifier is the most efficient way to retrieve objects from the Registry.

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

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

  2. Type the following command:


    Ant-base/ant 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 objects = response.getCollection();

To locate a particular object, search by unique identifier if possible. Searching by name is less efficient and more likely to lead to errors, since names are not unique.

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

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

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


    Ant-base/ant 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 LifeCycleManager.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

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

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


    Ant-base/ant run -Dtype=type-name
    

    Specify the exact name of the type, not a wildcard, as in the following command line:


    Ant-base/ant run -Dtype=federation
    

    The JAXRSearchByObjectType program passes the object type as a string argument to QueryManager.findObjects in order to accept user input as simply as possible. However, developers should use the constants defined by the LifeCycleManager interface.

    The program performs a case-insensitive search, returning all objects whose type is type-nameand displaying their names, descriptions, and unique identifiers. At the end, it displays the number of objects found.

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.

String schemeId = "urn:freebxml:registry:demo:schemes:iso-ch:3166:1999";
ClassificationScheme cScheme =
     (ClassificationScheme) bqm.getRegistryObject(schemeId);

Classification classification =
     blcm.createClassification(cScheme, "United States", "US");
Collection classifications = new ArrayList();
classifications.add(classification);
// perform search
BulkResponse response = bqm.findObjects(LifeCycleManager.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

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

  2. Type the following command:


    Ant-base/ant 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.

The program JAXRSearchByCountryClassification.java uses the OR_ALL_KEYS field of FindQualifier to find organizations that use either of two geographical classifications. By default, finder methods look for objects that have all the specified classifications.

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 Adding Classifications: Example first.

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

  2. Type either of the following commands:


    Ant-base/ant search-class
    Ant-base/ant 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.

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.

String schemeId = "urn:devguide:samples:ClassificationScheme:NASDAQ";
ClassificationScheme cScheme = (ClassificationScheme)
    bqm.getRegistryObject(schemeId);

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.

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

  2. Type the following command:


    Ant-base/ant 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(LifeCycleManager.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. Make sure you have set these properties as described in To Edit the build.properties 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.

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

  2. Type the following command:


    Ant-base/ant run
    

Finding Objects You Published

You can retrieve all objects that you published to the Registry. Alternatively, you 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 constant argument that specifies the type:

BulkResponse response = bqm.getRegistryObjects(LifeCycleManager.SERVICE);

The QueryManager.getRegistryObjects method is case-sensitive.

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

Finding Objects You Published: Examples

For examples of finding objects you published, 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

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

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


    Ant-base/ant 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:


    Ant-base/ant get-obj-type -Dtype=type-name
    

    The JAXRGetMyObjectsByType program passes the object type as a string argument to QueryManager.getRegistryObjects in order to accept user input as simply as possible. However, developers should use the constants defined by the LifeCycleManager interface.

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. If versioning is turned on, the version number is updated whenever a change is made to one of the object’s attributes.


Note –

At this release of Service Registry, versioning is turned off by default. To enable versioning, an administrator must perform the task described in Enabling Versioning of Registry Objects in Service Registry 3.1 Administration Guide.)


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, its 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 or more postal addresses and one or more 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 (or names), 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

  1. Go to the directory INSTALL/registry-samples/organizations.

  2. Type the following command:


    Ant-base/ant 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. It can also have a specification link, which 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.

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());
        }
    }
}

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 also creates an AuditableEvent object when some objects are modified in certain ways. 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 Table 3–4.

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. If versioning is enabled, 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 from another registry (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 may create 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.


Note –

At this release, versioning of objects is disabled by default. To enable versioning of objects, an administrator must perform the task described in Enabling Versioning of Registry Objects in Service Registry 3.1 Administration Guide. The administrator commonly enables versioning for some object types but not for all.


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

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

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


    Ant-base/ant get-free
    
  3. To run the JAXRGetAllSchemes example, type the following command:


    Ant-base/ant 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

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

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


    Ant-base/ant run -Dname=string
    

Using Stored Queries

It is possible to invoke queries that are stored in the Registry. A number of predefined queries are already stored in the Registry as AdhocQuery objects. To find them, search for objects of that type. Most of these queries are provided in the Web Console. See Chapter 2, Searching the Registry, in Service Registry 3.1 User’s Guide for information on how to invoke these queries through the Web Console.

To invoke stored queries through JAXR, you need to know the following:

For example, suppose you wanted to invoke the stored query named Basic Query to search by object type for all organizations in the Registry. If you look at this query in the Web Console, you can see that it takes a parameter named $objectTypePath. This means that you specify the classification scheme node as a path structure instead of specifying the concept for the object type directly. The following code first retrieves the constant for the query identifier, then specifies the object type path. The actual String value of the object type path is /urn:oasis:names:tc:ebxml-regrep:classificationScheme:ObjectType/RegistryObject/Organization.

String queryId = 
    CanonicalConstants.CANONICAL_QUERY_BasicQuery;
String objectType = 
    CanonicalConstants.CANONICAL_CLASSIFICATION_SCHEME_ID_ObjectType;
String objectTypePath = 
    "/" + objectType + "/RegistryObject/Organization";

Once you have the values for the query identifier and the parameters, you create a HashMap to pass these values. First put the parameters in the HashMap, and finally the query identifier, using the constant CANONICAL_SLOT_QUERY_ID to specify the parameter name. Then you call an implementation-specific form of the DeclarativeQueryManager.createQuery method to create the query. Finally, you call an implementation-specific form of the DeclarativeQueryManager.executeQuery method to execute the parameterized query.

Map parameters = new HashMap();
parameters.put("$objectTypePath", objectTypePath);
parameters.put(CanonicalConstants.CANONICAL_SLOT_QUERY_ID, queryId);
Query query = dqm.createQuery(Query.QUERY_TYPE_SQL);

BulkResponse br = dqm.executeQuery(query, parameters);

The signatures of the implementation-specific forms of the createQuery and executeQuery methods are as follows:

public Query createQuery(int queryType)
    throws InvalidRequestException, JAXRException

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

Using 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 returns all organizations stored in the Registry.

ProcedureTo Run the JAXRQueryStored Example

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

  2. Type the following command:


    Ant-base/ant run
    

Using Federated Queries

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. Normally, this value is well-known.

Next, 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). Because the federation stored in the Registry database does not have a well-known identifier value, the example uses findObjects to locate the federation.

The declarative query is the query that is performed in Using Declarative Queries: Example. The stored query is the FindAllMyObjects query.

Because the federation in the Registry database has no members, this example cannot perform the queries.

ProcedureTo Run the JAXRQueryFederationExample

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

  2. Type the following command:


    Ant-base/ant run