Main Page

Previous Section Next Section

The JAXR API

So far, we have discussed at a conceptual level the object model defined by JAXR. Let us now look at the API that client applications use to interact with the registry and work with this model.

RegistryService is the main interface implemented by the JAXR pluggable provider layer. It allows the client to query the implementation for the capability level it supports and also obtain references to the three main interfaces from the underlying registry-specific providers. These are:

All objects in the information model are implemented as interfaces in JAXR. The underlying registry provider supplies the implementation classes. As Figure 12.12 shows, we will break up the API into four parts for discussion, along the lines of connecting to the registry, creating data items, finding data, and performing queries on the registry. Let us look at each of them in detail.

Click To expand
Figure 12.12: JAXR API

JAXR and Connections

The first few step in any JAXR application is to establish a connection to the underlying registry, which is abstracted with a RegistryService interface. In general, all JAXR applications have the following sequence:

  1. Create a ConnectionFactory.

  2. Create a Connection object from that factory to the registry.

  3. Pass the Connection the appropriate user credentials (e.g., username and password) required by the registry operator.

  4. Obtain the reference to the RegistryService from the connection.

  5. Do some work with the RegistryService.

JAXR uses the Factory pattern and a ConnectionFactory that can be configured with properties for initializing the underlying Connection object. Just like the JAXM factories discussed in Chapter 11, the JAXR factory can be obtained from the J2EE container's JNDI context, as shown below:

HashMap properties = new HashMap();
properties.put("some property", "some value");
// set other properties.
InitialContext ctx = new InitialContext(properties);

ConnectionFactory connfactory =
       (ConnectionFactory)ctx.lookup("java:comp/env/jaxr/connectionfactory");

Note that the JNDI mechanism can be used only if the container supports it. Tomcat and the reference implementation servlet container do not have this feature. EJB containers such as the J2EE reference implementation do have this feature.

Table 12.1 shows the properties specified by JAXR. The only required setting is the javax.xml.registry.queryManagerURL property; others are optional. The factory can also be instantiated by the default mechanism using the new-Instance() method, as shown below:

// Set the properties for the factory
        Properties environment = new Properties();
        environment.setProperty("javax.xml.registry.queryManagerURL", QUERY_URL);
        environment.setProperty("javax.xml.registry.lifeCycleManagerURL",
                                                                    PUBLISH_URL);
 // Instantiate the factory and create a connection from it
        ConnectionFactory connfactory = ConnectionFactory.newInstance();
        connfactory.setProperties(environment);
        Connection connection = connfactory.createConnection();
// Authenticate the username and password with the registry
      PasswordAuthentication passwdAuth = new PasswordAuthentication(uddiusername,
                                                      uddipassword.toCharArray());
            Set credentials = new HashSet();
            credentials.add(passwdAuth);
            connection conn.setCredentials(credentials);
// Obtain a reference to the registry service
          RegistryService registryservice = connection.getRegistryService();
Table 12.1: The JAXR Connection Properties

Connection property

Description

javax.xml.registry.queryManagerURL

A required string that specifies the URL to the query manager service for the provider.

javax.xml.registry.lifeCycleManagerURL

An optional string that specifies the URL to the lifecycle manager service for the provider.

javax.xml.registry.semanticEquivalences

An optional set of tuples that specifies how two Concepts in two different ClassificationSchemes for the internal taxonomy may be considered equivalent (for example, microsoft-com:geoweb:2000:United States, microsoft-com:geoweb:2000:USA | microsoft-com:geoweb:2000:Netherland, microsoft-com:geoweb:2000:Holland)

javax.xml.registry.security.authenticationMethod

An optional string that may be used to tell the provider about the authentication method to use

javax.xml.registry.uddi.maxRows

An optional integer that tells UDDI registries the maximum number of rows that should be returned for find operations

javax.xml.registry.postalAddressScheme

The PostalAddress object in the information model has well-defined attributes (e.g., street, city, postal code), whereas some registries, such as the UDDI registry, may represent address attributes simply as a set of lines. This optional string property can be used to specify a ClassificationScheme (i.e., a postal address scheme) the provider uses to map the structured information in JAXR and unstructured information in the underlying registry.

JAXR and Create-Replace-Update-Delete (CRUD) Operations

The second part of the JAXR API deals with how applications can work with and manipulate objects in the information model with operations that can be used to create, update, delete, and save data in the underlying registry. The JAXR provider is responsible for translating these operations into the underlying registry's API calls.

The LifeCycleManager and the BusinessLifeCycleManager in the javax.xml.registry package shown in Figure 12.12 primarily abstracts all these operations, which are shown in Figure 12.13. The two lifecycle managers contain overloaded methods for:

  • Creating metadata entries such as Associations, Classification, ClasslificationScheme, and Concept

  • Creating data entries such as Organization, User, PostalAddress, Telephonenumber, Service, and ServiceBinding

  • Saving and deleting the Organization, Service, Concepts, Associations, and so on

Click To expand
Figure 12.13: The LifeCycleManager and the BusinessLifeCycleManager

Earlier in the chapter, we mentioned how everything in the information model is represented by an interface and that the implementation classes are vendor-provided. The BusinessLifeCyleManager is used as a factory for instantiating these objects in application classes. For example, empty User and TelephoneNumber objects can be created as shown below and subsequently populated with relevant attributes:

User contact = lifecyclemgr.createUser();
    TelephoneNumber telnum = lifecyclemgr.createTelephoneNumber();

JAXR and Get-Find Operations

The third part of the API relates to searching the registry using get-find type operations. These operations relating to retrieving data from the underlying registry are abstracted by the QueryManager and the BusinessQueryManager interfaces in the javax.xml.registry package, as Figure 12.14 shows. Both these query managers contain overloaded methods that relate to different mechanisms for searching and retrieving information on existing data in the registry. The data could relate to Associations, Organizations, Concepts, or other objects from the information model. The JAXR provider takes care of translating these operations into the underlying registry's API and generating the corresponding SOAP messages.

Click To expand
Figure 12.14: The QueryManager and the BusinessQueryManager

