Querying a Registry

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

Basic Query Methods

The simplest way for a client to use a registry is to query it for information about the objects and data in it. The QueryManager, BusinessQueryManager, and RegistryObject interfaces support a number of finder and getter methods that allow clients to search for data using the JAXR information model. Many of the finder methods return a BulkResponse (a collection of objects) that meets a set of criteria 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. While a UDDI registry supports a specific hierarchy of objects (organizations, which contain users, services, and service bindings), 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 the 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 8-2 lists the main interfaces supported by the JAXR information model. All these interfaces extend the RegistryObject interface.

Table 8-2 JAXR RegistryObject Subinterfaces 
Object Type
Description
Association
Defines a relationship between two objects. Getter/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 using a ClassificationScheme. Getter method: RegistryObject.getClassifications.
ClassificationScheme
Represents a taxonomy used to classify objects. An internal ClassificationScheme is one in which all taxonomy elements (concepts) are defined in the registry. An external ClassificationScheme is one in which the values are not defined in the registry but are represented using an ExternalIdentifier. 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 a value for the content of an external ClassificationScheme. Getter method: RegistryObject.getExternalIdentifiers.
ExternalLink
Provides a URI for content that may reside outside the registry. Getter method: RegistryObject.getExternalLinks.
ExtrinsicObject
Provides metadata that describes submitted content whose type is not intrinsically known to the registry and therefore must be described by means of additional attributes (such as mime type). No specific getter/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/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/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 one of its technical specifications that describes how to use the service 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 8-3 lists the other interfaces supported by the JAXR information model. These interfaces provide attributes for the main registry objects. They do not themselves extend the RegistryObject interface.

Table 8-3 JAXR Object Types Used as Attributes 
Object Type
Description
EmailAddress
Represents an email address. A User may have an EmailAddress. Getter method: User.getEmailAddresses.
InternationalString
Represents a String that has been 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
Represents a unique key that identifies a RegistryObject. 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 may 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 may have one or more TelephoneNumber objects. Getter methods: Organization.getTelephoneNumbers, User.getTelephoneNumbers.

Finding Objects by Name

