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:

  • The BusinessLifeCyleManager interface, used for creating objects based on the information model

  • The BusinessQueryManager interface, used to query the registry using objects from the information model

  • The DeclarativeQueryManager interface, used to execute statement type queries on the registry

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.

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.

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

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.

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.

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.

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

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.

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

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

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

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.

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

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

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.

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




Java Web Services Architecture
Java Web Services Architecture (The Morgan Kaufmann Series in Data Management Systems)
ISBN: 1558609008
EAN: 2147483647
Year: 2005
Pages: 210

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net