Registration and Discovery of Web Services Using JAXR with XML Registries such as UDDI and ebXML

   
By Qusay H. Mahmoud, June 2002  

Many data formats are being used in the enterprise world that make it difficult for businesses to collaborate with one another at the application level. Web services enable interoperability through a set of XML-based open standards. Businesses can describe their Web services on the Internet using an XML-based language, such as the Web Services Description Language (WSDL), or simple plain text, and list them in an XML-based registry such as Universal Description, Discovery, and Integration (UDDI), or the electronic business XML (or ebXML) Registry. But since the formats of these XML-based registries are different, developers must study each of them carefully and in detail. Luckily, however, Sun has pioneered the Java TM API for XML Registries (JAXR), which can be used to access any of the most widely adopted XML-based registries. With JAXR, you don't need to worry about the differences between UDDI and the ebXML Registry.

After reading this article, you'll know how to use JAXR to publish your Web services in XML-based registries and query the registries. This article:

  • Gives a brief overview of XML-based registries
  • Shows how to get started with registries
  • Discusses JAXR architecture and APIs
  • Describes the mapping of UDDI and the ebXML Registry to JAXR
  • Explains the JAXR programming model
  • Shows how to publish Web services and query registries

XML Registries



A registry is a shared resource, often available in the form of a web-based service that facilitates dynamic business-to-business interactions. The registry is a key component in Web services architecture, since it allows organizations to publish, discover, and utilize Web services.

It's important to distinguish between a registry (such as UDDI or the ebXML Registry) and a directory (such as the Java Naming and Directory Interface (JNDI)). JNDI was designed with a different set of requirements and a simple information model. On the other hand, a registry provides capabilities that take advantage of emerging e-business and Web services standards. A registry requires an elaborate information model and rich metadata and query capabilities in order to support more complex queries and therefore make the search for Web services as accurate as possible.

As I have already mentioned, a variety of XML registries exist. The most popular ones are the Universal Description, Discovery, and Integration (UDDI) and the ebXML Registry. The core information model is defined in XML, which was chosen because it offers a platform-neutral view of data and allows hierarchical relationships to be described in a natural way.

Note: It's important to note that an XML registry doesn't imply the use of an XML database in the implementation. It merely means that XML standards play a significant role in the registry specifications. In other words, you don't need to learn how to use an XML database in order to use an XML registry.

Overview of UDDI



UDDI is an XML registry that provides standard mechanisms for businesses to describe and publish their services, discover other businesses that offer desired services, and integrate with them. Think of UDDI as:

  • Yellow Pages that allow businesses to register themselves and their services under different categories and classifications.
  • White Pages that contain business addresses and contact information.
  • Green Pages (which do not lend themselves to a phone book analogy) that contain technical information about services offered by business entities. They include enough technical details to invoke a given service.


The UDDI information model contains four core elements:

  • Business information: This is described using the businessEntity element, which represents a physical organization. It contains information (such as name, description, and contacts) about the organization. The businessEntity information includes support for Yellow Pages taxonomies so that searches can be performed to locate organizations who service a particular industry or product category.
  • Service information: This is described using the businessService element, which groups together related services offered by an organization.
  • Binding information: This is described using the bindingTemplate element, for information that is relevant for application programs that need to connect to and then communicate with a remote Web service. In other words, it provides instructions on how to invoke a remote Web service. The instructions may either be in the form of an interface definition language such as WSDL, or a text-based document.
  • Information about specifications for services: This is described using the tModel element, which is an abstract representation of the technical specification. A tModel has a name, publishing organization, and URL pointers to the actual specifications themselves.

UDDI APIs



The UDDI APIs are divided into two logical parts: the Inquiry API and the Publish API. They describe the Simple Object Access Protocol (SOAP) messages that are used to publish and discover an entry in the registry.

The Publish API

The Publish API provides methods for publishing and updating information contained in a UDDI registry. A business should select a UDDI registry operator site to host its information. Invoking methods in the Publish API requires authorization and is usually done through HTTPS. The API consists of methods for saving information: save_business, save_service, save_binding, and save_tModel. These methods take authToken (which is optional if operators provide another mechanism of authentication such as username and password) and one or more businessEntity elements.

This API also contains methods for deleting information: delete_business, delete_service, delete_binding, and delete_tModel. These methods take the uuid key (which was generated by the registry when information was first published) as an input parameter.

