ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


O'Reilly Book Excerpts: Java Web Services

UDDI: Universal Description, Discovery, and Integration, Part 2

Related Reading

Java Web Services
By David A. Chappell, Tyler Jewell

by Tyler Jewell and David A. Chappell

This excerpt from O'Reilly's Java Web Services focuses on how to program UDDI services.

Two APIs are described by the UDDI specification: the inquiry API and the Publishing API. They are accessed using the same techniques but use different XML documents, data structures, and access points. The inquiry API locates information about a business, the services a business offers, the specifications of those services, and information about what to do in a failure situation. Any read operation from a UDDI registry uses one of the inquiry API's messages. The inquiry API does not require authenticated access and is subsequently accessed using HTTP.

The Publishing API is used to create, store, or update information located in a UDDI registry. All functions in this API require authenticated access to a UDDI registry; the UDDI registry must have a logon identity, and the security credentials for this identity must be passed as a parameter of the XML document for each UDDI invocation. Because publishing requires authenticated access, it is accessed over HTTPS, with a different URL than the one used with the inquiry access point. Table 6-1 lists the inquiry and publishing access point URLs for some major operator nodes.

Table 6-1: Access point URLs for some operator nodes

Operator node

Inquiry URL

Publishing URL

HP

http://uddi.hp.com/inquire

https://uddi.hp.com/publish

IBM Production

http://www-3.ibm.com/services/uddi/inquiryapi

https://www-3.ibm.com/services/uddi/protect/publishapi

IBM Test

http://www-3.ibm.com/services/uddi/testregistry/inquiryapi

https://www-3.ibm.com/services/uddi/testregistry/protect/publishapi

Microsoft
Production

http://uddi.microsoft.com/inquire

https://uddi.microsoft.com/publish

Microsoft
Test

http://test.uddi.microsoft.com/inquire

https://test.uddi.microsoft.com/publish

SAP Test

http://udditest.sap.com/UDDI/api/inquiry/

https://udditest.sap.com/UDDI/api/publish/

Systinet

http://www.systinet.com/wasp/uddi/inquiry/

https://www.systinet.com/wasp/uddi/publishing/

Several primary information types construct the XML documents used as input and output to UDDI invocations. This section shows these data structures along with the major APIs as defined by the UDDI specifications.

UDDI APIs are designed to be simple. All operations that a UDDI registry performs are synchronous, meaning that the requesting client blocks and waits until it receives a response message. Additionally, all operations have a simple request/response mechanism that gives them a stateless behavior. Therefore, using the UDDI APIs doesn't require a lot of complex ordering.

UDDI Data Structures

To understand the structure of the messages that are part of the API, you need a basic appreciation for the different data structures and XML formats that are used. This section discusses the major data structures that are passed as input and output parameters for major API messages. Figure 6-3 shows the relationships between the primary UDDI data structures.

Diagram.
Figure 6-3. Relationship of primary UDDI data structures.

A <businessEntity> structure represents a business's basic information. This information includes contact information, categorization, identifiers, descriptions, and relationships to other businesses. UDDI allows companies to establish relationships with one another. Many different types of relationships are possible. For example, a conglomerate can reference a subsidiary, or two companies can declare a partnership. In either case, each company must establish a unique <businessEntity> and separately establish its relationships to other companies that have their own <businessEntity> structures.

The <publisherAssertion> structure is used to establish public relationships between two <businessEntity> structures. A relationship between two <businessEntity> structures is visible only to the "public" when both companies have created the same assertion with two separate <publisherAssertion> documents independently. Thus, a company can claim a business relationship only if its partner asserts the same relationship. One company's assertion about a business relationship isn't visible to the public until its partner creates a similar, but separate, <publisherAssertion> document for its own <businessEntity> structure. Thus, if Company A asserts a relationship with Company B (fromKey=A, toKey=B), then the relationship will become public when Company B asserts a relationship with Company A (fromKey=B, toKey=A).