To search for objects by name, you normally use a combination of find qualifiers (which affect sorting and pattern matching) and name patterns (which 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. Its 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 

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

For example, the following code fragment finds all the organizations in the Registry whose names begin with a specified string, qString, 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(qString + "%");

// Find organizations with name that starts with qString
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 qString and sorts them 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("%" + qString + "%");

// Find objects with name that contains qString
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 the example <INSTALL>/registry/samples/query-name/src/JAXRQueryByName.java. To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-name.
  2. Type the following command, specifying a string value:
  3. ant run -Dname=string

The program performs a case-insensitive search, returning all objects whose names contain the specified string. It 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 will find all services in the Registry and sort 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 the example <INSTALL>/registry/samples/query-object-type/src/JAXRQueryByObjectType.java. To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-object-type.
  2. Type the following command, specifying a string value:
  3. ant 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:

ant run -Dtype=federation 

Finding Objects by Classification

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

To do this, you first find the classification scheme and then 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 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 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 query
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 (called ClassificationNodes 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 8-4 lists and describes these canonical classification schemes.

Table 8-4 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 bythe 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 wish to 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.

For a sample program that displays all the canonical classification schemes and their concepts, see <INSTALL>/registry/samples/classification-schemes/src/JAXRGetCanonicalSchemes.java. To run this example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/classification-schemes.
  2. Type the following command:
  3. ant get-schemes

Finding Objects by Classification: Examples

For examples of finding objects by classification, see the two examples in <INSTALL>/registry/samples/query-classification/src: JAXRQueryByClassification.java and JAXRQueryByCountryClassification.java. The first example searches for objects that use the canonical classification scheme InvocationModel, while the other example searches for organizations that use a geographical classification. To run the examples, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-classification.
  2. Type either of the following commands:
  3. ant query-class
    ant query-geo

These examples are likely to produce results only after you have published an object that uses the specified classification (for example, the one in Adding Classifications: Example, causes the query-geo target to return an object).

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. The sample database included with the Registry does not have any external classification schemes, so you would have to create one named NASDAQ for this example to work. See Adding External Identifiers to Objects for details on how to do this.

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 query
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 the example <INSTALL>/registry/samples/query-external-identifier/src/JAXRQueryByExternalIdentifier.java, which searches for objects that use the NASDAQ classification scheme. To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-external-identifier.
  2. Type the following command:
  3. ant run

This example is not likely to produce results unless you first run the publish-object example described in Adding Classifications: Example.

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 also need to 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 the example <INSTALL>/registry/samples/query-external-link/src/JAXRQueryByExternalLink.java, 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.

To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-external-link.
  2. Type the following command:
  3. ant run

This example is not likely to produce results unless you first run the publish-object example described in Adding Classifications: Example.

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 and logical identifiers are the same. 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); 

Once 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 the example <INSTALL>/registry/samples/query-id/src/JAXRQueryById.java, which searches for objects that have a specified unique identifier. To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-id.
  2. Type the following command:
  3. 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 You Published

You can retrieve all objects that you published to the Registry, or you can narrow this search to retrieve only the objects you published that are of a particular object type. To retrieve all the objects you have published, use the no-argument version of the QueryManager.getRegistryObjects method. The name of this method is misleading, because it returns only objects 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 the two examples in <INSTALL>/registry/samples/get-objects/src: JAXRGetMyObjects.java and JAXRGetMyObjectsByType.java. 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. To run the examples, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/get-objects.
  2. Type the following command to retrieve all objects you published:
  3. ant get-obj

  4. Type the following command to retrieve all objects you have published of a specified type, where type_name is case-sensitive:
  5. ant get-obj-type -Dtype=type_name


Note: At this release, every user has the identity RegistryOperator. Because this user owns all the objects in the Registry, the get-obj target takes a long time to run, and the get-obj-type target may take a long time if the type_name is one with many objects (ClassificationNode, for example).


Retrieving Information About an Object

Once 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: its name, description, type, ID values, classifications, external identifiers, external links, and slots. For an organization, you can also retrieve the primary contact (a User object), postal address, telephone numbers, and the services that the organization offers. For a user, you can retrieve the name, email addresses, postal address, and telephone numbers. For a service, you can retrieve the service bindings.

For an 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 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. For example:

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 Finding Objects You Published: Examples.

Retrieving the Type of an Object

If you have queried the Registry without specifying a particular object type, you can retrieve the type of the objects returned by the query. 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. For example:

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 JAXRQueryByName.java in Finding Objects by Name: Example.

Retrieving the ID 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, 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 JAXRQueryOrg.java in Retrieving Organization Attributes: Example.

Retrieving the Classifications for an Object

Use the RegistryObject.getClassifications method to retrieve a Collection of the object's classifications. For each classification, you can retrieve its name, value, and the classification scheme to which it belongs. 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 this code. See, for example, JAXRQueryByName.java in Finding Objects by Name: Example.

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 this code. See, for example, JAXRQueryByName.java in Finding Objects by Name: Example.

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 this code. See, for example, JAXRQueryByName.java in Finding Objects by Name: Example.

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, JAXRQueryByName.java in Finding Objects by Name: Example.

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 available to all other objects. Every organization also has a User object as a primary contact, and it may 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(); 

Once you have 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 the example <INSTALL>/registry/samples/organizations/src/JAXRQueryOrg.java, which displays information about an organization whose name contains a specified string. To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/organizations.
  2. Type the following command:
  3. ant query-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, which provides the linkage between a service binding and a technical specification that describes how to use the service through the service binding.

In addition to these 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. A specification link in turn has a specification object (typically an ExtrinsicObject), usage description (an InternationalString object), and a Collection of usage parameters that are String values.

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.

Retrieving an Organization Hierarchy

JAXR allows you to group organizations into families. One organization can have other organizations as its children, and these can in turn have children. Therefore, any given organization may 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: Example.

Retrieving the Audit Trail of an Object

Whenever an object is published to the Registry, and whenever it is modified in any way, JAXR creates another object, called an AuditableEvent, and adds the event 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 8-5.

Table 8-5 AuditableEvent Types 
Event Type
Description
EVENT_TYPE_CREATED
Object was created and 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 this code. See, for example, JAXRQueryByName.java in Finding Objects by Name: Example.

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 this happens, see Changing the State of Objects in the Registry. When you first create an object, it has a version of 1.1.


Note: At this release, versioning of objects is disabled by default. All objects have a version of 1.1 even after modification. For details on how to turn versioning on, see the Release Notes.


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, JAXRQueryByName.java in Finding Objects by Name: Example.

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 may 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 containing 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.

Using Declarative Queries: Example

For an example of the use of declarative queries, see <INSTALL>/registry/samples/query-declarative/src/JAXRQueryDeclarative.java, which creates and executes a SQL query.

The SQL query string, which is defined in the JAXRExamples.properties file, looks like this (all on one line):

declarative.query=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.

To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-declarative.
  2. Type the following command:
  3. ant run

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 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. Thus it is possible for new objects to be added or existing objects to be removed from the complete result set between iterations. Therefore, you may 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 <INSTALL>/registry/samples/query-iterative/src/JAXRQueryIterative.java. This program finds all registry objects whose names match a given string and then iterates through the first 100 of them. To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-iterative.
  2. Type the following command, specifying a string value:
  3. ant 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:

To invoke a stored query, begin by using the BusinessQueryManagerImpl.findObjects method to locate the query. The following code searches for the GetCallersUser query.

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

// Find objects with name GetCallersUser
BulkResponse response =
  bqm.findObjects("AdhocQuery", null, namePatterns, 
    null, null, null, null);
Collection queries = response.getCollection(); 

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

// get the first (only) query and invoke it
Iterator qIter = queries.iterator();
if (!(qIter.hasNext())) {
  System.out.println("No objects found");
} else {
  AdhocQueryImpl aq = (AdhocQueryImpl) qIter.next();
  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 <INSTALL>/registry/samples/query-stored/src/JAXRQueryStored.java. This example returns the user's registry login name. To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-stored.
  2. Type the following command:
  3. ant 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, you 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 <INSTALL>/registry/samples/query-federation/src/JAXRQueryFederation.java. 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 same query performed in Using Declarative Queries: Example. The stored query is the GetCallersUser query, as in the previous example.

To run the example, follow these steps:

  1. Go to the directory <INSTALL>/registry/samples/query-federation.
  2. Type the following command:
  3. ant run