The Inquiry API

The Inquiry API provides methods for querying the registry. Some of these methods are: find_service, get_businessDetail, get_serviceDetail, get_bindingDetail, and get_tModelDetail.

Registration Process



Registering your organization is easy; there are several UDDI registry operators that offer free registration services. To get started, select one of the following UDDI Business Registry operators (running a UDDI registry, version 2) or simply follow this link to select an operator through uddi.org.



It's worth noting that the Java Web Services Developer Pack (Java WSDP) comes with a UDDI-compliant registry, version 2 implementation.

In this article, I have used the IBM UDDI Business Registry Version 2.0 as shown in Figure 1.

Figure 1: IBM UDDI Business Registry Version 2.0

If you plan to run the examples in this article, be sure to register your organization and memorize your login name and password. Once you register, you will receive a login name and password that you must use for publishing and updating your information. Authorization, however, is not required for performing queries.

Overview of ebXML



ebXML is a business-to-business XML framework developed by the ebXML initiative, which is a joint project of the United Nations Centre for Trade Facilitation and Electronic Business (UN/CEFACT) and the Organization for the Advancement of Structured Information Standards (OASIS). The ebXML version 1 specifications were completed in May 2001, and the ebXML Registry version 2 is an approved OASIS standard. The ebXML membership includes representatives from over 2000 businesses, institutions, governments, standards bodies, and individuals from around the globe.

An ebXML Registry allows organizations to advertise and discover information about businesses. It stores Collaboration-Protocol Profile (CPP) and Collaboration-Protocol Agreement (CPA) and other information relevant to business collaboration. The CPP is an XML document that contains information about a business and the way it exchanges information with other businesses. The CPA is also an XML document that describes the specific capabilities that two businesses have agreed to use in a business collaboration.

Unlike the UDDI registry, which is a registry of metadata only, the ebXML Registry is both a metadata registry as well as a repository that can hold arbitrary content. To illustrate this, consider how the two registries publish a Web service. Only the metadata about a Web service is published to UDDI. The actual Web service description (that is, the WSDL document) cannot reside in UDDI and must reside in the service provider's web site. In contrast, a Web service description may be published in an ebXML Registry and repository to include all metadata as well as technical specifications and related artifacts. A common example is as follows: businesses register their profiles (CPPs) in an ebXML registry. When a business searches the registry and finds another business that it wants to collaborate with, it creates a technical agreement (CPA) using the CPP and sends the CPA to the other business. The two businesses collaborate according to the CPA.

The ebXML Registry offers many unique features that are valuable for e-business collaboration:

  • It can hold arbitrary content and not just metadata.
  • Its object-oriented information model provides consistent capabilities resulting in a simpler information model that is more easily extended.
  • In addition to predefined associations, you can invent and maintain your own associations.
  • Data validation features improve integrity of registry data. For example, URLs are checked before being stored in the registry.
  • Packaging (or grouping) of related registry objects.
  • Attribute extensibility of registry objects. This allows the registry to be customized for very specific purposes.
  • Registry interface described in abstract with multiple concrete bindings including WSDL and ebXML Messaging.
  • Supports flexible communication styles, including both synchronous and asynchronous communication.
  • Supports life cycle management (versions, status, stability, expiration) of registry entries.
  • Provides ad hoc query support across all metadata.
  • Supports the ability to find services without specifying organization.
  • Allows auditing of all important events during the life cycle of a registry object.
  • Provides a security infomodel with digital-signature-based authentication, integrity validation and authorization.


For an overview of the ebXML specifications, please see Overview of ebXML Specifications. For detailed information on ebXML, please see http://www.ebxml.org.

JAXR



The Java API for XML Registries (JAXR) API is an abstract uniform Java API for accessing different kinds of XML registries. It provides you with a single set of APIs to access a variety of XML registries, including UDDI and the ebXML Registry. You don't need to worry about the nitty-gritty details of each registry's information model.

This abstraction is consistent with the Java philosophy of Write once, Run Anywhere. It enables value-added capabilities beyond what the underlying registries can do. As an example, a non-JAXR UDDI client can't do taxonomy browsing and taxonomy-aware smart queries -- which are available to a JAXR client for UDDI.