A <businessEntity> contains one or more <businessService> structures. A <businessService> represents a single, logical service classification. A <businessService> element is used to describe a set of services provided by the business. These services can be web services or manual services such as a nonelectronic service. A <businessService> document is reusable (i.e., a <businessService> element can be used by several <businessEntity> elements). For example, GE might create an HR web service and publish that service as part of an "HR web service" <businessService> structure. Additionally, GE might choose to list each of its subsidiaries as a separate <businessEntity>, since each subsidiary has its own IT infrastructure. Doing so would allow the <businessEntity> structure for the Plastics division to reference the same "HR web service" <businessService> as the Chemicals division.

A <businessService> contains one or more <bindingTemplate> structures. A <bindingTemplate> contains pointers to technical descriptions and the access point URL, but does not contain the details of the service's specifications. A <bindingTemplate> contains an optional text description of the web service, the URL of its access point, and a reference to one or more <tModel> structures. A <tModel> is an abstract description of a particular specification or behavior to which the web service adheres. A <tModel> is a type of digital "fingerprint" for determining the specifics of how to interact with a particular web service. The <tModel> structure does not provide the web service's specification directly. Instead, it contains pointers to the locations of the actual specifications. Companies can use the information pointed to by a <tModel> to determine whether a web service is compatible with their business requirements.

UUID

Instances of these data structures are identified and referenced by a universally unique identifier, known as a UUID. UUIDs are assigned when the data structure is first inserted into the UUID registry. They are hexadecimal strings whose structure and generation algorithm is defined by the ISO/IEC 11578:1996 standard. This standard virtually guarantees the generation of a unique identifier by concatenating the current time, hardware address, IP address, and random number in a specific fashion. The Inquiry API uses the UUID to request a particular structure on demand.

<publisherAssertion> documents do not have UUIDs, however.

Browsing Basic Information

A series of messages allow a program to retrieve basic information about a business, a web service, or metadata about a specification that a web service supports. These messages all have SOAP messages whose XML body element begins with find. Table 6-2 lists the messages that can be used to retrieve basic information for searching purposes. The "Message name" column lists the name of the XML root element used as the body of the SOAP envelope on the call's request portion. The "Response document" column shows the name of the XML root element that is the body of the SOAP envelope for the response.

Table 6-2: XML documents used in browsing inquiry messages

Message name

Response document

Brief description

<find_binding>

<bindingDetail>

Given a UUID to a <businessService> structure, this message retrieves zero or more <bindingTemplate> structures within a single <bindingDetail> structure matching the criteria specified in the input arguments.

<find_business>

<businessList>

Given a regular expression, business category, business identifier, or <tModel>, this message retrieves zero or more <businessInfo> structures contained within a single <businessList> structure that meet the criteria specified in the input arguments.

<find_relatedBusinesses>

<relatedBusinessesList>

Given the UUID of a <businessEntity>, this message returns a list of UUIDs contained within a <relatedBusinessList> structure for the other businesses that have a relationship with this business.

<find_service>

<serviceList>

Given the UUID of a <businessEntity> and either the name of the service, the <tModel> of an implemented specification, or the service category, this message returns a list of all matching <businessService> documents contained within a <serviceList> structure.

<find_tModel>

<tModelList>

Given the a name, a category, or identifier, this message returns all matching <tModel> structures contained within a <tModelList> structure.

UDDI Response Structure

Many response messages return an XML document that contains zero or more of the primary UDDI data structures, rather than the data structures themselves. For example, the <find_business> message returns zero or more <businessInfo> structures, but does so in a <businessList> structure. The <businessList> structure is merely another data structure designed to hold zero or more other elements, similar to a Java Collection object. Don't confuse collection structures such as <businessList> with the primary UDDI data structures; they exist only for grouping.

The UDDI Programmer's API and UDDI Schema documents identify dozens of different structures used to make up the request and response messages. The Programmer's API identifies the structure of the request and response messages, paying particular attention to the input parameters for every request message. The UDDI Schema represents the same data structures, but provides datatyping and constraint information that can't be conveyed in the Programmer's API. When doing any development with UDDI, you should keep a copy of these two documents.

Traversing UDDI data structures can be complicated. To demonstrate this complexity, let's delve into the inner workings of the <find_business> message. The <find_business> message returns a <businessList> structure. Here's the definition of <businessList> from the UDDI Schema:

