The JavaTM Web Services Tutorial
Home
TOC
PREV TOP NEXT

Implementing a JAXR Client

This section describes the basic steps to follow in order to implement a JAXR client that can perform queries and updates to a UDDI registry. A JAXR client is a client program that can access registries using the JAXR API.

This tutorial does not describe how to implement a JAXR provider. A JAXR provider provides an implementation of the JAXR specification, usually as a facade around an existing registry provider, such as a UDDI or ebXML registry. The JAXR RI itself is an example of a JAXR provider.

This tutorial includes several client examples, which are described in Running the Client Examples.

The JAXR release also includes several sample JAXR clients, the most complete of which is a Registry Browser that includes a graphical user interface (GUI).

The Registry Browser source code is in the directory <JWSDP_HOME>/samples/jaxr/jaxr-browser (on UNIX systems) or <JWSDP_HOME>\samples\jaxr\jaxr-browser (on Microsoft Windows systems). Much of the source code implements the GUI. The JAXR code is in the file JAXRClient.java.

Establishing a Connection

The first task a JAXR client must complete is to establish a connection to a registry.

Preliminaries: Getting Access to a Registry

Any user of a JAXR client may perform queries on a registry. In order to add data to the registry or to update registry data, however, a user must obtain permission from the registry to access it. To register with one of the UDDI version 2 registries, go to one of the following Web sites and follow the instructions:

These UDDI version 2 registries are currently in beta test and are intended for testing purposes. When you register, you will obtain a user name and password. You will specify this user name and password in some of the JAXR client example programs.

For information on getting access permission to add or update data in the Java WSDP Registry Server, see the first step in Using the Command Line Client Script with the Registry Server.

Creating or Looking Up a Connection Factory

A client creates a connection from a connection factory. A JAXR provider may supply one or more preconfigured connection factories that clients can obtain by looking them up using the Java Naming and Directory Interface (JNDI) API.

The JAXR RI does not currently supply preconfigured connection factories. Instead, a client creates an instance of the abstract class ConnectionFactory:

import javax.xml.registry.*;	
...	
ConnectionFactory connFactory = 	
    ConnectionFactory.newInstance();
 

Creating a Connection

To create a connection, a client first creates a set of properties that specify the URL or URLs of the registry or registries being accessed and the class of the registry provider connection factory. For example, the following code provides the URLs of the IBM test query registry and test publishing registry and specifies the JAXR RI implementation of the connection factory for the UDDI registry. (There should be no line break in the strings.)

Properties props = new Properties();	
props.setProperty("javax.xml.registry.queryManagerURL",	
    "http://www-3.ibm.com/services/uddi/v2beta/inquiryapi");	