The JAXR information model is based on the ebXML Registry Information Model (RIM), with enhancements to support UDDI. The ebXML RIM is more generic and extensible than the UDDI XML data structures, so the ebXML RIM can be extended to satisfy the needs of UDDI.

The JAXR Reference Implementation, which is part of the Java Web Services Developer Pack (Java WSDP) implements the level 0 capability profile defined by the JAXR specification (JSR 93), which allows access to both UDDI and ebXML registries at a basic level. Note, however, that the current release of the JAXR RI supports access to UDDI version 2 registries. Several UDDI version 2 registries are already available as discussed above. Some ebXML registries are under development, such as the open source OASIS ebXML Registry Reference Implementation Project (ebxmlrr) which will be available soon. The ebxmlrr Registry Browser is already available, however. If you have the Java Web Start (which comes with J2SE 1.4), you can access the ebxmlrr Registry Browser through http://ebxmlrr.sourceforge.net/registryBrowser/registryBrowser.jnlp. Once loaded (it may take a few minutes) you will see something similar to Figure 2.

Figure 2: ebxmlrr Registry Browser

 

JAXR Architecture



The high-level architecture of JAXR is shown in Figure 3.

Figure 3: High-level architecture of JAXR

The different layers of the JAXR architecture are:

  • JAXR Client: An application that uses the JAXR API to access a registry via a JAXR provider.
  • JAXR Provider: An implementation of the JAXR API. The JAXR provider is pluggable in the sense that it implements the JAXR API independent of any specific registry, which provides a single abstraction for multiple registry-specific JAXR providers. It also exposes capability-specific interfaces for life cycle and query management.
  • Registry Providers: Implementations of various registry specifications such as UDDI and the ebXML Registry.
  • Registries: These are the UDDI and ebXML actual registry data.


JAXR provides the abstraction through the JAXR provider, which implements two packages:

  • javax.xml.registry: Consists of interfaces and classes that define the registry access interface independent of any specific registry. Other interfaces in this package include:

    • Connection: The client must create a connection with the JAXR provider in order to use a registry. It represents a client session with a registry provider.
    • RegistryService: A client obtains a RegistryService object from its connection. It lets the client obtain other interfaces to access the registry.
    • BusinessQueryManager: Allows the client to search the registry for information.
    • BusinessLifeCycleManager: Allows the client to modify the information in a registry, either by updating it or deleting it.
    • DeclarativeQueryManager: Allows the client to use SQL syntax for queries. (Note: the current release of JAXR RI does not implement this interface).
  • javax.xml.registry.infomodel: Consists of the interfaces that define the information model for JAXR. It defines the type of objects that reside in the registry and the relationships between them. The basic interface is the RegistryObject, and its subinterfaces Organization, Service, and ServiceBinding.

Mapping of UDDI Information Model to JAXR



This section describes the mapping between the JAXR information model and the UDDI XML data structures defined in UDDI version 2. For more detailed information on the mapping, see the JAXR Specification (JSR 93).

Note: UDDI methods that are not needed or supported in JAXR are not listed.


Mapping of Interfaces

The mapping of high-level UDDI data structures to JAXR interfaces is shown in Table 1. See the JAXR Specification for information on mapping attributes.