<element name="businessList" type="uddi:businessList" />
<complexType name="businessList">
  <sequence>
    <element ref="uddi:businessInfos" />
  </sequence>
  <attribute name="generic" use="required" type="string" />
  <attribute name="operator" use="required" type="string" /> 
  <attribute name="truncated" use="optional" type="uddi:truncated" />
</complexType>

This definition says that a <businessList> contains a single <businessInfos> subelement (defined in the same schema, as indicated by the preceding uddi:) and three attributes named generic, operator, and truncated. Doesn't tell us much, does it? So, let's delve further. The schema for the <businessInfos> structure is:

<element name="businessInfos" type="uddi:businessInfos" />
<complexType name="businessInfos">
  <sequence>
    <element ref="uddi:businessInfo" minOccurs="0" maxOccurs="unbounded" />
  </sequence>
</complexType>

This definition tells us that a <businessInfos> structure contains zero or more <businessInfo> subelements, which are also defined in the same schema document. minOccurs="0" and maxOccurs="unbounded" tell us that the included <businessInfo> elements can be repeated zero or more times. We now need to seek out the schema definition of the <businessInfo> structure, which is:

<element name="businessInfo" type="uddi:businessInfo" />
<complexType name="businessInfo">
  <sequence>
    <element ref="uddi:name" maxOccurs="unbounded" />
    <element ref="uddi:description" minOccurs="0" maxOccurs="unbounded" />
    <element ref="uddi:serviceInfos" />
  </sequence>
  <attribute name="businessKey" use="required" type="uddi:businessKey" />
</complexType>

This structure contains three subelements and an attribute. The attribute, businessKey, is the UUID for this business. The first subelement, <name>, gives the name of the business. The second subelement, <description>, is zero or more text elements that describe what the business does. The third subelement, <serviceInfos>, is a grouping of <businessService> documents. To figure out what a <businessService> document is, we must search the schema for the <serviceInfos> element.

Searching for this schema is left as the proverbial "exercise for the reader." At this stage, you should have an idea of the complexity of UDDI data structures and their navigation. An entire book could be dedicated to exploring every facet of the UDDI Programmers API. The rest of this chapter focuses on how to interact with UDDI and presents Java clients that demystify some of the complexity in the UDDI API and its data structures.

Finding a Business

Now it's finally time to pull everything that we have talked about together into a program. The examples in this chapter use Systinet WASP UDDI Standard. We selected this software because it is robust and free for development purposes. It includes:

We use Systinet WASP UDDI Standard primarily for its local registry, which allows you to run a registry locally on your computer for testing and development. We won't focus on the client API. Since a UDDI server accepts standard SOAP messages, we can use any Java-based SOAP client API to create the appropriate messages and direct them to a valid UDDI registry.

Our first UDDI client retrieves basic business information for a fictitious company called Demi Credit. The Systinet WASP UDDI registry comes with a preconfigured entry for Demi Credit. This example uses the Apache SOAP client library to create an appropriate SOAP message that has a <find_business> document as its body. We won't create this document programmatically, which would be an exercise in the use of the DOM or JDOM APIs; instead, we'll take the body for our SOAP request message from the file Ch6_FindBusiness.xml:

<uddi:find_business generic="2.0" maxRows="10">
  <uddi:name>
    Demi Credit
  </uddi:name>
</uddi:find_business>

The <uddi:find_business> tag indicates that this element is named find_business and defined in the uddi namespace. The contents of the tag must adhere to the schema for find_business, which defines a couple of different attributes. The generic attribute indicates the UDDI API version that is used (Version 2.0, in this case). maxRows indicates how many matching <businessInfo> structures should be returned if the query matches more than one company.

Optional Attributes and Elements

All UDDI API messages have several optional attributes and elements. For example, the maxRows attribute of the <find_business> element is optional. If this attribute is not included, the response message will contain an unbounded list of every match that could be found (up to the point where the UDDI server truncates a response).

In fact, the <name> subelement of <find_business> is optional as well. You can search for companies in other ways (besides using their name). You can search by category (through the <categoryBag> element), identifier (through the <identifierBag> element), or a particular specification that one of their web services implements (through the <tModelBag> element). Categories and identifiers are discussed in more detail later in this chapter.