A registry can be queried for different fields (e.g., Organization, Concepts, ServiceBindings, Service, Associations) using the BusinessQueryManager interface. Each argument to the methods in this interface is of type java.util.Collection, which represents the following:

  • findQualifiers. Constants specified in the javax.xml.registry.FindQualifier interface that specify the find criteria (e.g., sorting, searching, etc.) For example, to search in a case-sensitive manner and have the results arranged in descending order, the qualifier parameter would look like this:

    Collection findqualifier= new ArrayList();
    findqualifier.add(FindQualifier. CASE_SENSITIVE_MATCH);
    findqualifier.add(FindQualifier. SORT_BY_NAME_DESC);
    
  • namePatterns. The wildcard pattern based on the syntax of the SQL LIKE clause to search on (e.g., %Flute%, %Flute, Flute, Flute%, etc.)

  • For example, to search for an organization whose name contains starts with "Flute" in a case-sensitive manner and have the results arranged in descending order, the code would look like this:

    Collection findqualifier= new ArrayList();
    findqualifier.add(FindQualifier. CASE_SENSITIVE_MATCH);
    findqualifier.add(FindQualifier. SORT_BY_NAME_DESC);
    Collection searchpattern = new ArrayList();
    searchpattern.add("%Flute");
    BulkResponse response =  querymgr.findOrganizations(findqualifier,searchpattern,
                             null, null, null, null);
    
  • classifications. The Classification objects to use during the find operation.

  • specifications. The javax.xml.registry.infomodel.Concept or javax.xml.registry.infomodel.ExtrinsicObject objects to use during the find operation.

  • externalIdentifiers. The javax.xml.registry.infomodel.ExternalIdentifiers objects to use during the find operation.

  • externalLinks. The javax.xml.registry.infomodel.ExternalLink objects to use during the find operation.

Typical use cases covered later in this chapter will show more detailed code using these parameters in the corresponding find operations.

JAXR and Declarative Queries

Level 1 registries, such as the ebXML registry, expose clients with the ability to execute declarative queries against the registry (Figure 12.15). JAXR abstracts this using the Query and DelarativeQuery interfaces. JAXR at present supports only SQL-92 and the OASIS ebXML registry filter queries. An example of a simple query that returns all the organizations in the registry is shown below:

// obtain a connection here
RegistryService registryservice = conn.getRegistryService();
DeclarativeQueryManager decquerymgr
                       = registryservice. getDeclarativeQueryManager;
String querystr = "SELECT * FROM Organization"
Query query = decquerymgr.createQuery(Query.QUERY_TYPE_SQL, querystr);
BulkResponse response = dqm.executeQuery(query);
Click To expand
Figure 12.15: The DeclarativeQueryManager for level 1 providers

Publishing Company Information to a UDDI Registry

The JAXR API provides a higher level of abstraction. There are essentially two ways to register the business and the services it provides with a UDDI registry. UDDI specifications require that a UDDI provider expose the registry though a Web-based HTML interface, such as that shown in earlier figures. In this section, we will show how the JAXR API can be used to register details about Flute Bank and its bill payment Web service in the UDDI registry.

From an information model perspective, here are the steps that need to be followed to create the conceptual representation:

  1. Create an Organization object.

  2. Create a User object with a TelephoneNumber and EmailAddress and set it as the primary contact for the Organization.

  3. Classify the Organization. We will follow the NAICS classification scheme and assign the code and category description that fits Flute Bank: the high-level category of "Finance and Insurance," with a corresponding code of 52.

From an implementation perspective, the steps are straightforward:

  1. Create a Connection and obtain a reference to the RegistryService.

  2. Obtain a BusinessLifeCycleManager from the RegistryService.

  3. Obtain a BusinessQueryManager from the RegistryService. This is used only to set the ClassificationScheme.

  4. Create the information model, as outlined above. Save the organization in the registry by invoking the saveOrganizations(Collection organizations) method in the BusinessLifeCycleManager.

  5. Parse the BulkResponse returned by the registry to obtain the unique key the registry assigned our service.

  6. Close the connection to the registry.

Listing 12.1 shows the complete code for these steps. Upon successful registration, the registry assigns a unique key and discovery URL to Flute Bank, which are printed in the output of the example. The successful registration can be verified using the Web interface of the registry, shown in Figure 12.16.

Click To expand
Figure 12.16: Flute Bank as registered in the IBM UDDI registry
Listing 12.1: Publishing organization information
Start example
import javax.xml.registry.infomodel.*;
import javax.xml.registry.*;
import java.util.*;
import java.net.PasswordAuthentication;

