JaVa
   

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 apps 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 Screenshot 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.

Java Click To expand
Screenshot: JAXR API

JAXR and Connections

The first few step in any JAXR app is to establish a connection to the underlying registry, which is abstracted with a RegistryService interface. In general, all JAXR apps 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 , 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.

Java Start Sidebar

Tomcat 4.1 and above can be enabled to use JNDI with some effort; see details at http://jakarta.apache.org/tomcat/tomcat-4.1-doc/index.html.

Java End Sidebar

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 apps 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 Screenshot primarily abstracts all these operations, which are shown in Screenshot. The two lifecycle managers contain overloaded methods for:

Java Click To expand
Screenshot: 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 app 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 Screenshot 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.

Java Click To expand
Screenshot: 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:

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 (Screenshot). 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);


Java Click To expand
Screenshot: The DeclarativeQueryManager for level 1 providers
Java Start Sidebar

The relational schema definition for SQL queries required by the ebXML Registry Service can be found at www.oasis-open.org/committees/regrep/documents/2.0/sql/database.sql. The stored procedures that must be supported by the SQL query feature are defined at www.oasis-open.org/committees/regrep/documents/2.0/sql/storedProcedures.sql.

Java End Sidebar

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.

Java Start Sidebar

The relational schema definition for SQL queries required by the ebXML Registry Service can be found at www.oasis-open.org/committees/regrep/documents/2.0/sql/database.sql. The stored procedures that must be supported by the SQL query feature are defined at www.oasis-open.org/committees/regrep/documents/2.0/sql/storedProcedures.sql.

Java End Sidebar

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 Screenshot.

Java Click To expand
Screenshot: Flute Bank as registered in the IBM UDDI registry Listing 12.1: Publishing organization information
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 tutorial Java Web Services Architecture,
 "+ "shared by Morgan Kaufman, ." +
"The authors can be reached at webservicesbook@bugmenot.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@bugmenot.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);
 }
 }
}



Java End example
Java Start Sidebar

Remember that although we are publishing to a UDDI registry, developers using JAXR never have to do anything UDDI-specific. JAXR providers take care of all the wiring under the hood.

Java End Sidebar

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" user 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 tutorial
 Java Web Services Architecture, shared by Morgan Kaufman, 
 1-55860-900-8. The authors can be reached at webservicesbook@bugmenot.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@bugmenot.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" authorized >
 <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 tutorial
 Java Web Services Architecture, shared by Morgan Kaufman, .
 The authors can be reached at webservicesbook@bugmenot.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@bugmenot.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 app. The app deals only with the JAXR API and the information model objects contained therein; the provider takes care of the details.

Java Start Sidebar

Because publication to UDDI happens over SSL, the SOAP messages cannot be captured on the wire using HTTP tools. JAXR debugging can be enabled by using the options

Java End Sidebar
-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 ; in , 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.

Java Start Sidebar

The service interface consists of the abstract description (types, messages, operations, portTypes, and elements) and a protocol binding (binding element), which describe the Web service interface. The service implementation consists of the imported service interface and the WSDL service element, which describe port implementation details, such as location. Typically, the service interface and the service implementation can and should be defined in different WSDL documents. The rationale behind this from the UDDI consortium is that different industry verticals will define a set of service interfaces that will be made publicly available. Organizations will then build services that conform to these industry-standard specifications (i.e., the abstract definition and the protocol binding for the service), implement them, and expose the endpoints. These recommendations from the UDDI consortium can be found at www.uddi.org/bestpractices.html.

Java End Sidebar

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
<?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 type="xsd:double"/>
 </message>
 <message name="BillPay_listScheduledPayments"/>
 <message name="BillPay_listScheduledPaymentsResponse">
 <part 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 type="tns:PaymentConfirmation"/>
 </message>
 <message >
 <part 
 type="tns:ScheduleFailedException"/>
 </message>
 <portType >
 <operation parameterOrder="String_1">
 <input message="tns:BillPay_getLastPayment"/>
 <output message="tns:BillPay_getLastPaymentResponse"/>
 </operation>
 <operation parameterOrder="">
 <input message="tns:BillPay_listScheduledPayments"/>
 <output message="tns:BillPay_listScheduledPaymentsResponse"/>
 </operation>
 <operation 
 parameterOrder="Date_1 String_2 double_3">
 <input message="tns:BillPay_schedulePayment"/>
 <output message="tns:BillPay_schedulePaymentResponse"/>
 <fault 
 message="tns:ScheduleFailedException"/>
 </operation>
</portType>
<binding type="tns:BillPay">
 <operation >
 <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 >
 <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 >
 <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 >
 <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>



Java End example
Listing 12.2b: The schema definition referenced by billpayservice.wsdl
<?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 >
 <complexContent>
 <restriction base="soap-enc:Array">
 <attribute ref="soap-enc:arrayType" wsdl:arrayType=
"tns:PaymentDetail[]"/>
 </restriction>
 </complexContent>
 </complexType>
 <complexType >
 <sequence>
 <element type="dateTime"/>
 <element type="string"/>
 <element type="string"/>
 <element type="double"/>
 </sequence>
 </complexType>
 <complexType >
 <sequence>
 <element type="int"/>
 <element type="string"/>
 <element type="double"/>
 </sequence>
 </complexType>
 <complexType >
 <sequence>
 <element type="string"/>
 <element type="string"/>
 </sequence>
 </complexType>
</schema>



Java End example
Listing 12.2c: The billpayservice.wsdl implemented by Flute Bank
<?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 >
 <port binding="tns:BillPayBinding">
 <soap:address
 location="http://127.0.0.1:8080/billpayservice/jaxrpc/BillPay"/>
 </port>
 </service>
</definitions>



Java End example

In , 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. Screenshot shows the mapping of the WSDL elements to the UDDI structures for the BillPay Web service. Screenshot shows the WSDL information as it would appear in the UDDI registry browser.

Java Click To expand
Screenshot: WSDL representation in UDDI Java Click To expand
Screenshot: 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 shared by the same business entity. The code in Listing 12.3 shows details about doing so with JAXR.

Listing 12.3: JAXR app to publish the WSDL
// imports not shown
public class WSDLuploader {
 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);
 }
 }
}



Java End example
Java Start Sidebar

By default, JAXR will download and verify that the WSDL is available at the URLs when publishing. The validation can be bypassed by using the setValidateURI(false) method.

Java End Sidebar

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 >
     <port binding="good:BillPayBinding">
     <soap:address
     location="http://www.flutebank.com:8080/billpayservice/CardBillPay"/>
     </port>
     <port 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 Screenshot) 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
    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());
     }
     }
     }
    }
    
    
    


    Java End example
    Listing 12.4b: Output of UDDIQuery
    C:\jaxr\jwsa>java UDDIQueryOrg fluteadmin flutepassword Organization name: Flute Bank Organization description: A fictitious bank used for examples in the tutorial Java Web
     Services Architecture, shared by Morgan Kaufman, . The authors
     can be reached at
     webservicesbook@bugmenot.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
    
    


    Java 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 apps. There are two broad use cases for retrieving the WSDL definition:

  • The client knows the organization and wants to retrieve one or more interfaces shared 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
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);
 }
 }
 }



Java End example
Listing 12.5b: Client side output of a service query
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



Java 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
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();
 }
 }
}



Java End example
Listing 12.6b: The client side output
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 tutorial Java Web Services Architecture, shared by Morgan Kaufman, . The authors can be
 reached at webservicesbook@bugmenot.com OR
 http://www.javawebservicesarchitecture.com.



Java 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 , 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 , 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 . 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 app 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 app 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.


JaVa
Comments