This <find_business> element has a single subelement, <name>, which is the meat of our request. The value of the <name> element is a simple regular expression used to search the names of different businesses. The percentage sign (%) can be used for wildcard matching. In this example, we know the name of the company we are searching for: Demi Credit.

Before looking at the code for the client, let's run it and observe its behavior. The client reads an XML file, wraps it in a SOAP envelope, and sends it to a URL destination, adding various UDDI and Systinet namespace declarations that are required to make the SOAP message comply to the UDDI specification. The destination is the URL of an endpoint configured to accept UDDI inquiry messages. Run the command:

java UDDISoapClient -df ./Ch6_FindBusiness.xml

You should see the following output:

_________________________________________________
Starting UDDISoapClient:
    host url      = http://localhost:8080/wasp/uddi/inquiry/
    data file     = Ch6_FindBusiness.xml
_________________________________________________
Sent SOAP Message with Apache HTTP SOAP Client.
Waiting for response....
 
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Body>
    <businessList xmlns="urn:uddi-org:api_v2" generic="2.0" operator="SYSTINET">
      <businessInfos>
        <businessInfo businessKey="892ac280-c16b-11d5-85ad-801eef208714">
          <name xml:lang="en">
            Demi Credit
          </name>
          <description xml:lang="en">
            A smaller demo credit agency used for illustrating UDDI inquiry.
          </description>
          <serviceInfos>
            <serviceInfo serviceKey="860eca90-c16d-11d5-85ad-801eef208714" 
              businessKey="9a26b6e0-c15f-11d5-85a3-801eef208714">
              <name xml:lang="en">
                DCAmail
              </name>
            </serviceInfo>
          </serviceInfos>
        </businessInfo>
      </businessInfos>
    </businessList>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

This output is saved as Ch6_FindBusiness_OUTPUT.xml and is included with the examples provided for this chapter. Other examples that use this program have their response documents saved in the same format.

Let's pick apart the response to see what it contains. The UDDI Server returned a single <businessList> structure which, in turn, has a single <businessInfos> structure. The <businessInfos> element can have zero or more <businessInfo> elements, based upon the number of businesses that were matched as part of the query. In this case, the server found only one business matching the name Demi Credit in the UDDI registry.

The <businessInfo> element contains several other important pieces of information. First, the businessKey attribute contains the UUID of Demi Credit. The UUID value is needed to do a more detailed information search or an update using the Publisher's API. Second, the <businessInfo> structure has a <description> that contains a textual description of what the company does. Next, the <businessInfo> structure contains a <serviceInfos> structure that contains a collection of all web services registered by this business. Each web service is described by a single <serviceInfo> structure, which contains the web service's UUID as an attribute.

Now that we've seen what the client does and examined the documents it sends and receives, it is time to look at UDDISoapClient.java in its entirety:

import java.io.*;
import java.util.*;
 
public class UDDISoapClient
{
    // Default values used if no command line parameters are set
    private static final String DEFAULT_HOST_URL = 
                               "http://localhost:8080/wasp/uddi/inquiry/";
    private static final String DEFAULT_DATA_FILENAME   = "./Default.xml";
    
    // In the SOAP chapter, we used "urn:oreilly:jaws:samples", 
    // but Systinet UDDI requires this to be blank.
    private static final String URI                     = "";
    private String m_hostURL;
    private String m_dataFileName;
 
    public UDDISoapClient(String hostURL, String dataFileName) throws Exception
    {
        m_hostURL = hostURL;
        m_dataFileName    = dataFileName;
        
        System.out.println(  );
        System.out.println("______________________________________");
        System.out.println("Starting UDDISoapClient:");
        System.out.println("    host url        = " + m_hostURL);
        System.out.println("    data file       = " + m_dataFileName);
        System.out.println("______________________________________");
        System.out.println(  );
    }
    