public class UDDIPublishOrg {
        private static final String QUERY_URL=
          "http://www-3.ibm.com:80/services/uddi/v2beta/inquiryapi";
    private static final String PUBLISH_URL =
        "https://www-3.ibm.com:443/services/uddi/v2beta/protect/publishapi";
        private static String uddiusername;
        private static String uddipassword;
    public static void main(String[] args) {
        if(args.length!=2){
           System.out.println("Usage java UDDIPublish username uddipassword");
            return;
        }
        uddiusername = args[0];
     uddipassword = args[1];
try{

// Set the properties for the ConnectionFactory
Properties environment = new Properties();
environment.setProperty("javax.xml.registry.queryManagerURL", QUERY_URL);
environment.setProperty("javax.xml.registry.lifeCycleManagerURL",PUBLISH_URL);

 // Instantiate the factory and create a connection from it
    ConnectionFactory connfactory = ConnectionFactory.newInstance();
    connfactory.setProperties(environment);
    Connection conn = connfactory.createConnection();

  // Authenticate the username and password with the registry
     PasswordAuthentication passwdAuth = new PasswordAuthentication
                                   (uddiusername, uddipassword.toCharArray());
     Set credentials = new HashSet();
     credentials.add(passwdAuth);
     conn.setCredentials(credentials);

 // Obtain a reference to the RegistryService, the BusinessLifeCycleManager, and
//  the BusinessQueryManager
   RegistryService registryservice = conn.getRegistryService();
   BusinessLifeCycleManager lifecyclemgr
                               =registryservice.getBusinessLifeCycleManager();
   BusinessQueryManager querymgr = registryservice.getBusinessQueryManager();

//  Create an organization object
   Organization company =   lifecyclemgr.createOrganization("Flute Bank");
   InternationalString description = lifecyclemgr.createInternationalString("A
         fictitious bank used for examples in the book Java Web Services Architecture,
            "+                    "published by Morgan Kaufman, ISBN 1-55860-900-8." +
"The authors can be reached at    webservicesbook@yahoogroups.com OR" +
     "www.javawebservicesarchitecture.com. ");
     company.setDescription(description);
 // Create a user object
     User contact = lifecyclemgr.createUser();
     PersonName name = lifecyclemgr.createPersonName("John Malkovich");
     contact.setPersonName(name);

 // Create and set the user's telephone number
     TelephoneNumber telnum = lifecyclemgr.createTelephoneNumber();
     telnum.setNumber("1-800-FLUTE-US");
     Collection phonenumbers = new ArrayList();
     phonenumbers.add(telnum);
     contact.setTelephoneNumbers(phonenumbers);

// Create and set the user's email address
     EmailAddress email = lifecyclemgr.createEmailAddress
                                             ("uddiadmin@flutebank.com");
            Collection emaillist = new ArrayList();
            emaillist.add(email);
            contact.setEmailAddresses(emaillist);

 // Set the user as the primary contact for the organization
            company.setPrimaryContact(contact);
     ClassificationScheme scheme =
               querymgr.findClassificationSchemeByName(null," ntis-gov:naics");

 // Create the classification using the above scheme and pass the relevant category
                                                                  code and description
            Classification classification =
(Classification)lifecyclemgr.createClassification(scheme, "Finance and Insurance",
                                                                                "52");
            Collection classificationlist = new ArrayList();
            classificationlist.add(classification);
            company.addClassifications(classificationlist);

// Set the organization in the list of organizations
// An organization list is a list of organizations, because a user could choose to
                                                       publish multiple organizations
           Collection organizationlist = new ArrayList();
           organizationlist.add(company);
// make the final call to the registry and get a response
            BulkResponse response = lifecyclemgr.saveOrganizations(organizationlist);
            Collection exceptions = response.getExceptions();

// If there are no exceptions, the publish action was successful
            if (exceptions == null) {
                Collection keys = response.getCollection();
                Iterator iterator = keys.iterator();
                Key key = (Key) iterator.next();
                String uid = key.getId();
                System.out.println("The unique ID returned by the UDDI registry for
                                                           the Organization is " + uid);
                company.setKey(key);
                }
// This means exceptions occurred during the publish action
                else {
                Iterator iterator = exceptions.iterator();
                while (iterator.hasNext()) {
                    Exception exception = (Exception) iterator.next();
                    System.out.println("Exception occurred while saving to the
                                                               registry: " + exception);
                }
            }
// Finally, close the connection
            conn.close();
        } catch (Exception exception) {
             System.out.println("General exception occurred: " + exception);
        }
    }
}
End example

Let us examine what happens under the hood when the example class UDDIPublish is executed. Publication calls to UDDI happen only as a set of authenticated operations where the authentication is token-based. The JAXR provider connects to the registry using SSL and verifies the username and password by making the get_authToken call. The registry returns the XML response with the authToken element. The request sent looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
  <soap-env:Body>
      <get_authToken generic="2.0" userID="fluteuddi" cred="fluteuddi"
              xmlns="urn:uddi-org:api_v2"/>
  </soap-env:Body>
</soap-env:Envelope>

The response from the registry looks like this:

    <?xml version="1.0" encoding="UTF-8"?>
        <authToken generic="2.0" xmlns="urn:uddi-org:api_v2"
                                operator="www.ibm.com/services/uddi">
<authInfo>xyzi2892somesecuretoken</authInfo>
   </authToken>

The provider then sends another SOAP request, which includes the token and XML structure, based on the save_business UDDI operation:

<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Body>
<save_business generic="2.0" xmlns="urn:uddi-org:api_v2">
  <authInfo>xyzi2892somesecuretoken</authInfo>
  <businessEntity businessKey="">
     <name xml:lang="en">Flute Bank</name>
    <description xml:lang="en">A fictitious bank used for examples in the book
              Java Web Services Architecture, published by Morgan Kaufman, ISBN
       1-55860-900-8. The authors can be reached at webservicesbook@yahoogroups.com OR
http://www.javawebservicesarchitecture.com.
      </description>
    <contacts>
    <contact>
         <description xml:lang="en">
                  The primary contact person for Flute web services
             </description>
         <personName>John Malkovich</personName>
         <phone useType="">1-800-FLUTE-US</phone>
         <email>uddiadmin@flutebank.com</email>
    </contact>
   </contacts>
   <businessServices>
      <businessService serviceKey="">
      <name xml:lang="en">Billpayservice</name>
       <description xml:lang="en">A web service allowing online account holders to
                                                          pay bills online</description>
   <bindingTemplates>
       <bindingTemplate bindingKey="">
                  <description>Flute Bank, beyond providing simple account-related
               services, also has the infrastructure to support online bill payments.
     The online bill payment system is offered to customers as a value-added service.
               </description>
                   <accessPoint URLType="http">
                             http://127.0.0.1:8080/billpayservice/jaxrpc/BillPay
                   </accessPoint>
                 <tModelInstanceDetails/>
             </bindingTemplate>
   </bindingTemplates>
  </businessService>
  </businessServices>
  <categoryBag>
    <keyedReference tModelKey="uuid:C0B9FE13-179F-413D-8A5B-5004DB8E5BB2"
                              keyName="Finance and Insurance" keyValue="52"/>
  </categoryBag>
</businessEntity>
</save_business>
</soap-env:Body>
</soap-env:Envelope>

In response to this request, the registry returns the businessDetail structure, which is the top-level element in the UDDI information model. It is used to represent information about an entity or business, as shown below:

<?xml version="1.0" encoding="UTF-8"?>
<businessDetail generic="2.0" xmlns="urn:uddi-org:api_v2" operator="www.ibm.com/
services/uddi">
    <businessEntity businessKey="25BF1920-D020-11D6-9314-000629DC0A7B"
                    operator="www.ibm.com/services/uddi" authorizedName="100000CTU6">
    <discoveryURLs>
        <discoveryURL useType="businessEntity">
            http://uddi.ibm.com/testregistry/uddiget?businessKey=25BF1920-D020-11D6-
                                                                     9314-000629DC0A7B
        </discoveryURL>
    </discoveryURLs>
    <name xml:lang="en">Flute Bank</name>
    <description xml:lang="en">A fictitious bank used for examples in the book
      Java Web Services Architecture, published by Morgan Kaufman, ISBN 1-55860-900-8.
                      The authors can be reached at webservicesbook@yahoogroups.com OR
                                           http://www.javawebservicesarchitecture.com.
    </description>
    <contacts>
        <contact>
        <description xml:lang="en">The primary contact person for Flute Web services
                                                                        </description>
        <personName>John Malkovich</personName>
        <phone useType="">1-800-FLUTE-US</phone>
        <email>uddiadmin@flutebank.com</email>
        </contact>
    </contacts>
    <businessServices>
        <businessService serviceKey="25E12010-D020-11D6-9314-000629DC0A7B"
                          businessKey="25BF1920- D020-11D6-9314-000629DC0A7B">
        <name xml:lang="en">Billpayservice</name>
        <description xml:lang="en">A Web service allowing account holders to pay bills
                                                                  online</description>
        <bindingTemplates>
            <bindingTemplate bindingKey="2606F790-D020-11D6-9314-000629DC0A7B"
                                    serviceKey="25E12010-D020-11D6-9314-000629DC0A7B">
                <description xml:lang="en">Flute Bank, beyond providing simple
                      account-related services, also has the infrastructure to support
                       online bill payments. The online bill payment system is offered
                                                to customers as a value-added service.
                </description>
                <accessPoint
            URLType="http">http://127.0.0.1:8080/billpayservice/jaxrpc/BillPay
                          </accessPoint>
                <tModelInstanceDetails/>
            </bindingTemplate>
        </bindingTemplates>
        </businessService>
    </businessServices>
    <categoryBag>
    <keyedReference tModelKey="UUID:C0B9FE13-179F-413D-8A5B-5004DB8E5BB2"
                    keyName="Finance and Insurance" keyValue="52"/>
        </categoryBag>
    </businessEntity>
</businessDetail>

Notice that in the businessDetail structure of the response, the registry has assigned the unique identifier to the entity and filled out the businessKey, operator, and authorizedName attributes. It has also assigned a unique discovery URL, where the XML describing the UDDI businessEntity structure for Flute Bank can be accessed.

All this communication and these SOAP messages are transparent to the Java application. The application deals only with the JAXR API and the information model objects contained therein; the provider takes care of the details.

-Dorg.apache.commons.logging.log=org.apache.commons.logging.impl.SimpleLog and
-Dorg.apache.commons.logging.simplelog.defaultlog=debug.

Additionally, using -DuseSOAP=true enables JAXR to switch Soap4J instead of JAXM internally. This can be helpful when using JDK 1.4.

Publishing Service Information to a UDDI Registry

WSDL, with its abstract and concrete sections, was covered in Chapter 5; in Chapter 6, UDDI and how the WSDL elements map to UDDI elements was discussed. Let us now look at how JAXR can be used to publish service descriptions contained in the WSDL programmatically to a registry.

Let us look at the earlier example of the bill payment service. Suppose all the banks in the Good Banking Consortium got together and agreed to have a common bill payment service interface, so that customers of one bank could use the bill payment service of another bank to address a wider merchant account base. They could describe the billpayserviceinterface.wsdl shown in Listing 12.2a. (This is the same WSDL we covered in previous chapters.) Flute Bank could then implement this standard service and expose it as an endpoint. The WSDL is shown in Listing 12.2c. Notice that the schema definitions in billpayservice.wsdl have also been separated into their own XSD file, so that they can be reused across multiple service interfaces. Listing 12.2b shows the schema.

Listing 12.2a: Service interface separated into billpayinterface.wsdl
Start example
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="billpayservice-abstractinterface" targetNamespace="http://
www.flutebank.com/xml" xmlns:tns="http://www.flutebank.com/xml" xmlns="http://
schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap=
"http://schemas.xmlsoap.org/wsdl/soap/">
    <types>
        <schema targetNamespace="billpaydatatypes.xsd" xmlns:wsdl="http://
schemas.xmlsoap.org/wsdl/" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns="http://www.w3.org/2001/XMLSchema"/>
    </types>
    <message name="BillPay_getLastPayment">
        <part name="String_1" type="xsd:string"/>
    </message>
    <message name="BillPay_getLastPaymentResponse">
        <part name="result" type="xsd:double"/>
    </message>
    <message name="BillPay_listScheduledPayments"/>
    <message name="BillPay_listScheduledPaymentsResponse">
        <part name="result" type="tns:ArrayOfPaymentDetail"/>
    </message>
    <message name="BillPay_schedulePayment">
        <part name="Date_1" type="xsd:dateTime"/>
        <part name="String_2" type="xsd:string"/>
        <part name="double_3" type="xsd:double"/>
    </message>
    <message name="BillPay_schedulePaymentResponse">
        <part name="result" type="tns:PaymentConfirmation"/>
    </message>
    <message name="ScheduleFailedException">
        <part name="ScheduleFailedException"
                      type="tns:ScheduleFailedException"/>
    </message>
    <portType name="BillPay">
        <operation name="getLastPayment" parameterOrder="String_1">
            <input message="tns:BillPay_getLastPayment"/>
            <output message="tns:BillPay_getLastPaymentResponse"/>
        </operation>
    <operation name="listScheduledPayments" parameterOrder="">
        <input message="tns:BillPay_listScheduledPayments"/>
        <output message="tns:BillPay_listScheduledPaymentsResponse"/>
    </operation>
    <operation name="schedulePayment"
                              parameterOrder="Date_1 String_2 double_3">
        <input message="tns:BillPay_schedulePayment"/>
        <output message="tns:BillPay_schedulePaymentResponse"/>
        <fault name="ScheduleFailedException"
                   message="tns:ScheduleFailedException"/>
    </operation>
</portType>
<binding name="BillPayBinding" type="tns:BillPay">
    <operation name="getLastPayment">
        <input>
           <soap:body
                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                 use="encoded" namespace="http://www.flutebank.com/xml"/>
        </input>
        <output>
            <soap:body
                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                 use="encoded" namespace="http://www.flutebank.com/xml"/>
        </output>
        <soap:operation soapAction=""/>
    </operation>
    <operation name="listScheduledPayments">
        <input>
            <soap:body
                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                 use="encoded" namespace="http://www.flutebank.com/xml"/>
        </input>
        <output>
            <soap:body
                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                 use="encoded" namespace="http://www.flutebank.com/xml"/>
        </output>
        <soap:operation soapAction=""/>
    </operation>
    <operation name="schedulePayment">
        <input>
                <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                              use="encoded" namespace="http://www.flutebank.com/xml"/>
            </input>
            <output>
                <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                              use="encoded" namespace="http://www.flutebank.com/xml"/>
            </output>
            <fault name="ScheduleFailedException">
                <soap:fault encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                              use="encoded" namespace="http://www.flutebank.com/xml"/>
            </fault>
            <soap:operation soapAction=""/>
        </operation>
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
    </binding>
</definitions>
End example
Listing 12.2b: The schema definition referenced by billpayservice.wsdl
Start example
<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="http://www.flutebank.com/xml" xmlns="http://www.w3.org/2001/
XMLSchema" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://www.flutebank.com/xml"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
    <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
    <complexType name="ArrayOfPaymentDetail">
        <complexContent>
            <restriction base="soap-enc:Array">
                <attribute ref="soap-enc:arrayType" wsdl:arrayType=
"tns:PaymentDetail[]"/>
            </restriction>
        </complexContent>
    </complexType>
    <complexType name="PaymentDetail">
        <sequence>
            <element name="date" type="dateTime"/>
            <element name="account" type="string"/>
            <element name="payeeName" type="string"/>
            <element name="amt" type="double"/>
        </sequence>
    </complexType>
    <complexType name="PaymentConfirmation">
        <sequence>
            <element name="confirmationNum" type="int"/>
            <element name="payee" type="string"/>
            <element name="amt" type="double"/>
        </sequence>
    </complexType>
    <complexType name="ScheduleFailedException">
        <sequence>
            <element name="message" type="string"/>
            <element name="localizedMessage" type="string"/>
        </sequence>
    </complexType>
</schema>
End example
Listing 12.2c: The billpayservice.wsdl implemented by Flute Bank
Start example
<?xml version="1.0" encoding="UTF-8"?>

<definitions name="billpayservice" targetNamespace="http://www.flutebank.com/
billpayservice" xmlns:tns="http://www.flutebank.com/xml" xmlns="http://
schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap=
"http://schemas.xmlsoap.org/wsdl/soap/">

<import namespace="http://www.flutebank.com/xml"
        location="baillpayinterface.wsdl"/>

  <service name="Billpayservice">
    <port name="BillPayPort" binding="tns:BillPayBinding">
      <soap:address
              location="http://127.0.0.1:8080/billpayservice/jaxrpc/BillPay"/>
    </port>
  </service>
</definitions>
End example

In Chapter 5, we mentioned best practices relating to how the WSDL elements should be stored in the registry. The WSDL service interface should be represented as a tModel, so that it can be reused across service implementations. The service and port elements in the service implementation descriptions map to the businessService and bindingTemplate in the UDDI registry. Figure 12.17 shows the mapping of the WSDL elements to the UDDI structures for the BillPay Web service. Figure 12.18 shows the WSDL information as it would appear in the UDDI registry browser.

Click To expand
Figure 12.17: WSDL representation in UDDI
Click To expand
Figure 12.18: WSDL information published in UDDI

All the above mappings can be realized quite easily using JAXR. Let us look at how the WSDL can be published to a UDDI registry and examine the JAXR code for doing so. The JAXR client should:

  1. Connect to the registry and authenticate with the username and password.

  2. Locate the organization in the registry using the BusinessQueryManager. The organization should have been published previously, using either JAXR (previous example) or the provider's Web interface.

  3. Publish the WSDL service interface of the Web service (i.e., the billpayserviceinterface.wsdl) as a tModel. In JAXR terms, this is a Concept with the namespace, description, and a link to the binding element specified in the service interface.

  4. Classify the service interface as a WSDL specification in the UDDI registry. UDDI has defined the type wsdlSpec for this purpose.

  5. Save the Concept and get a key for it. This will correspond to a key for the tModel in UDDI.

  6. Publish the WSDL describing the service implementation (i.e., the billpayservice.wsdl) and reference the tModel used by the service. In JAXR terms, this means creating and saving a Service, the ServiceBinding, and a SpecificationLink object that links the bindings to the Concept in the above step.

  7. Save the Service using the LifeCycleManager.

Note that in the ideal situation, steps 1 to 6 would be performed by the industry consortium (such as the Good Banking Consortium). Flute Bank would perform only step 6 and publish it under the service implementation within its own organization. In most cases today, however, the service interface and description would be published by the same business entity. The code in Listing 12.3 shows details about doing so with JAXR.

Listing 12.3: JAXR application to publish the WSDL
Start example
// imports not shown
public class WSDLPublisher {
      private static final String QUERY_URL =
           "http://www-3.ibm.com:80/services/uddi/v2beta/inquiryapi";
      private static final String PUBLISH_URL =
           "https://www-3.ibm.com:443/services/uddi/v2beta/protect/publishapi";
        private static String uddiusername;
        private static String uddipassword;

/**
 * Main method to publish the WSDL to the UDDI registry
 */
    public static void main(String[] args) {
      if(args.length!=2){
       System.out.println("Usage java UDDIPublish username uddipassword");
          return;
        }
        uddiusername = args[0];
        uddipassword = args[1];
    try{
// Set the properties for the ConnectionFactory
     Properties environment = new Properties();
      environment.setProperty("javax.xml.registry.queryManagerURL",
                                                           QUERY_URL);
      environment.setProperty("javax.xml.registry.lifeCycleManagerURL",
                                                           PUBLISH_URL);
 // Instantiate the factory and create a connection from it
    ConnectionFactory connfactory = ConnectionFactory.newInstance();
    connfactory.setProperties(environment);
    Connection conn = connfactory.createConnection();

        // Authenticate the username and password with the registry
    PasswordAuthentication passwdAuth =
        new PasswordAuthentication(uddiusername, uddipassword.toCharArray());
    Set credentials = new HashSet();
    credentials.add(passwdAuth);
    conn.setCredentials(credentials);
// Obtain a reference to the RegistryService, the BusinessLifeCycleManager,
// and the BusinessQueryManager
    RegistryService registryservice = conn.getRegistryService();
    BusinessLifeCycleManager lifecyclemgr =
                                 registryservice.getBusinessLifeCycleManager();
    BusinessQueryManager querymgr =
                                  registryservice.getBusinessQueryManager();

// First find the organization (this would already be registered from the
// previous examples)
    Collection searchpattern = new ArrayList();
    searchpattern.add("Flute Bank");
    Collection findqualifier= new ArrayList();
    findqualifier.add(FindQualifier.EXACT_NAME_MATCH);
    BulkResponse orgresponse =  querymgr.findOrganizations(findqualifier,
                                        searchpattern, null, null, null, null);
    Collection orgs = orgresponse.getCollection();
    Iterator orgiter= orgs.iterator();
// We don't need to iterate, because we know there is only one organization in the
                                                                              registry
// called Flute Bank
    Organization fluteorg = (Organization) orgiter.next();

// Create a concept for the service interface of the WSDL
    Concept concept=
              lifecyclemgr.createConcept(null," http://www.flutebank.com/xml",null);
    InternationalString conceptdescription =
              lifecyclemgr.createInternationalString("The service interface of the
                                                           bill payment Web service");
    concept.setDescription(conceptdescription);
// Note that the WSDL at this URL must be physically accessible. JAXR will access
//the URL and ensure that the WSDL is valid
    ExternalLink link=lifecyclemgr.createExternalLink(
           "http://127.0.0.1:8080/billpayservice/
billpayserviceinterface.wsdl#BillPayBinding",
           "Wsdl service interface document");
    concept.addExternalLink (link);

// Classify the service interface as the WSDL
    Collection classification=new ArrayList();
    ClassificationScheme uddiOrgTypes =
     querymgr.findClassificationSchemeByName(null, "uddi-org:types");
    Classification wsdlclassification =
       lifecyclemgr.createClassification(uddiOrgTypes, "wsdlSpec", "wsdlSpec");
    classification.add(wsdlclassification);
    concept.setClassifications(classification);

// Save the concept (the UDDI registry will save this as a tModel and return a
// Key to it)
    Collection concepts = new ArrayList();
     concepts.add(concept);
     BulkResponse savedConcepts =lifecyclemgr.saveConcepts(concepts);
     Iterator conceptIterator =savedConcepts.getCollection().iterator();
     if (conceptIterator.hasNext()){
         javax.xml.registry.infomodel.Key key
                     =(javax.xml.registry.infomodel.Key) conceptIterator.next();
         concept.setKey(key);
        System.out.println("tModel key: "+ key.getId());
             }

// the service interface has been saved and the tModel created in the UDDI
// registry
// Create the concrete service (this maps to the businessService)
    Service service = lifecyclemgr.createService("Billpayservice");
    InternationalString servicedescription =
                         lifecyclemgr.createInternationalString("A Web service
allowing account holders to pay bills online");
    service.setDescription(servicedescription);

// Create the service bindings for the Web service
    Collection serviceBindings = new ArrayList();
    ServiceBinding binding = lifecyclemgr.createServiceBinding();
    InternationalString bindingdescription =
                   lifecyclemgr.createInternationalString("HTTP bindings for
                                            the Billpayservice Web service");
    binding.setDescription(bindingdescription);
// replace with the actual URL where the service is deployed
   binding.setAccessURI("http://127.0.0.1:8080/billpayservice/jaxrpc/BillPay");
// Create the specification link for the Web service
   SpecificationLink specLink=lifecyclemgr.createSpecificationLink();
// the concept now has the key created for the tModel
    specLink.setSpecificationObject(concept);
    binding.addSpecificationLink(specLink);
    serviceBindings.add(binding);

// Add the service bindings to service
    service.addServiceBindings(serviceBindings);
// Link the service to the provider
    service.setProvidingOrganization(fluteorg);

// Add the Web service to the list of services, then add the list of services to
// the organization
    Collection servicelist = new ArrayList();
    servicelist.add(service);

// Make the final call to the registry to save the services and get a response
    BulkResponse response = lifecyclemgr.saveServices(servicelist);
    System.out.println("services saved");
    Collection exceptions = response.getExceptions();

// If there are no exceptions, the publish action was successful
    if (exceptions == null){
          Collection keys = response.getCollection();
          Iterator iterator = keys.iterator();
         Key key = (Key) iterator.next();
        String uid = key.getId();
         System.out.println("The unique ID returned by the UDDI registry for the
                                                             Organization is "+ uid);
            }
// This means exceptions occurred during the publish action
    else {
        Iterator iterator = exceptions.iterator();
           while (iterator.hasNext()) {
             Exception exception = (Exception) iterator.next();
              System.out.println("Exception occurred while saving to the registry: "
                                                                        + exception);
            exception.printStackTrace();
                }
            }
// Finally, close the connection
            conn.close();
       } catch (Exception exception) {
        System.out.println("General exception occurred: "+ exception);
        }
   }
}
End example

Although five usage combinations can be derived and are outlined below based on the concept of separating the service interface and service implementation, we believe that usage is currently typically centered around two use cases (items two and three).

  1. Publishing the service interface only. This can be realized as the first part of Listing 12.3.

  2. Publishing the service interface with one service implementation. This is Listing 12.3.

  3. Publishing a complete WSDL document that contains both a service interface and service implementation interface. The realization for this would be identical to Listing 12.3.

  4. Publishing a service implementation definition that uses multiple service interfaces. This would be the case if, for example, Flute Bank decided to implement two services, as shown below:

    <import namespace="http://www.goodbankconsortium.com/xml"
          location="http://www.goodbankconsortium.com/creditcardinterface.wsdl"/>
    <import namespace="http://www.betterbankconsortium.com/xml"
          location="http://www.betterbankconsortium bankacountdebit.wsdl"/>
    
    <service name="Billpayservice">
      <port name="CreditCardBillPayPort" binding="good:BillPayBinding">
        <soap:address
             location="http://www.flutebank.com:8080/billpayservice/CardBillPay"/>
        </port>
     <port name="AccountBillPayPort" binding="better:BillPayBinding">
       <soap:address
        location="http://www.flutebankx.com:8080/billpayservice/AccountBillPay"/>
       </port>
    </service>
    

    The only difference between the realization for this and Listing 12.3 would be multiple ServiceBinding objects associated with the Service.

  5. Publishing an abstract description that references another abstract description. In this case, instead of a Service, another Concept that refers would be created and published.

Querying UDDI Registry with JAXR

We have already covered the case of finding entities in the registry in the previous two examples, where we searched for an organization called Flute Bank and also for classifications.

Steps 1 through 8 remain the same as in the section Publishing Company Information to a UDDI Registry and in Listing 12.1, with one exception. Per the UDDI specifications, no authentication or SSL is needed to query the registry. Let us look at the subsequent steps:

  1. Use the reference to the BusinessQueryManager and one of the find methods (see Figure 12.14) to query the registry. Listing 12.4 queries the registry for an organization whose name must exactly match "Flute Bank." This should return one or more organizations, one of which would be the organization we published in Listing 12.1.

  2. Create a pattern to query on. For the above criteria, this would be FluteBank.

  3. Create the qualifiers for the find operation.

  4. Invoke the findOrganizations method on the BusinessQueryManager.

  5. Parse the BulkResponse object returned from the find method and obtain the collection of Organization objects.

  6. Query each Organization object to obtain details about the primary contact and services registered.

  7. Close the Connection to the registry

    Listing 12.4a shows the code; Listing 12.4b shows the corresponding output.

    Listing 12.4a: Querying organization information from UDDI

    Start example

    import javax.xml.registry.infomodel.*;
    import javax.xml.registry.*;
    import java.util.*;
    
    public class UDDIQueryOrg {
    
    public static void main(String[] args) {
    // Set the properties for the ConnectionFactory
    Properties environment = new Properties();
    environment.setProperty("javax.xml.registry.queryManagerURL", QUERY_URL);
    environment.setProperty("javax.xml.registry.lifeCycleManagerURL", PUBLISH_URL);
    
     // Instantiate the factory and create a connection from it
    ConnectionFactory connfactory = ConnectionFactory.newInstance();
    connfactory.setProperties(environment);
    Connection conn = connfactory.createConnection();
    
    Collection searchpattern = new ArrayList();
    searchpattern.add("Flute Bank");
    
    Collection findqualifier= new ArrayList();
    findqualifier.add(FindQualifier.EXACT_NAME_MATCH);
    
    // Find using the name
    BulkResponse response =  querymgr.findOrganizations(findqualifier,
                              searchpattern, null, null, null, null);
    
    // Display information about the organizations found
    Collection orgs = response.getCollection();
    Iterator orgiterator = orgs.iterator();
    
    while (orgiterator.hasNext()) {
        Organization org =  (Organization) orgiterator.next();
        System.out.println("\t Organization name: " + org.getName().getValue());
        System.out.println("\t Organization description: " +
    org.getDescription().getValue());
        System.out.println("\t Organization uid: " + org.getKey().getId());
    // Display information about the discovery URLs found
        Collection links = org.getExternalLinks();
        Iterator linkiterator = links.iterator();
        while(linkiterator.hasNext()){
            ExternalLink link = (ExternalLink)linkiterator.next();
            System.out.println("\t\t Link URI = " +link.getExternalURI());
           }
    
    // Display information about the discovery URLs found
        Collection classify = org.getClassifications();
        Iterator classifyiterator = classify.iterator();
        while(linkiterator.hasNext()){
           Classification clasf = (Classification)linkiterator.next();
           System.out.println("\t\t Classification value = " +clasf.getValue());
           }
    
    // Display primary contact information
        User pc = org.getPrimaryContact();
        if (pc != null) {
            PersonName pcName = pc.getPersonName();
            System.out.println("\t\t Primary contact name: " +
                                                    pcName.getFullName());
            Collection phNums = pc.getTelephoneNumbers(pc.getType());
            Iterator phIter = phNums.iterator();
            while (phIter.hasNext()) {
            TelephoneNumber num = (TelephoneNumber) phIter.next();
            System.out.println("\t\t Phone number: " + num.getNumber());
            }
            Collection eAddrs = pc.getEmailAddresses();
            Iterator eaIter = eAddrs.iterator();
            while (phIter.hasNext()) {
            System.out.println("\t\tEmail Address: " +
                                             (EmailAddress) eaIter.next());
            }
        }
      }
    }
    
    
    End example

    Listing 12.4b: Output of UDDIQuery

    Start example

    C:\jaxr\jwsa>java UDDIQueryOrg fluteadmin flutepassword
    Organization name: Flute Bank
    Organization description: A fictitious bank used for examples in the book Java Web
       Services Architecture, published by Morgan Kaufman, ISBN 1-55860-900-8. The authors
                                                                         can be reached at
           webservicesbook@yahoogroups.com OR
           www.javawebservicesarchitecture.com.
    Organization uid: 38920050-D028-11D6-9314-000629DC0A7B
         Link URI = http://uddi.ibm.com/testregistry/uddiget?
                      businessKey=38920050-D028-11D6-9314-000629DC0A7B
         Primary contact name: John Malkovich
         Phone number: 1-800-FLUTE-US
    
    End example

Finding Services Information in UDDI

We have looked at how service information can be published. Let us now look at how it can be retrieved from the registry by JAXR client applications. There are two broad use cases for retrieving the WSDL definition:

  • The client knows the organization and wants to retrieve one or more interfaces published by it.

  • The client knows the namespace corresponding to the service.

In the first case, the client must query the registry for a particular organization. It can retrieve this information based on name, classification, external identifiers, and other criteria. The organization can then be queried for the services published under it. Listing 12.5a shows how the WSDL published earlier can be retrieved using the Flute Bank organization name. Listing 12.5b shows its corresponding output.

Listing 12.5a: Querying the registry for service information
Start example
import javax.xml.registry.infomodel.*;
import javax.xml.registry.*;
import java.util.*;
public class UDDIQueryServices {
    private static final String QUERY_URL =
                     "http://www-3.ibm.com:80/services/uddi/v2beta/inquiryapi";

/* Main method */
    public static void main(String[] args) {
    try{

// Set the properties for the ConnectionFactory
      Properties environment = new Properties();
      environment.setProperty("javax.xml.registry.queryManagerURL", QUERY_URL);

// Instantiate the factory and create a connection from it
    ConnectionFactory connfactory = ConnectionFactory.newInstance();
    connfactory.setProperties(environment);
    Connection conn = connfactory.createConnection();

// Obtain a reference to the RegistryService,the BusinessLifeCycleManager,
 //  and the BusinessQueryManager
    RegistryService registryservice = conn.getRegistryService();
   BusinessLifeCycleManager lifecyclemgr =
                            registryservice.getBusinessLifeCycleManager();
   BusinessQueryManager querymgr = registryservice.getBusinessQueryManager();

// prepare the arguments for the find operation
   Collection searchpattern = new ArrayList();
   searchpattern.add("Flute Bank");
   Collection findqualifier= new ArrayList();
    findqualifier.add(FindQualifier.EXACT_NAME_MATCH);

// Find using the name
    BulkResponse response =  querymgr.findOrganizations(findqualifier,
                                        searchpattern, null, null, null, null);

// Display information about the organizations found
// In our case, only one should be returned
    Collection orgs = response.getCollection();
    Iterator orgiterator = orgs.iterator();
   while (orgiterator.hasNext()) {
        Organization org =  (Organization) orgiterator.next();
        System.out.println("Organization name: "+org.getName().getValue());
        System.out.println("Organization uid: " + org.getKey().getId());

//Display service and binding information
        Collection services = org.getServices();
        Iterator svcIter = services.iterator();
        while (svcIter.hasNext()) {
            Service svc = (Service) svcIter.next();
            System.out.println("\t\t Service name: " +
                                              svc.getName().getValue());
            System.out.println("\t\t Service description: " +
                                              svc.getDescription().getValue());
            Collection serviceBindings = svc.getServiceBindings();
            Iterator sbIter = serviceBindings.iterator();
            while (sbIter.hasNext()) {
                ServiceBinding sb =(ServiceBinding) sbIter.next();
                System.out.println("\t\t\t Binding "+
                              "Description: " +sb.getDescription().getValue());
                System.out.println("\t\t\t Access URI: " +
                                                            sb.getAccessURI());
                Collection servicespecs= sb.getSpecificationLinks();
                Iterator servicespecit=servicespecs.iterator();
                while(servicespecit.hasNext()){
                SpecificationLink spec=
                                       (SpecificationLink)servicespecit.next();
            Concept tModel= (Concept)spec.getSpecificationObject();
// get the tModel
                System.out.println("\t\t\t\t Service Interface :"
                                   +tModel.getDescription().getValue());
                Iterator extlinks=tModel.getExternalLinks().iterator();
                while(extlinks.hasNext()){
                    ExternalLink extlink=(ExternalLink)extlinks.next();
                    System.out.println("\t\t\t\t\t Service Interface
                                        location : "+extlink.getExternalURI());
                    System.out.println("\t\t\t\t\t Location
                                               description:"
                                         +extlink.getDescription().getValue());
                        }
                }
            }
        }
    }
// Finally, close the connection
    conn.close();
  } catch (Exception exception) {
     System.out.println("General exception occurred: " + exception);
            }
        }
    }
End example
Listing 12.5b: Client side output of a service query
Start example
C:\jaxr\jwsa>java UDDIQueryServices flutebank fluteadmin
Organization name: Flute Bank
Organization uid: 46F5D8A0-D3D5-11D6-8370-000629DC0A7B
   Service name: Billpayservice
    Service description: A Web service allowing account holders to pay bills online
          Binding Description: HTTP bindings for the
                                 Billpayservice Web service
          Access URI: http://127.0.0.1:8080/billpayservice/jaxrpc/BillPay
                Service Interface: The service interface of the bill payment Web
                                                                               service
                Service Interface location:
http://127.0.0.1:8080/billpayservice/billpayserviceinterface.wsdl#BillPayBinding
                 Location description: Wsdl service interface document
End example

In the second case, the client can query the registry based on the namespace declaration from the WSDL defining the service interface. The namespace corresponds to the name of the concept (i.e., the tModel name) classified with the wsdlSpec in UDDI, as shown earlier. This may be helpful in two cases:

  • The parties can agree upon the namespace as part of the service level agreement between them.

  • The client may want to query the registry to find service implementation based on service interfaces defined by industry verticals. For example, we mentioned earlier how the Good Banking Consortium may define the BillPay service implemented by Flute. The namespace of this service interface will be that as defined by the consortium.

Listing 12.6a shows how the service can be queried on namespace. Listing 12.6b shows the corresponding output.

Listing 12.6a: Service discovery based on namespace
Start example
import javax.xml.registry.*;
import javax.xml.registry.infomodel.*;
import java.util.*;

public class UDDIQueryServicesByNamespace {
private static final String QUERY_URL="http://uddi.microsoft.com:80/inquire";

/* Main method of the class*/
    public static void main(String[] args) {
    try{
// Set the properties for the ConnectionFactory
    Properties environment = new Properties();
    environment.setProperty("javax.xml.registry.queryManagerURL", QUERY_URL);
// Instantiate the factory and create a connection from it
    ConnectionFactory connfactory = ConnectionFactory.newInstance();
    connfactory.setProperties(environment);
    Connection conn = connfactory.createConnection();
// Obtain a reference to the RegistryService,the BusinessLifeCycleManager
//  and the BusinessQueryManager
    RegistryService registryservice = conn.getRegistryService();
    BusinessLifeCycleManager lifecyclemgr =
                                 registryservice.getBusinessLifeCycleManager();
    BusinessQueryManager querymgr =
                                     registryservice.getBusinessQueryManager();

// prepare the parameters for the find operation
    Collection findqualifier= new ArrayList();
    findqualifier.add(FindQualifier.EXACT_NAME_MATCH);

// WSDL tModels must be classified under the wsdlSpec classification in UDDI
    Collection  classifications = new ArrayList();
    ClassificationScheme uddiOrgTypes =
               querymgr.findClassificationSchemeByName(null, "uddi-org:types");
    Classification wsdlSpecClassification =
       lifecyclemgr.createClassification(uddiOrgTypes, "wsdlSpec", "wsdlSpec");
    classifications.add(wsdlSpecClassification);
// WSDLs corresponding to this namespace
    Collection searchpattern = new ArrayList();
    searchpattern.add("%http://www.flutebank.com/xml%");

// find the Concepts (i.e., the tModels)
    BulkResponse response = querymgr.findConcepts(null, searchpattern,
                                                classifications, null, null);
    Collection specConcepts = response.getCollection();
    Iterator iter = specConcepts.iterator();
    while (iter.hasNext()) {
    try {
        Concept concept = (Concept)iter.next();
        String name = concept.getName().getValue();
        Collection extlinks = concept.getExternalLinks();
        System.out.println("WSDL :\n\t Namespace: " + name +
            "\n\t Key: " + concept.getKey().getId() +
        "\n\t Description: " + concept.getDescription().getValue());
        Iterator linkiter=extlinks.iterator();
        while(linkiter.hasNext()) {
        ExternalLink link = (ExternalLink)linkiter.next();
        System.out.println("\t WSDL location : " + link.getExternalURI());
        }
    // Find all the organizations using this WSDL definition
       Collection tmodels = new ArrayList();
       tmodels.add(concept);
       response = querymgr.findOrganizations(null, null, null, tmodels, null, null);
       Collection orgs = response.getCollection();
       Iterator orgIter = orgs.iterator();
       if (orgIter.hasNext())
             System.out.println("Organizations using the " + name + " WSDL
                                                                      namespace:");
       else
           System.out.println("No Organizations using the WSDL " + name);
                                                          while (orgIter.hasNext()) {
           Organization org = (Organization)orgIter.next();
           System.out.println("\t Name: " + org.getName().getValue() +
               "\n\t Key: " + org.getKey().getId() +
               "\n\t Description: " + org.getDescription().getValue());
               }
        }catch (JAXRException e) {
            e.printStackTrace();
            }
        }
        } catch (JAXRException e) {
              e.printStackTrace();
            }
      }
}
End example
Listing 12.6b: The client side output
Start example
C:\jaxr\jwsa>java UDDIQueryServicesByNamespace
WSDL :
   Namespace: http://www.flutebank.com/xml
   Key: UUID:67191F10-D3D6-11D6-8370-000629DC0A7B
   Description: The service interface of the bill payment Web service
WSDL location:
http://127.0.0.1:8080/billpayservice/billpayserviceinterface.wsdl#BillPayBinding
Organizations with service implementations for namespace www.flutebank.com/xml
   Name: Flute Bank
   Key: 46F5D8A0-D3D5-11D6-8370-000629DC0A7B
   Description: A fictitious bank used for examples in the book Java Web Services
Architecture, published by Morgan Kaufman, ISBN 1-55860-900-8. The authors can be
     reached at webservicesbook@yahoogroups.com OR
     http://www.javawebservicesarchitecture.com.
End example

Runtime Service Discovery from UDDI

We have just looked at how the service information can be published and retrieved from the UDDI registry. In Chapter 2, we talked about the register-find-bind scenario for Web services. In most cases, service consumers will locate the WSDL and generate the client-side code in Java or other languages for consuming that service.

In Chapter 9, we looked at how to do this for both Java and C#. This is a typical use of the static compile-time binding pattern discussed in Chapter 5. In most cases, clients will not look up the UDDI registry at runtime for this information, because the WSDL published in the registry will be part of some service level or business agreement and will not be expected to change often.

We also discussed the second static deploy-time binding pattern, where the portType is known but the location is retrieved at runtime. Let us look at a strategy for implementing this pattern:

  1. Design-time tools can discover the service in the UDDI registry and retrieve its service interface and the service implementation. Though we looked at how to do this programmatically with JAXR, we envision that vendor-provided tools will perform this task at design time, using APIs such as those provided by JSR-110 (Java API for WSDL) in combination with JAXR.

  2. Either way, the client application will have complete service information described by the JAXR Service and ServiceBinding (containing the key), Concept, and ExternalLink. It can then store the ServiceBinding key, which corresponds to the UDDI bindingKey in some configuration variable.

  3. When the client is executed, it can use this stored ServiceBinding key to retrieve the ServiceBinding information from the BusinessQueryManager. For example:

    BulkResponse response=querymgr.findServiceBindings(serviceKey,null,null,null);
    

    We have already discussed this static deploy-time pattern earlier but clearly this can be useful if:

    • The service location changes.

    • The client is created and distributed by the service provider to different service consumers.

    • The service invocation fails, at which time the client can query the registry for a mirror location for the same service defined by the service provider.

Deployment-Time Publication to UDDI

Though we have discussed how information can be published progammatically to the registry, it is quite common for an enterprise to follow an administrator-driven approach during application deployment into production environments Here, for example, a designated person is responsible for publishing information in the UDDI registry using the browser-based interface. This also makes sense, because information such as company address, contact information, and service location is expected to remain static and is included as part of the service level agreements forged with business partners.


Previous Section Next Section


JavaScript Editor Java Tutorials Free JavaScript Editor