props.setProperty("javax.xml.registry.lifeCycleManagerURL",	
"https://www-
3.ibm.com/services/uddi/v2beta/protect/publishapi");	
props.setProperty("javax.xml.registry.factoryClass", 	
    "com.sun.xml.registry.uddi.ConnectionFactoryImpl");
 

With the JAXR RI, if the client is accessing a registry that is outside a firewall, it must also specify proxy host and port information for the network on which it is running. For queries it may need to specify only the HTTP proxy host and port; for updates it must specify the HTTPS proxy host and port.

props.setProperty("javax.xml.registry.http.proxyHost", 	
    "myhost.mydomain");	
props.setProperty("javax.xml.registry.http.proxyPort", 	
    "8080");	
props.setProperty("javax.xml.registry.https.proxyHost", 	
    "myhost.mydomain");	
props.setProperty("javax.xml.registry.https.proxyPort", 	
    "8080");
 

The client then sets the properties for the connection factory and creates the connection:

connFactory.setProperties(props);	
Connection connection = connFactory.createConnection();
 

The makeConnection method in the sample programs shows the steps used to create a JAXR connection.

Obtaining and Using a RegistryService Object

After creating the connection, the client uses the connection to obtain a RegistryService object and then the interface or interfaces it will use:

RegistryService rs = connection.getRegistryService();	
BusinessQueryManager bqm = rs.getBusinessQueryManager();	
BusinessLifeCycleManager blcm = 	
    rs.getBusinessLifeCycleManager();
 

Typically, a client obtains both a BusinessQueryManager object and a BusinessLifeCycleManager object from the RegistryService object. If it is using the registry for simple queries only, it may need to obtain only a BusinessQueryManager object.

Querying a Registry

The simplest way for a client to use a registry is to query it for information about the organizations that have submitted data to it. The BusinessQueryManager interface supports a number of find methods that allow clients to search for data using the JAXR information model. Many of these methods return a BulkResponse (a collection of objects) that meets a set of criteria specified in the method arguments. At this release the most useful of these methods are likely to be

The JAXRQuery program illustrates how to query a registry by organization name and display the data returned. The JAXRQueryByNAICSClassification and JAXRQueryByWSDLClassification programs illustrate how to query a registry using classifications.

The following sections describe how to perform some common queries.

Finding Organizations by Name

The following fragment shows how to find all the organizations in the registry whose names begin with a specified string, qString, and to sort them in alphabetical order.

// Define find qualifiers and name patterns	
Collection findQualifiers = new ArrayList();	
findQualifiers.add(FindQualifier.SORT_BY_NAME_DESC);	
Collection namePatterns = new ArrayList();	
namePatterns.add(qString);	
	
// Find using the name	
BulkResponse response = 	
    bqm.findOrganizations(findQualifiers, 	
        namePatterns, null, null, null, null);	
Collection orgs = response.getCollection();
 

A client can specify a case-sensitive search by using the first argument of the findOrganizations method to specify a collection of findQualifiers. For example, the following code fragment finds organizations whose names contain the string "Coffee":

Collection findQualifiers = new ArrayList();	
findQualifiers.add(FindQualifier.CASE_SENSITIVE_MATCH);	
Collection namePatterns = new ArrayList();	
namePatterns.add("%Coffee%");	
 	
// Find orgs with name containing 'Coffee'	
BulkResponse response = 	
    bqm.findOrganizations(findQualifiers, namePatterns, null,	
        null, null, null);	
Collection orgs = response.getCollection();
 

Finding Organizations by Classification

To find organizations by classification, you need to establish the classification within a particular classification scheme and then specify the classification as an argument to the findOrganizations method.

The following code fragment finds all organizations that correspond to a particular classification within the North American Industry Classification System (NAICS) taxonomy. (You can find the NAICS codes at http://www.census.gov/epcd/naics/naicscod.txt.)

BusinessLifeCycleManager lcm = 	
    rs.getBusinessLifeCycleManager();	
ClassificationScheme cScheme = 	
    lcm.findClassificationSchemeByName("ntis-gov:naics");	
Classification classification = (Classification)	
    lcm.createClassification(cScheme, "Snack and Nonalcoholic	
         Beverage Bars", "722213");	
Collection classifications = new ArrayList();	
classifications.add(classification);	
       	
// make JAXR request	
BulkResponse response = bqManager.findOrganizations(null,	
    null, classifications, null, null, null);	
Collection orgs = response.getCollection();
 

You can also use classifications to find organizations that offer services based on technical specifications that take the form of WSDL (Web Services Description Language) documents. In JAXR, a concept is used as a proxy to hold the information about a specification. The steps are a little more complicated than in the previous example, because the client must find the specification concepts first, then the organizations that use those concepts.

The following code fragment finds all the WSDL specification instances used within a given registry. You can see that the code is similar to the NAICS query code except that it ends with a call to findConcepts instead of findOrganizations.

/*	
 * Find the classification scheme defined by the	
 *  UDDI specification.	
 */	
String schemeName = "uddi-org:types";	
ClassificationScheme uddiOrgTypes =	
    bqm.findClassificationSchemeByName(schemeName);	
	
/*	
 * Create a classification, specifying the scheme	
 *  and the taxonomy name and value defined for WSDL	
 *  documents by the UDDI specification.	
 */	
Classification wsdlSpecClassification = 	
blcm.createClassification(uddiOrgTypes, 	
    "wsdlSpec", "wsdlSpec");	
	
Collection classifications = new ArrayList();	
classifications.add(wsdlSpecClassification);	
	
// Find concepts	
BulkResponse br = bqm.findConcepts(null, null, 	
    classifications, null, null);
 

To narrow the search, you could use other arguments of the findConcepts method (search qualifiers, names, external identifiers, or external links).

The next step is to go through the concepts, find the WSDL documents they correspond to, and display the organizations that use each document:

// Display information about the concepts found	
Collection specConcepts = br.getCollection();	
Iterator iter = specConcepts.iterator();	
if (!iter.hasNext()) {	
    System.out.println("No WSDL specification concepts found");	
} else {	
    while (iter.hasNext()) {	
    Concept concept = (Concept) iter.next();	
	
    String name = getName(concept);	
	
    Collection links = concept.getExternalLinks();	
    System.out.println("\nSpecification Concept:\n\tName: " + 	
        name + "\n\tKey: " + 	
        concept.getKey().getId() + 	
        "\n\tDescription: " + 	
        getDescription(concept));	
    if (links.size() > 0) {	
        ExternalLink link = 	
            (ExternalLink) links.iterator().next();	
        System.out.println("\tURL of WSDL document: '" +	
        link.getExternalURI() + "'");	
    }	
	
    // Find organizations using this concept	
    Collection specConcepts1 = new ArrayList();	
    specConcepts1.add(concept);	
    br = bqm.findOrganizations(null, null, null, 	
    specConcepts1, null, null);	
	
    // Display organization information	
    ...	
}
 

If you find an organization that offers a service you wish to use, you can invoke the service using the JAX-RPC API.

Finding Services and ServiceBindings

After a client has located an organization, it can find that organization's services and the service bindings associated with those services.

Iterator orgIter = orgs.iterator();	
while (orgIter.hasNext()) {	
    Organization org = (Organization) orgIter.next();	
    Collection services = org.getServices();	
    Iterator svcIter = services.iterator();	
    while (svcIter.hasNext()) {	
        Service svc = (Service) svcIter.next();	
        Collection serviceBindings = 	
            svc.getServiceBindings();	
        Iterator sbIter = serviceBindings.iterator();	
        while (sbIter.hasNext()) {	
            ServiceBinding sb = 	
                (ServiceBinding) sbIter.next();	
        }	
    }	
}
 

Managing Registry Data

If a client has authorization to do so, it can submit data to a registry, modify it, and remove it. It uses the BusinessLifeCycleManager interface to perform these tasks.

Registries usually allow a client to modify data only if the data is being modified by the same user who first submitted the data.

Getting Authorization from the Registry

Before it can submit data, the client must send its user name and password to the registry in a set of credentials. The following code fragment shows how to do this.

// Edit to provide your own username and password	
String username = "";	
String password = "";	
	
// Get authorization from the registry	
PasswordAuthentication passwdAuth =	
    new PasswordAuthentication(username, 	
        password.toCharArray());	
	
Set creds = new HashSet();	
creds.add(passwdAuth);	
connection.setCredentials(creds);
 

Creating an Organization

The client creates the organization and populates it with data before saving it.

An Organization object is one of the more complex data items in the JAXR API. It normally includes the following:

For example, the following code fragment creates an organization and specifies its name, description, and primary contact. When a client creates an organization, it does not include a key; the registry normally returns the new key when it accepts the newly created organization. The blcm object in this code fragment is the BusinessLifeCycleManager object returned in Obtaining and Using a RegistryService Object. An InternationalString object is used for string values that may need to be localized.

// Create organization name and description	
Organization org = 	
    blcm.createOrganization("The Coffee Break");	
InternationalString s =	
    blcm.createInternationalString("Purveyor of " +	
        "the finest coffees. Established 1895");	
org.setDescription(s);	
	
// Create primary contact, set name	
User primaryContact = blcm.createUser();	
PersonName pName = blcm.createPersonName("Jane Doe");	
primaryContact.setPersonName(pName);	
	
// Set primary contact phone number	
TelephoneNumber tNum = blcm.createTelephoneNumber();	
tNum.setNumber("(800) 555-1212");	
Collection phoneNums = new ArrayList();	
phoneNums.add(tNum);	
primaryContact.setTelephoneNumbers(phoneNums);	
	
// Set primary contact email address	
EmailAddress emailAddress = 	
    blcm.createEmailAddress("jane.doe@TheCoffeeBreak.com");	
Collection emailAddresses = new ArrayList();	
emailAddresses.add(emailAddress);	
primaryContact.setEmailAddresses(emailAddresses);	
	
// Set primary contact for organization	
org.setPrimaryContact(primaryContact);
 

Adding Classifications

Organizations commonly belong to one or more classifications within one or more classification schemes (taxonomies). To establish a classification for an organization within a taxonomy, the client locates the taxonomy it wants to use, then creates a classification. It uses the BusinessQueryManager to find the taxonomy. For example, the following code sets up a classification for the organization within the NAICS taxonomy.

// Set classification scheme to NAICS	
ClassificationScheme cScheme = 	
    bqm.findClassificationSchemeByName("ntis-gov:naics");	
	
// Create and add classification	
Classification classification = (Classification)	
    blcm.createClassification(cScheme, 	
        "Snack and Nonalcoholic Beverage Bars", "722213");   	
Collection classifications = new ArrayList();	
classifications.add(classification);	
org.addClassifications(classifications);
 

Services also use classifications, so you can use similar code to add a classification to a Service object.

Adding Services and Service Bindings to an Organization

Most organizations add themselves to a registry in order to offer services, so the JAXR API has facilities to add services and service bindings to an organization.

Like an Organization object, a Service object has a name and a description. Also like an Organization object, it has a unique key that is generated by the registry when the service is registered. It may also have classifications associated with it.

A service also commonly has service bindings, which provide information about how to access the service. A ServiceBinding object normally has a description, 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 using the service binding.

The following code fragment shows how to create a collection of services, add service bindings to a service, then add the services to the organization. It specifies an access URI but not a specification link.

// Create services and service	
Collection services = new ArrayList();	
Service service = blcm.createService("My Service Name");	
InternationalString is = 	
  blcm.createInternationalString("My Service Description");	
service.setDescription(is);	
	
// Create service bindings	
Collection serviceBindings = new ArrayList();	
ServiceBinding binding = blcm.createServiceBinding();	
is = blcm.createInternationalString("My Service Binding " +	
    "Description");	
binding.setDescription(is);	
binding.setAccessURI("http://TheCoffeeBreak.com:8080/sb/");	
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);
 

Saving an Organization

The primary method a client uses to add or modify organization data is the saveOrganizations method, which creates one or more new organizations in a registry if they did not exist previously. If one of the organizations exists but some of the data have changed, the saveOrganizations method updates and replaces the data.

After a client populates an organization with the information it wants to make public, it saves the organization. The registry returns the key in its response, and the client retrieves it.

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

Removing Data from the Registry

A registry allows you to remove from the registry any data that you have submitted to it. You use the key returned by the registry as an argument to one of the BusinessLifeCycleManager delete methods: deleteOrganizations, deleteServices, deleteServiceBindings, and others.

The JAXRDelete sample program deletes the organization created by the JAXRPublish program. It searches the registry by name for the organization and uses the key string displayed by the JAXRPublish program to verify that it is removing the correct organization. Once it has the key, it deletes the organization and then displays the key again so that the user can confirm that it has deleted the correct one.

String id = key.getId();	
System.out.println("Deleting organization with id " + id);	
Collection keys = new ArrayList();	
keys.add(key);	
BulkResponse response = blcm.deleteOrganizations(keys);	
Collection exceptions = response.getException();	
if (exceptions == null) {	
    System.out.println("Organization deleted");	
    Collection retKeys = response.getCollection();	
    Iterator keyIter = retKeys.iterator();	
    javax.xml.registry.infomodel.Key orgKey = null;	
    if (keyIter.hasNext()) {	
        orgKey = 	
            (javax.xml.registry.infomodel.Key) keyIter.next();	
        id = orgKey.getId();	
        System.out.println("Organization key was " + id);	
    }	
} 
 

A client can use a similar mechanism to delete services and service bindings.

Running the Client Examples

The simple client programs provided with this tutorial can be run from the command line. You can modify them to suit your needs. They allow you to specify the IBM registry, the Microsoft registry, or the Registry Server for queries and updates; you can specify another registry.

The client examples, in the docs/tutorial/examples/jaxr directory (on UNIX systems) or the docs\tutorial\examples\jaxr directory (on Microsoft Windows systems), are as follows:

Before You Compile the Examples

Before you compile the examples, edit the source files as follows. (See Using the JAXR API to Access the Registry Server for details on editing the examples to access the Registry Server.)

  1. Edit the following lines in the main method of each source file to specify the registry you wish to access. For both the queryURL and the publishURL assignments, comment out all but the registry you wish to access. The default is the IBM registry, so if you will be using the IBM registry you do not need to change this section.
       String queryURL = 	
           "http://www-3.ibm.com/services/uddi/v2beta/inquiryapi";	
           //"http://uddi.rte.microsoft.com/inquire";	
           // For Registry Server, replace <YourHost> with fully	
           //  qualified host name or localhost	
            //"http://<YourHost>:8080/registry- 
    server/RegistryServerServlet";	
       String publishURL = 	
           "https://www-
    3.ibm.com/services/uddi/v2beta/protect/publishapi";	
           //"https://uddi.rte.microsoft.com/publish";	
           // For Registry Server, replace <YourHost> with fully	
           //  qualified host name or localhost	
            //"http://<YourHost>:8080/registry-
    server/RegistryServerServlet";
     
    
    The IBM and Microsoft registries both have a considerable amount of data in them that you can perform queries on. Moreover, you do not have to register if you are only going to perform queries.
    If you want to publish to the IBM and Microsoft registries, the registration process for obtaining access to them is not difficult (see Preliminaries: Getting Access to a Registry). Each of them, however, allows you to have only one organization registered at a time. If you publish an organization to one of them, you must delete it before you can publish another. Since the organization that the JAXRPublish example publishes is fictitious, you will want to delete it immediately anyway.
    The Registry Server gives you more freedom to experiment with JAXR. You can publish as many organizations to it as you wish. However, this registry comes with an empty database, so you must publish organizations to it yourself before you can perform queries on the data.
  2. Edit the following lines in the makeConnection method of each source file, which contain empty strings for the proxy hosts and ports, to specify your own proxy settings. (The proxy host is the system on your network through which you access the Internet; you usually specify it in your Internet browser settings.)
       String httpProxyHost = "";	
       String httpProxyPort = "";	
       String httpsProxyHost = "";	
       String httpsProxyPort = "";
     
    
    The JAXRQuery example has only the first two of these lines, because it does not use an HTTPS proxy.
    For the IBM or Microsoft registry, your entries usually follow this pattern:
       String httpProxyHost = "proxyhost.mydomain"; 	
       String httpProxyPort = "8080"; 	
       String httpsProxyHost = "proxyhost.mydomain";	
       String httpsProxyPort = "8080";
     
    
  3. In the JAXRPublish and JAXRDelete source files, edit the following lines in the main method to specify the user name and password you obtained when you registered with the IBM or Microsoft registry.
       // Edit to provide your own username and password	
       // Defaults for Registry Server are testuser/testuser	
       String username = "";	
       String password = "";
     
    
  4. Feel free to change any of the organization data in the JAXRPublish source file.
  5. If you modify the business name in JAXRPublish, edit the following line in the main method of JAXRDelete to specify the beginning of your business name:
       String busNameString = "The Coffee";
     
    

Compiling the Examples

To compile the programs, go to the docs/tutorial/examples/jaxr directory (on UNIX systems) or the docs\tutorial\examples\jaxr directory (on Microsoft Windows systems). A build.xml file allows you to use the command

ant build
 

to compile all the examples. The ant tool creates a subdirectory called build and places the class files there.

You will notice that the classpath setting in the build.xml file includes the contents of the directories common/lib and common/endorsed. All JAXR client examples require this classpath setting.

Running the Examples

Some of the build.xml targets for running the examples contain <sysproperty> tags that set the JAXR logging level to debug. These tags are provided to illustrate how to change the default logging level. Feel free to modify or delete these tags.

If you are running the examples with the Registry Server, start Tomcat and the Xindice database. See Setting Up the Registry Server for details. You do not need to start Tomcat in order to run the examples against external registries.

Running the JAXRQuery Example

To run the JAXRQuery example, use the ant target run-query. Specify a query-string argument on the command line to search the registry for organizations whose names contain that string. For example, the following command line searches for organizations whose names contain the string "ha":

ant -Dquery-string=ha run-query
 

Running the JAXRPublish Example

To run the JAXRPublish program, use the run-publish target with no command line arguments:

ant run-publish
 

The program output displays the string value of the key of the new organization.

If you forgot to fill in the username and password strings, you will get a "No Credentials present" error message.

After you run the JAXRPublish program but before you run JAXRDelete, you can run JAXRQuery to look up the organization you published. You can also use the Registry Browser to search for it.

Running the JAXRQueryByNAICSClassification Example

After you run the JAXRPublish program, you can also run the JAXRQueryByNAICSClassification example, which looks for organizations that use the "Snack and Nonalcoholic Beverage Bars" classification, the same one used for the organization created by JAXRPublish. To do so, use the ant target run-query-naics:

ant run-query-naics
 

If you modify the classification in the JAXRPublish program, modify it in this program as well.

Running the JAXRDelete Example

To run the JAXRDelete program, specify the key string returned by the JAXRPublish program as input to the run-delete target:

ant -Dkey-string=string-value run-delete
 

Running the JAXRQueryByWSDLClassification Example

You can run the JAXRQueryByWSDLClassification example at any time. It currently returns many results from the IBM registry, but none from the Microsoft registry. Use the ant target run-query-wsdl:

ant run-query-wsdl
 

Other Targets

To remove the build directory and class files, use the command

ant clean
 

To obtain a syntax reminder for the targets, use the command

ant help
 
Home
TOC
PREV TOP NEXT