    public void sendSOAPMessage(  ) {
        try {
 
            // Get soap body to include in the SOAP envelope from FILE
            FileReader fr = new FileReader (m_dataFileName);
            javax.xml.parsers.DocumentBuilder xdb = 
                org.apache.soap.util.xml.XMLParserUtils.getXMLDocBuilder(  );
            org.w3c.dom.Document doc = 
                xdb.parse (new org.xml.sax.InputSource (fr));
            if (doc == null) {
                throw new org.apache.soap.SOAPException 
                    (org.apache.soap.Constants.FAULT_CODE_CLIENT, "parsing error");
            }
            
            // Create a vector for collecting the body elements
            Vector bodyElements = new Vector(  );
            
            // Parse XML element as soap body element
            bodyElements.add(doc.getDocumentElement (  ));
            
            // Create the SOAP envelope
            org.apache.soap.Envelope envelope = new org.apache.soap.Envelope(  );
            envelope.declareNamespace("idoox", "http://idoox.com/uddiface");
            envelope.declareNamespace("ua", "http://idoox.com/uddiface/account");
            envelope.declareNamespace("config", 
              "http://idoox.com/uddiface/config");
            envelope.declareNamespace("attr", "http://idoox.com/uddiface/attr");
            envelope.declareNamespace("fxml", "http://idoox.com/uddiface/formxml");
            envelope.declareNamespace("inner", "http://idoox.com/uddiface/inner");
            envelope.declareNamespace("", "http://idoox.com/uddiface/inner");
            envelope.declareNamespace("uddi", "urn:uddi-org:api_v2");
            
            //
            // NO SOAP HEADER ELEMENT AS SYSTINET WASP DOES NOT REQUIRE IT
            //
            
            // Create the SOAP body element
            org.apache.soap.Body body = new org.apache.soap.Body(  );
            body.setBodyEntries(bodyElements);
            envelope.setBody(body);
            
            // Build and send the Message.
            org.apache.soap.messaging.Message msg = 
                new org.apache.soap.messaging.Message(  );
            msg.send (new java.net.URL(m_hostURL), URI, envelope);
            System.out.println("Sent SOAP Message with Apache HTTP SOAP Client.");
            
            
            // Receive response from the transport and dump it to the screen
            System.out.println("Waiting for response....");
            org.apache.soap.transport.SOAPTransport st = msg.getSOAPTransport (  );
            BufferedReader br = st.receive (  );
            
            if(line == null) {
                System.out.println("HTTP POST was unsuccessful. \n");
            } else {
                while (line != null) {
                    System.out.println (line);
                    line = br.readLine(  );
                }
            }
 
        /////
        // Version in examples has XML pretty printing logic here.
        ////
 
        } catch(Exception e) {
            e.printStackTrace(  );
        }
    }
    
    //
    // NOTE: the remainder of this deals with reading arguments
    //
    /** Main program entry point. */
    public static void main(String args[]) {
    
      // Not Relevant
 
    }
}

This code is similar to the code presented in the SOAP chapters, with a couple of exceptions. First, Systinet WASP UDDI uses different servlets to implement the inquiry and publisher ports. When Systinet WASP UDDI is first installed, the URL of the inquiry port is http://localhost:8080/wasp/uddi/inquiry. In the program, this URL is assigned to the constant DEFAULT_HOST_URL:

private static final String DEFAULT_HOST_URL = 
        "http://localhost:8080/wasp/uddi/inquiry/";

Second, UDDI SOAP messages don't require the use of a SOAP header. Thus, all of the code used to create a SOAP header and fill it with values, such as mustUnderstand, is not needed. Next, UDDI and Systinet WASP UDDI SOAP envelopes require the addition of several different namespaces that they have defined. These namespaces are required at the envelope level of the message, not the SOAP header or body. In the Apache SOAP API, the Envelope interface has a method called declareNamespace( ) that adds these additional namespaces:

// Create the SOAP envelope
org.apache.soap.Envelope envelope = new org.apache.soap.Envelope(  );
 
// Add the Systinet namespaces.  
envelope.declareNamespace("idoox", "http://idoox.com/uddiface");
envelope.declareNamespace("ua", "http://idoox.com/uddiface/account");
envelope.declareNamespace("config", "http://idoox.com/uddiface/config");
envelope.declareNamespace("attr", "http://idoox.com/uddiface/attr");
envelope.declareNamespace("fxml", "http://idoox.com/uddiface/formxml");
envelope.declareNamespace("inner", "http://idoox.com/uddiface/inner");
 