Table 1: Mapping of high-level UDDI data structures to JAXR interfaces
UDDI Data Structure JAXR Interface
businessEntity Organization
businessService Service
bindingTemplate ServiceBinding
tModel (fingerprint) Concept
tModel (namespace) ClassificationScheme
disCoveryURL ExternalLink
contact User
identifierBag Collection of ExternalIdentifier instances
categoryBag Collection of Classification instances
address PostalAddress
overviewDoc ExternalLink
keyedReference (in categoryBag) Classification
keyedReference (in identifierBag ExternalIdentifier




Mapping of UDDI Publisher API to JAXR

The mapping from UDDI Publisher API methods to JAXR methods is shown in Table 2.

Table 2: Mapping of UDDI Publisher API to JAXR
UDDI Method JAXR BusinessLifeCycleManager
add_publisherAssertions saveAssociations
delete_binding deleteServiceBindings
delete_business deleteOrganizations
delete_publisherAssertions deleteAssociations
delete_service deleteServices
delete_tModel deleteClassificationsSchemes and deleteConcepts
get_assertionStatusReport findAssociations
get_publisherAssertions QueryManager.getRegistryObjects
get_registeredInfo QueryManager.getRegistryObjects
save_binding saveServiceBindings
save_business saveOrganizations
save_service saveServices
save_tModel saveClassificationsSchemes and saveConcepts
set_publisherAssertions saveAssociations




Mapping of UDDI Inquiry API to JAXR

The mapping from UDDI Inquiry API methods to JAXR methods is shown in Table 3.

Table 3: Mapping of UDDI Inquiry API to JAXR
UDDI Method JAXR BusinessQueryManager
find_binding findServiceBindings
find_business findOrganizations
find_related_business findAssociatedObjects
find_service findServices
find_tModel findConcepts and findClassificationSchemes


Mapping of ebXML Registry Information Model to JAXR



The mapping of the ebXML Registry Information Model (RIM) to the JAXR information model is shown in Table 4. Almost all mappings are direct because the JAXR information model is based on the ebXML RIM.

Table 4: Mapping of ebXML Registry to JAXR
ebXML JAXR
Association Assiciation
AuditableEvent AuditableEvent
Classification Classification
ClassificationNode Concept
EmailAddress EmailAddress
ExternalIdentifier ExternalIndentifier
ExtrinsicObject ExtrinsicObject
Organization Organization
RegistryPackage RegistryPackage
PersonName PersonName
PostalAddress PostalAddress
RegistryEntry RegistryEntry
RegistryObject RegistryObject
Service Service
ServiceBinding ServiceBinding
Slot Slot
SpecificationLink SpecificationLink
TelephoneNumber TelephoneNumber
User User
Versionable Versionable


The JAXR Programming Model



The development life cycle of a JAXR-based application requires the following steps:

  1. Establish connection to registry: To do this, you define connection configuration properties and then create a connection using ConnectionFactory. The following snippet of code shows how this can be done:
    // define configuration properties
    String publishURL = 
      "https://www-3.ibm.com/services/uddi/v2beta/protect/publishapi";
    String queryURL = 
      "http://www-3.ibm.com/services/uddi/v2beta/inquiryapi";
    Properties props = new Properties();
    props.setProperty("javax.xml.registry.lifeCycleManagerURL", 
      publishUrl);
    props.setProperty("javax.xml.registry.queryManagerURL",queryUrl);
    props.setProperty("javax.xml.registry.factoryClass", 
      "com.sun.xml.registry.uddi.ConnectionFactoryImpl");
    
    try {
      // Create the connection, passing it the 
      // configuration properties
      ConnectionFactory factory = 
        ConnectionFactory.newInstance();
      factory.setProperties(props);
      connection = factory.createConnection();
      System.out.println("Created connection to registry");
    } catch (Exception e) {
       e.printStackTrace();
       if (connection != null) {
         try {
           connection.close();
         } catch (JAXRException je) {}
       }
    }
    

    Note that different URLs are used for the publishing and discovery of services. When publishing new information or updating existing information, you need to provide a username and password, and HTTPS is used.

    Note: If you are accessing a registry that is outside a firewall, you must specify proxy host and port information as shown in the following snippet of code. If you are performing a query, you need to specify only the HTTP proxy host and port; if you are performing updates, you must specify the HTTPS proxy host and port.

    props.setProperty("javax.xml.registry.http.proxyHost", 
      "host.domain");
    props.setProperty("javax.xml.registry.http.proxyPort", 
      "proxyPortNumber");
    props.setProperty("javax.xml.registry.https.proxyHost", 
      "host.domain");
    props.setProperty("javax.xml.registry.https.proxyHost", 
      "proxyPortNumber");
    

  2. Perform query and/or update operations: Once a connection has been established, you can obtain a RegistryService interface, through which you can either perform a query operation (using the BusinessQueryManager or DeclarativeQueryManager) or an update operation (using the BusinessLifeCycleManager).
  3. Check output: A registry response to an update or query operation comes to the client in the form of a BulkResponse object, which contains a Collection of JAXRResponse objects that correspond to query result. If the operation failed, the BulkResponse allows you to catch JAXRException.
  4. Close the connection: This is done using the close method.


Example 1: Creating an organization and publishing it in the registry

This example shows how to create an organization and publish it in the IBM UDDI V2 Business Registry. The same thing can be done using the web-based interface as described earlier. This example (Code Sample 1), however, shows how to do this programmatically. Note that you need to have your username and password for that registry for this example to work. Instructions on how to run the examples are provided later. These examples are adapted from the Java WSDP Tutorial.

Code Sample 1: PublishORG.java

import javax.xml.registry.*; 
import javax.xml.registry.infomodel.*; 
import java.net.*;
import java.security.*;
import java.util.*;

/**
 * The PublishORG class consists of a main method, a
 * makeConnection method, and an executePublish method.  
 * It creates an organization and publishes it to a registry.
 * 
 * To run this program, use the command 
 * 
 *     ant run-publish-org
 */

public class PublishORG {
  Connection connection = null;

  public PublishORG() {
  }

  public static void main(String[] args) {
    String publishURL = 
      "https://www-3.ibm.com/services/uddi/v2beta/protect/publishapi";
    String queryURL = 
      "http://www-3.ibm.com/services/uddi/v2beta/inquiryapi";   
    // Provide your user name and password    
    String username = "YourUserName";
    String password = "YourPassword";

    PublishORG po = new PublishORG();
    po.makeConnection(publishURL, queryURL);
    po.executePublish(username, password);
  }
    
  /**
   * Establishes a connection to a registry.
   * @param publishUrl   the URL of the publish registry
   * @param queryUrl   the URL of the query registry
   */
  public void makeConnection(String publishUrl, 
    String queryUrl) {
    /*
     * Define connection configuration properties. 
     * To publish, you need both the query URL and the 
     * publish URL.
     */
     Properties props = new Properties();
     props.setProperty(
       "javax.xml.registry.lifeCycleManagerURL", publishUrl);
     props.setProperty(
       "javax.xml.registry.queryManagerURL",queryUrl);
     props.setProperty("javax.xml.registry.factoryClass", 
       "com.sun.xml.registry.uddi.ConnectionFactoryImpl");

     try {
       // Create the connection, passing it the 
       // configuration properties
       ConnectionFactory factory = ConnectionFactory.newInstance();
       factory.setProperties(props);
       connection = factory.createConnection();
       System.out.println("Created connection to registry");
     } catch (Exception e) {
        e.printStackTrace();
        if (connection != null) {
          try {
            connection.close();
          } catch (JAXRException je) {}
        }
     }
  }
    
  /**
   * Creates an organization, its classification, and its
   * services, and saves it to the registry.
   */
  public void executePublish(String username, String password) {
    RegistryService rs;
    BusinessLifeCycleManager blcm;
    BusinessQueryManager bqm;

    try {
      rs = connection.getRegistryService();
      blcm = rs.getBusinessLifeCycleManager();
      bqm = rs.getBusinessQueryManager();
      System.out.println("Got registry service, 
        query manager, and life cycle manager");

      // Get authorization from the registry
      PasswordAuthentication passwdAuth = new 
        PasswordAuthentication(username, password.toCharArray());
      Set credits = new HashSet();
      credits.add(passwdAuth);
      connection.setCredentials(credits);
      System.out.println("Established security credentials");

      // Create organization name and description
      // Replace this information with your organization information
      Organization org = blcm.createOrganization("javacourses.com");
      InternationalString s = 
        blcm.createInternationalString("Java training and 
          consulting services");
      org.setDescription(s);

      // Create primary contact, set name
      User primaryContact = blcm.createUser();
      PersonName pName = blcm.createPersonName("Qusay H. Mahmoud");
      primaryContact.setPersonName(pName);

      // Set primary contact phone number
      TelephoneNumber phoneNum = blcm.createTelephoneNumber();
      phoneNum.setNumber("(604) 285-2000");
      Collection phoneNums = new ArrayList();
      phoneNums.add(phoneNum);
      primaryContact.setTelephoneNumbers(phoneNums);

      // Set primary contact email address
      EmailAddress emailAddress = 
      blcm.createEmailAddress("qmahmoud@javacourses.com");
      Collection emailAddresses = new ArrayList();
      emailAddresses.add(emailAddress);
      primaryContact.setEmailAddresses(emailAddresses);

      // Set primary contact for organization
      org.setPrimaryContact(primaryContact);

      // Set classification scheme to NAICS
      ClassificationScheme cScheme = 
        bqm.findClassificationSchemeByName("ntis-gov:naics");

      // Create and add classification
      Classification classification = (Classification)
      blcm.createClassification(cScheme, 
        "Computer Training", "61142");  
      Collection classifications = new ArrayList();
      classifications.add(classification);
      org.addClassifications(classifications);

      // Create services and service
      Collection services = new ArrayList();
      Service service = 
        blcm.createService("Buy a Java Course");
      InternationalString is = 
          blcm.createInternationalString("This service 
            allows you to register for a Java course and 
              download its manuals.");
      service.setDescription(is);

      // Create service bindings
      Collection serviceBindings = new ArrayList();
      ServiceBinding binding = blcm.createServiceBinding();
      is = blcm.createInternationalString("Service Binding " 
        + "Access this services using the given URL.");
      binding.setDescription(is);
      binding.setAccessURI("http://javacourses.com/register");
      serviceBindings.add(binding);

      // Add service bindings to service
      service.addServiceBindings(serviceBindings);

      // Add service to services, then add services to organization
      services.add(service);
      org.addServices(services);

      // Add organization and submit to registry
      // Retrieve key if successful
      Collection orgs = new ArrayList();
      orgs.add(org);
      BulkResponse response = blcm.saveOrganizations(orgs);
      Collection exceptions = response.getException();
      if (exceptions == null) {
        System.out.println("Organization saved");
        Collection keys = response.getCollection();
        Iterator keyIter = keys.iterator();
        if (keyIter.hasNext()) {
          javax.xml.registry.infomodel.Key orgKey = 
            (javax.xml.registry.infomodel.Key) keyIter.next();
          String id = orgKey.getId();
          System.out.println("Organization key is " + id);
          org.setKey(orgKey);
        }
      } else {
         Iterator excIter = exceptions.iterator();
         Exception exception = null;
         while (excIter.hasNext()) {
           exception = (Exception) excIter.next();
           System.err.println("Exception on save: " + 
             exception.toString());
         }
      }
    } catch (Exception e) {
       e.printStackTrace();
       if (connection != null) {
         try {
           connection.close();
         } catch (JAXRException je) {
            System.err.println("Connection close failed");
         }
       }
    }
  }
}



In this example, I have published my business's information. Note that in addition to the basic contact information, I have also published a service and its service bindings. Also, I have classified my business according to the North American Industry Classification System (NAICS). In this scheme, businesses are classified based on the products and services they offer. For example, I have published my business as a "Computer Training" business using the code 61142. A list of all the codes is available at http://www.census.gov/epcd/naics/naicscod.txt.

When you run this example (instructions are provided later), you see an output similar to Figure 4. Note that a unique key identifier has been generated by the registry, which is used when you wish to update your information.

Figure 4: Output of PublishORG

Once you run the example successfully, it's easy to confirm that your organization information has been added to the registry. Simply log on to the registry you are using and check the information. My information is shown in Figure 5.

Figure 5: Information has been published successfully

Note: The Java WSDP comes with a registry browser that allows you to browse information from any registry. You can also publish services to registries. To start the browser, execute the command jaxr-browser from JWSDP_HOME\bin. Choose the registry you have used to publish your information and then enter a string to search for (no username and password are needed to perform a query on a registry). You see output similar to Figure 6.

Figure 6: The JAXR browser comes with Java WSDP

When you double-click on the information that was retrieved, you see the organization information output as shown in Figure 7.

Figure 7: Organization information displayed in the JAXR browser

You can also check the services and the service bindings published by the organization as shown in Figure 8 and 9, respectively.

Figure 8: Service information

Figure 9: Service binding information

Example 2: Performing a query

You have seen how to use registry browsers to browse the registry. This example shows how to perform queries programmatically. JAXR allows you to find organizations by name (name of organizations), classifications (such as NAICS), and WSDL classification. This example shows how to find organizations based on the NAICS classification scheme. The code is shown in Code Sample 2.

Code Sample 2 NaicsQuery.java

import javax.xml.registry.*; 
import javax.xml.registry.infomodel.*; 
import java.net.*;
import java.util.*;

/**
 * The NaicsQuery class consists of a main 
 * method, a makeConnection method, an 
 * executeQuery method. It 
 * searches a registry for information about 
 * organizations using
 * NAICS classification.
 * 
 * To run this application, use the command 
 * 
 *     ant run-naics-query
 */

public class NaicsQuery {

  Connection connection;

  // constructor
  public NaicsQuery() {
  }

  public static void main(String[] args) {
    String queryURL = 
      "http://www-3.ibm.com/services/uddi/v2beta/inquiryapi";

    if (args.length != 0) {
      System.out.println("Usage: ant run-naics-query");
      System.exit(1);
    }
        
    NaicsQuery nq = new NaicsQuery();
    nq.makeConnection(queryURL);    
    nq.executeQuery();
  }

  /**
   * Establishes a connection to a registry.
   * @param queryUrl    the URL of the query registry
   */
  public void makeConnection(String queryUrl) {
    /* 
     * Define connection configuration properties. 
     */
    Properties props = new Properties();
    props.setProperty(
      "javax.xml.registry.queryManagerURL", queryUrl);
    props.setProperty("javax.xml.registry.factoryClass", 
      "com.sun.xml.registry.uddi.ConnectionFactoryImpl");
    try {
      // Create the connection, passing it the 
      // configuration properties
      ConnectionFactory factory = 
        ConnectionFactory.newInstance();
      factory.setProperties(props);
      connection = factory.createConnection();
      System.out.println("Created connection to registry");
    } catch (Exception e) {
       e.printStackTrace();
       if (connection != null) {
         try {
           connection.close();
         } catch (JAXRException jaxre) {}
       }
    }
  }
    
  /**
   * Searches for organizations corresponding to NAICS
   * classification and displays information about them.
   */
  public void executeQuery() {
    RegistryService rs;
    BusinessQueryManager bqm;
    BusinessLifeCycleManager blcm;

    try {
      // Get registry service and managers
      rs = connection.getRegistryService();
      bqm = rs.getBusinessQueryManager();
      blcm = rs.getBusinessLifeCycleManager();
      System.out.println("Got registry service, 
        query manager, and life cycle manager");

      // Find using an NAICS classification
      // Set classification scheme to NAICS
      ClassificationScheme cScheme = 
        bqm.findClassificationSchemeByName(
          "ntis-gov:naics");
      // Create and add classification
      Classification classification = (Classification) 
        blcm.createClassification(cScheme, "Wired 
          Telecommunications Carriers", "51331");
      Collection classifications = new ArrayList();
      classifications.add(classification);
      BulkResponse response = bqm.findOrganizations(
        null, null, classifications, null, null, null);
      Collection orgs = response.getCollection(); 

      // Display information about the organizations found
      Iterator orgIter = orgs.iterator();
      while (orgIter.hasNext()) {
        Organization org = (Organization) orgIter.next();
        System.out.println("Organization Name: " + 
          org.getName().getValue());
        System.out.println("Organization Description: " +     
          org.getDescription().getValue());
        System.out.println("Organization Key ID: " + 
          org.getKey().getId());

       // Display more information such as primary contact
       // and service bindings

       // Print stars between organizations
        System.out.println("**************************"); 
      }
    } catch (Exception e) {
       e.printStackTrace();
    } finally  {
       // At end, close connection to registry
       if (connection != null) {
         try {
           connection.close();
         } catch (JAXRException jaxre) {}
       }
    }
  }
}

This sample query searches for organizations classified under the "Wired Telecommunications Carriers" with the NAICS code number "51331". When you run NaicsQuery, you see an output similar to Figure 10.

Figure 10: Output of NaicsQuery

This example displays the name of the organization, its description, and key identifier. If you'd like to display more information -- such as contacts and service bindings -- you can use the following snippet of code.

// Display primary contact information
User pc = org.getPrimaryContact();
if (pc != null) {
  PersonName pcName = pc.getPersonName();
  System.out.println(" Contact name: " + 
    pcName.getFullName());
  Collection phNums = pc.getTelephoneNumbers(null);
  Iterator phIter = phNums.iterator();
  while (phIter.hasNext()) {
    TelephoneNumber num = (TelephoneNumber) 
      phIter.next();
    System.out.println("  Phone number: " + 
      num.getNumber());
  }
  Collection eAddrs = pc.getEmailAddresses();
  Iterator eaIter = eAddrs.iterator();
  while (phIter.hasNext()) {
    System.out.println("  Email Address: " + 
      (EmailAddress) eaIter.next());
  }
}

// Display service and binding information
Collection services = org.getServices();
Iterator svcIter = services.iterator();
while (svcIter.hasNext()) {
  Service svc = (Service) svcIter.next();
  System.out.println(" Service name: " + 
    svc.getName().getValue());
  System.out.println(" Service description: " + 
    svc.getDescription().getValue());
  Collection serviceBindings = svc.getServiceBindings();
  Iterator sbIter = serviceBindings.iterator();
  while (sbIter.hasNext()) {
  ServiceBinding sb = (ServiceBinding) sbIter.next();
  System.out.println("  Binding " + "Description: " + 
    sb.getDescription().getValue());
  System.out.println("  Access URI: " + sb.getAccessURI());
}

Instructions for running PublishORG and NaicsQuery

To run the above code examples ( PublishORG and NaicsQuery), follow these steps. I assume you have both J2SE 1.4 and Java WSDP installed.

  1. Create a directory called jaxr-code.
  2. Copy and save PublishORG.java and NaicsQuery.java in jaxr-code.
  3. Copy and save the following ANT build file, build.xml, in jaxr-code.

    ANT build file: build.xml

    <project name="JAXR for UDDI and ebXML"
      default="build" basedir=".">
      <target name="init">
          <tstamp/>
      </target>
    
      <property name="build.home" value="build" />
    
      <path id="classpath">
        <fileset dir="${jwsdp.home}/common/lib">
          <include name="*.jar" />
        </fileset>
    
        <fileset dir="${jwsdp.home}/common/endorsed">
          <include name="*.jar" />
        </fileset>
      </path>
    
      <target name="prepare" depends="init"
       description="Create build directories.">
        <mkdir dir="${build.home}" />
    
      </target>
    
      <target name="build" depends="prepare" 
         description="Compile Java files.">
          <javac srcdir="." destdir="${build.home}">
            <include name="*.java" />
            <classpath refid="classpath"/>
          </javac>
    
      </target>
    
      <target name="run-naics-query" depends="build"
         description="Run NaicsQuery.">
        <java classname="NaicsQuery" fork="yes">
          <classpath refid="classpath" />
          <classpath path="${build.home}" />
        </java>
    
      </target>
    
      <target name="run-publish-org" depends="build"
         description="Run PublishOrg.">
        <java classname="PublishORG" fork="yes">
          <sysproperty key="useSOAP" value="false"/>
          <classpath refid="classpath" />
          <classpath path="${build.home}" />
    
        </java>
      </target>
    
      <target name="help">
         <echo message="Targets for the JAXR examples:" />
         <echo message="  run-publish-org" />
         <echo message="  run-naics-query" />
    
      </target>
    
    </project>
    

  4. To compile, use the command: ant build
  5. To run PublishORG, use the command: ant run-publish-org.
  6. To run NaicsQuery, use the command: ant run-naics-query.

    Note: The above instructions use the ANT build tool. If you don't have it installed, don't worry; Java WSDP comes with the ANT build tool. Just make sure that JWSDP_HOME\bin is in your path.

Conclusion

In this article, I've highlighted the many benefits of JAXR. You've learned how to access, publish, and query such XML registries as UDDI and the ebXML Registry, and the various snippets of code demonstrate how easy it is to work with the JAXR APIs. I hope the JAXR information model and its mapping to UDDI and the ebXML Registry are no longer a mystery to you.

Now you know the basics of JAXR and XML registries, so you can explore the JAXR API in more detail on your own.

Acknowledgments

Special thanks to Farrukh Najmi (JAXR Specification Lead), David J. Etelson (Java Strategy and Product Marketing), and Ramesh Mandava (staff engineer at Sun Microsystems who currently leads the Web Services Software Quality Engineering team) for their contributions to this article.

For more information

- Java Web Services Developer Pack v1.0:
link

- Web Services Registration and the JAXR API:
Web Services Pack

- UDDI:
http://www.uddi.org

- ebXML:
http://www.ebxml.org

- ebxmlrr open source project:
http://ebxmlrr.sourceforge.org

- Java API for XML Registries (JAXR) Specification:
http://www.jcp.org/jsr/detail/93.jsp

- Yahoo JAXR discussion group:
http://groups.yahoo.com/group/jaxr-discussion

About the authors

Qusay H. Mahmoud has published dozens of articles for the Java Developer Connection and Java Wireless Developer Initiative. He has also presented tutorials on developing wireless applications at a number of international conferences. He is the author of Distributed Programming with Java (Manning Publications, 1999) and Learning Wireless Java (O'Reilly & Associates, 2002).