// Add the default namespace
envelope.declareNamespace("", "http://idoox.com/uddiface/inner");
 
// Include the standard UDDI namespace.
// This URN contains all of the UDDI XML data structures and messages.
envelope.declareNamespace("uddi", "urn:uddi-org:api_v2");

WARNING:   Systinet was formally named Idoox. In their documentation, namespaces, and other declarations, you'll often see references to Idoox. When you come across these references, treat them synonymously with Systinet.

Using Systinet's UDDI Java API

The simple SOAP client we've just examined is sufficient to demonstrate a variety of UDDI APIs and data structures. It has some obvious limitations, however:

To get a feeling for what these limitations mean, we'll implement the same example using Systinet's UDDI Java API. To run this program, compile the file SystinetFindBusiness.java and execute the following command:

java -Dwasp.restrictor.packages=- SystinetFindBusiness

Because of a limitation in the way the Systinet UDDI client library operates, you get a series of array typing error messages if you omit the -Dwasp.restrictor.packages=- environment variable definition. Don't forget to include the hyphen (-) after the equal sign!

Here's a listing of the Systenet-based client in its entirety:

import org.idoox.uddi.client.api.v2.request.inquiry.*;
import org.idoox.uddi.client.structure.v2.tmodel.*;
import org.idoox.uddi.client.api.v2.response.*;
import org.idoox.uddi.client.structure.v2.base.*;
import org.idoox.uddi.client.structure.v2.business.*;
import org.idoox.uddi.client.api.v2.*;
import org.idoox.uddi.client.*;
 
/**
 * This is simple example of Systinet's UDDI Java API for accessing 
 * a UDDI registry.
 * This program does a find_business call by name.
 */
 
public class SystinetFindBusiness {
 
    // Program Entry Point
    public static void main(String args[]) throws Exception
    {
        String company = "Demi Credit";
        findBusinessByName(company);
    }
 
    public static void findBusinessByName(String name) throws Exception
    {
        System.out.println("Searching for businesses named '" + 
                            name + "'...");
 
        // Create a FindBusiness instance.
        // This creates a SOAP message.
        FindBusiness findBusiness = new FindBusiness(  );
 
        // Set the name to use in the query.
        findBusiness.addName(new Name(name));
 
        // This will limit the number of returned matches.  
        // maxRows is an optional attribute.
        findBusiness.setMaxRows(new MaxRows("10"));
 
        // This will retrieve a stub to the UDDI inquiry port.
        UDDIApiInquiry inquiry = 
               UDDILookup.getInquiry("http://localhost:8080/wasp/uddi/inquiry/");
 
        // Send the message and retrieve the response.
        BusinessList businessList=inquiry.find_business(findBusiness);
 
        // Show the results
        if (businessList==null) {
            System.err.println("ERROR: Business list is null!");
        }
        else {
            // Business list is holder for results - business infos.
            BusinessInfos businessInfos = businessList.getBusinessInfos(  );
            System.out.println("\nFound: " + 
                               businessInfos.size(  ) + 
                               " businesses.\n");
 
            // Iterate through each company found in the query.
            BusinessInfo businessInfo = businessInfos.getFirst(  );
            BusinessKey result;
            if (businessInfo != null) {
                result=businessInfo.getBusinessKey(  );
                
                while (businessInfo!=null) {
                    System.out.println("BusinessEntity name = " + 
                               businessInfo.getNames().getFirst().getValue(  ));
                    System.out.println("BusinessEntity UUID = " + 
                               businessInfo.getBusinessKey(  ));
                    System.out.println("***");
                    businessInfo = businessInfos.getNext(  );
                }
            }
        }
    }
}  

The Systinet UDDI client library is spread throughout several different packages. Since the UDDI API and data structures changed from Version 1.0 to Version 2.0 of the specification, Systinet opted to create separate Java packages for each version. This can be problematic for developers, but it is workable. Here are the import statements needed for the current crop of packages:

import org.idoox.uddi.client.api.v2.request.inquiry.*;
import org.idoox.uddi.client.structure.v2.tmodel.*;
import org.idoox.uddi.client.api.v2.response.*;
import org.idoox.uddi.client.structure.v2.base.*;
import org.idoox.uddi.client.structure.v2.business.*;
import org.idoox.uddi.client.api.v2.*;
import org.idoox.uddi.client.*;

The main( ) method is responsible for declaring the search string for the company and calling findBusinessByName( ), where the bulk of the work is performed:

    // Program Entry Point
    public static void main(String args[]) throws Exception
    {
        String company = "Demi Credit";
        findBusinessByName(company);
    }

Within findBusinessByName( ), the program needs to create a <find_business> message and populate it with the search criteria we established. The Systinet UDDI library has a separate class abstraction representing each UDDI XML message. Therefore, to create a <find_business> structure, you merely need to create an instance of their FindBusiness class. The FindBusiness class has several methods that add elements and attributes to the underlying <find_business> structure. In this example, we'll use addName( ), which adds the company name to search for, and setMaxRows( ), which limits the number of matches returned:

        // Create a FindBusiness instance.
        // This creates a SOAP message.
        FindBusiness findBusiness = new FindBusiness(  );
 
        // Set the name to use in the query.
        findBusiness.addName(new Name(name));
 
        // This will limit the number of returned matches.  
        // maxRows is an optional attribute.
        findBusiness.setMaxRows(new MaxRows("10"));

Next, the program creates a connection to a UDDI server's inquiry port. The UDDILookup class has static methods that create a dynamic Java proxy object that communicates using SOAP. From the developer's point of view, it looks and feels like an RMI stub, except it doesn't communicate over RMI. The UDDILookup.getInquiry( ) method creates an inquiry connection. This program uses the same inquiry port as the UDDISoapClient program, http://localhost:8080/wasp/uddi/inquiry/. An UDDIApiInquiry object is returned and encapsulates an active stub that communicates with the UDDI server:

        // This will retrieve a stub to the UDDI inquiry port.
        UDDIApiInquiry inquiry = 
               UDDILookup.getInquiry("http://localhost:8080/wasp/uddi/inquiry/");

Finally, the program needs to send the <find_business> document as part of a SOAP message. The UDDIApiInquiry object has a number of methods that create the SOAP envelope and populate it with an XML structure. A separate method exists for each UDDI XML message in the Programmer's API. For our example, the program calls the find_business( ) method on the UDDIApiInquiry object, passing in the FindBusiness object containing the XML structure.

The Systinet API also has matching classes for the response XML structures. Thus, since a <find_business> request yields a <businessList> response structure, the Systinet API has a BusinessList class. We can traverse this class to get to each subelement and attribute that was returned:

        BusinessList businessList=inquiry.find_business(findBusiness);
 
        // Show the results
        if (businessList==null) {
            System.err.println("ERROR: Business list is null!");
        }
        else {
            // Business list is holder for results - business infos.
            BusinessInfos businessInfos = businessList.getBusinessInfos(  );
            System.out.println("\nFound: " + 
                               businessInfos.size(  ) + 
                               " businesses.\n");
 
            // Iterate through each company found in the query.
            BusinessInfo businessInfo = businessInfos.getFirst(  );
            BusinessKey result;
            if (businessInfo != null) {
                result=businessInfo.getBusinessKey(  );
        
                while (businessInfo!=null) {
                    System.out.println("BusinessEntity name = " + 
                               businessInfo.getNames().getFirst().getValue(  ));
                    System.out.println("BusinessEntity UUID = " + 
                               businessInfo.getBusinessKey(  ));
                    System.out.println("***");
                    businessInfo = businessInfos.getNext(  );
                }
            }
        }

The next installment will focus on programming UDDI with the Java API for XML Registries.

Tyler Jewell , Director, Technical Evangelism, BEA Systems Tyler oversees BEA's technology evangelism efforts that are focused on driving early adoption of strategic BEA technologies into the ISV and developer community.

David A. Chappell is vice president and chief technology evangelist for is vice president and chief technologist for SOA at Oracle Corporation.


View catalog information for Java Web Services

Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.