Web services provide a new paradigm for distributed computing. The promise of invoking Web services dynamically based on descriptions stored in WSDL is very powerful. As Web service users become more sophisticated, the next challenge will be how to find or discover the existence of services that may be of interest. As the Web services invocations become more automated, it is important to have a mechanism to be able to discover Web services in a predictable, repeatable way that can be implemented programmatically.
Universal Description, Discovery and Integration (UDDI) provides such a mechanism. Defined as a Web service itself, UDDI allows businesses and their services to be registered in a UDDI registry. A registered service can include descriptive information such as WSDL and can be categorized in an arbitrary number of ways. Categorization of the Web service allows sophisticated searches to be used to find the most desirable service.
UDDI is defined as a set of XML messages that can be sent and received from a UDDI registry. UDDI4J is a client Java API implementation used to interact with a UDDI registry. UDDI4J objects and methods are used to construct a request message and to send it to a registry. Likewise, UDDI4J interprets response messages from a UDDI registry and presents a set of objects and methods used to access the response message.
UDDI4J version 1 was released to coincide with the original release of the public UDDI Business Registry (UBR). UDDI has continued to evolve, and with it UDDI4J. The UDDI version 2 specification has been available for several months along with beta registries. The public UDDI Business Registry now has support for version 2 of the UDDI specification. UDDI4J version 2 was released as a beta in November 2001 and than released as non-beta in July 2002. This new UDDI4J release adds support for the new features within the specification as well as additional usability and configuration improvements.
UDDI4J was originally released by IBM in January 2001 as an open source project on developerWorks with participation by other companies and individuals encouraged. For version 2, HP joined as a major participant in the evolution of UDDI4J and contributed much of the UDDI version 2 enhancements. With the active support and endorsement of IBM, HP, and SAP, UDDI4J has become the default Java API for UDDI interaction.
As UDDI continues to evolve to meet the needs of the growing Web services community, UDDI4J will continue to track those changes.
UDDI4J is organized into a variety of packages. org.uddi4j.client.UDDIProxy is the primary class used to interact with a UDDI registry. It represents a proxy for the UDDI registry with which communication will take place. UDDIProxy provides methods which map very closely to the API defined within the UDDI specification. Parameters are typically data objects that represent various elements within UDDI.
Many of the API calls return org.uddi4j.response.DispositionReport to indicate the success or failure of the operation. Some calls may throw org.uddi4j.UDDIException to indicate an error condition. Depending on the nature of the error, a UDDIException may contain a DispositionReport with more information about the error.
The UDDI API is divided into an inquiry and publish API. These APIs use separate URLs. The publish URL typically specifies an https address using SSL. When using SSL within Java programming language, a JSSE provider must be defined and added to the set of security managers. The following code fragment enables SSL using the Sun's Java technology JSSE package. The security provider can also be added by modifying the jdk/jre/lib/security/java.security configuration file.
System.setProperty("java.protocol.handler.pkgs",
"com.sun.net.ssl.internal.www.protocol");
java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
|
UDDIProxy requires that both an inquiry and publish URL be specified. Once set, all method invocations use these URLs unless the values are modified. When using the publish API, a userid and password is required. These are typically obtained by creating an account through a Web site associated with the chosen registry.
The following code fragment is a typical setup step required for code which uses the publish API.
// Construct a UDDIProxy object
UDDIProxy proxy = new UDDIProxy();
try {
// Select the desired UDDI server node
proxy.setInquiryURL("inquiryURL");
proxy.setPublishURL("publishURL");
// Pass in userid and password registered at the UDDI site
AuthToken token = proxy.get_authToken("userid", "password");
...
} catch (UDDIException e) {
...
|
There are a number of significant changes to UDDI4J version 2 that include both support for those in the version 2 specification and enhancements that improve the behavior of UDDI4J but are unrelated to the specification.
- Support for UDDI version 2 features, including:
- business relationships
- service projections
- enhanced inquiry
- internationalization features
- Enhancements unrelated to UDDI version 2:
- package name change
- pluggable transports
- debug logging
- collection class enhancements
UDDI version 2 has modified some existing message APIs and changed the version identifier on all incoming and outgoing messages. The result is some incompatibility between UDDI version 2 and version 1. UDDI version 2 registries are able to accept both version 1 and version 2 messages. However, version 1 registries are not able to handle version 2 messages.
UDDI4Jv2 generates and handles version 2 messages only, and does not support version 1 messages. UDDI4Jv1 can be used to send and receive version 1 messages. Both UDDI4Jv1 and version UDDI4Jv2 can be used at the same time within the same JVM to allow communication with version 1 or 2 registries. It is not anticipated that many version 1 registries will remain in operation as most will be upgrading to support version 2.
As a further commitment to open source, the package name for UDDI4J has been changed from com.ibm.uddi to org.uddi4j. Likewise a new Web site has been defined, http://www.uddi4j.org, to host releases and information about the project. Mailing lists are available for general questions and for participation in the development of UDDI4J.
An expanded set of samples is provided with UDDI4J version 2. Some of the more mundane setup tasks have been simplified using a configurator class to establish the SSL provider, set the URLs, etc. from information provided in a property file. Information about the current public registry URLs has been removed from the samples given the expanded set of vendors providing registries. A list of the more common registry URLs is available under the 'Links' topic at the http://www.uddi4j.org site.
UDDI4J version 2 adds configuration options which are set using properties. These properties can be specified as system properties or, if needed, they can be set within a properties object and passed to UDDIProxy in a new constructor. If multiple copies of UDDI4J are needed within the same JVM, this new constructor allows a mechanism to configure the environment from a property file and allows each copy of UDDI4J to run with a different configuration. Using system properties is a simpler and more straightforward approach to configuring UDDI4J.
System properties can be set in code or on the command line as follows:
java -DpropertyName=propertyValue
UDDI4Jv2 adds support for pluggable transport layers. UDDI4Jv1 required used of Apache SOAP. Additional SOAP implementations have appeared since the first release. An abstraction and factory layer has been created so that multiple SOAP transport providers can be supported. The Apache SOAP project has been superseded by the follow on Apache Axis project. HP, a major contributor to UDDI4Jv2, also provides a SOAP transport. These three SOAP transports are supported by UDDI4Jv2. Apache SOAP remains the default transport. Use of an alternate transport can be specified by setting the following property,
org.uddi4j.TransportClassName=transport_class_name |
The specified transport class name can be one of the following included transports or a third party provided SOAP transport.
- org.uddi4j.transport.ApacheSOAPTransport (the default)
- org.uddi4j.transport.ApacheAxisTransport
- org.uddi4j.transport.HPSOAPTransport
Communication errors which originate from the transport result in a org.uddi4j.transport.TransportException being thrown. This exception wrappers a transport specific exception that may contain additional detail.
UDDI4J has added the ability to log incoming and outgoing messages. This is very useful when diagnosing communications problems with UDDI registries. Output is enabled by setting the following system property:
org.uddi4j.logEnabled=true |
Logging is supported by all of the SOAP transports. The HP SOAP transport has additional properties that can be used to determine the log destination.
Proxies are often used to communicate through a firewall to allow communication from a company's intranet to the Internet. Proxies can be HTTP or socks. UDDI4J now supports commonly used Java properties to define HTTP and socks proxy to allow communication through a firewall. The required values are dependent on the company's network configuration and can be obtained from your network administrator. UDDI4J handles passing the basic set of http proxy properties to the underlying transport. Properties supported include:
http.proxyHost- The hostname of the proxy server.http.proxyPort- Port used by the proxy server, defaults to 80.https.proxyHost- Hostname of the proxy server if different from the http proxyhost.https.proxyPort- Port used for SSL by the proxy server, defaults to 80.http.proxyUserName- If your proxy server requires authentication, specify the username.http.proxyPassword- Specify the matching password if a proxy username is given.
The following proxy related properties are directly supported by the JDK and included for completeness.
socksProxyHost- Hostname of the socks proxy server.socksProxyPort- Portname of the socks proxy server.
Many UDDI4J classes directly map one to one with elements defined in the UDDI schema. In UDDI4J v1, this resulted in several classes that sounded like collection classes but were in fact only containers for real collections. UDDI4J v2 has improved the usability of these classes by adding a set of collection class methods to these classes. More complex classes that contain attributes as well as a collection have not been enhanced with these methods.
The methods that have been added are:
public void add(KeyedReference) public boolean remove(KeyedReference) public KeyedReference get(int index) public int size() |
The following classes have been modified to include these new methods:
util.IdentifierBag collection of KeyedReferences util.CategoryBag collection of KeyedReferences util.DiscoveryURLs collection of DiscoveryURL objects util.FindQualifiers collection of FindQualifier objects util.TmodelBag collection of Tmodel objects response.BusinessInfos collection of BusinessInfo objects response.PublisherAssertions collection of PublisherAssertion objects response.RelatedBusinessInfos collection of RelatedBusinessInfo objects response.ServiceInfos collection of ServiceInfo objects response.TmodelInfos collection of TmodelInfo objects datatype.binding.BindingTemplates collection of BindingTemplate objects datatype.binding.TModelInstanceDetails collection of TmodelInstanceInfo objects datatype.business.Contacts collection of Contact objects datatype.service.BusinessServices collection of BusinessService objects |
A new constructor has also been provided for the KeyedReference class to allow it to be constructed by supplying all its attributes.
public KeyedReference(String keyName, String keyValue, String tModelKey)
The following examples illustrate adding a keyed reference to an identifier bag with and without using the new methods.
Using the old process the following code was required:
Vector ibVector = new Vector();
KeyedReference kr1 = new KeyedReference("name", "value");
kr1.setTModelKey("tmodelKey");
ibVector.add(kr1);
IdentifierBag ib = new IdentifierBag();
// The identifierbag is not really a collection, simply a container for a vector
ib.setKeyedReferenceVector(ibVector);
|
With the new collection class methods, this has been simplified to:
KeyedReference kr1 = new KeyedReference("name", "value", "tmodelKey");
IdentifierBag ib = new IdentifierBag();
// New identifierBag method, it now acts like a simple collection class
ib.add(kr1);
|
UDDI version 2 changes: Business relationships
UDDI version 2 adds modeling support for complex organizations. The concept of business relationships is the largest single change in UDDI version 2 that affects UDDI4J. Large organizations had been using UDDI and encountered issues regarding representation of divisions or portions of their businesses. Typically each division would create their own UDDI business entity, however there was no easy way to establish a relationship to indicate that these various businesses were really part of the same overall business. UDDI version 2 has added an ability to add this relationship. Most of the changes reflected in UDDI4J are related to this capability of expressing relationships between businesses.
Two new UDDI constructs have been added to handle these relationships: publisher assertions and service projections. A publisher assertion is an assertion made by the publisher of a business that a relationship exists between two businesses. A relationship is established between two businesses when each publisher asserts the same relationship. When the UDDI registry receives one assertion, it places the relationship in a pending state. When a matching assertion is received by the publisher of the other business, the business relationship is established. Three relationship types have been defined. A parent-child relationship describes a hierarchical association such as a subsidiary or division. Peer-peer relationships represent an association where neither business is considered the parent. An identity relationship indicates that both business entities represent the same business, similar to creating an alias for the business.
Once two businesses have an established relationship, services that have been defined in one of those businesses can be referenced from the other business. When the other business's service appears within a business, it is known as a service projection. The public UDDI v2 business registry does not currently support service projections. This support will be added at a later date.
UDDI4J closely follows the UDDI specification when implementing the API. The best and only reference required to understand UDDI4J is the UDDI specification itself available from the UDDI organization site (see Resources). Appendix J in the UDDI version 2 specification has a reference on using business relationships.
The following new APIs related to business relationships have been defined within UDDI version 2. These APIs are represented within UDDI4J as new methods on the UDDIProxy class.
RelatedBusinessesList find_relatedBusinesses (FindQualifiers findQualifiers,
String businessKey
KeyedReference keyedReference);
DispositionReport add_publisherAssertions (String authInfo,
PublisherAssertion publisherAssertion);
DispositionReport add_publisherAssertions (String authInfo,Vector publisherAssertion);
DispositionReport delete_publisherAssertions (String authInfo,
PublisherAssertion publisherAssertion);
DispositionReport delete_publisherAssertions (String authInfo,Vector publisherAssertion);
AssertionStatusReport get_assertionStatusReport (String authInfo,
CompletionStatus completionStatus);
AssertionStatusReport get_assertionStatusReport (String authInfo,
String completionStatus);
PublisherAssertions get_publisherAssertions (String authInfo);
PublisherAssertions set_publisherAssertions (String authInfo,Vector publisherAssertion);
PublisherAssertions set_publisherAssertions (String authInfo,PublisherAssertion pub);
|
The following example illustrates how the first publisher creates a publisher assertion. A keyed reference is created which describes the relationship to be formed. The key value indicates the type of relationship being asserted. Defined value types are peer-peer, parent-child, or identity and are defined in the UDDI data structures specification. When using parent-child, the from key represents the parent business and to key represents the subsidiary. To create a publisher assertion, two publishers are required, each with its own registry userid.
// Follows example in v2 spec appendix J
KeyedReference kr = new KeyedReference("Holding Company", // Key name
"parent-child", // Key value
TModel.RELATIONSHIPS_TMODEL_KEY);// Tmodelkey
PublisherAssertion pa = new PublisherAssertion(bk1, // from key
bk2, // to key
kr); // keyed reference
// Add publisher assertion linking two businesses
DispositionReport dr = proxy.add_publisherAssertions(token1.getAuthInfoString(),pa);
|
When one publisher adds an assertion, the registry places the relationship in a pending state, waiting for the affected business to make the identical assertion in response, indicating that both parties agree to the relationship assertion. The second publisher reciprocates by adding the same assertion. Once both parties have asserted the same relationship, the UDDI registry will create the business relationship. In this fragment, a query is performed to find pending assertions affecting this publisher. The business keys from the assertion report are used to recreate the matching original assertion.
// List available assertions (relationships)
AssertionStatusReport asr = proxy.get_assertionStatusReport(token2.getAuthInfoString(),
CompletionStatus.TOKEY_INCOMPLETE);
Vector v = asr.getAssertionStatusItemVector();
for (int i = 0; i < v.size(); i++) {
AssertionStatusItem asi = (AssertionStatusItem)v.elementAt(i);
PublisherAssertion pa = new PublisherAssertion(asi.getFromKeyString(),
asi.getToKeyString(),
asi.getKeyedReference());
DispositionReport dr = proxy.add_publisherAssertions(pa);
}
|
Note that service projections are not supported by the public UDDI Business Registry at the time this article was written. This information is provided for future reference.
In the following fragment, the second publisher creates a service projection. A query is performed on the related (first) business that contains the service to be projected. The BusinessService object is stored, and later used in a save_business() call to add this service to the second business as a projection.
BusinessDetail bd1 = proxy.get_businessDetail(bk1);
BusinessEntity be1 = (BusinessEntity)bd1.getBusinessEntityVector().elementAt(0);
BusinessServices bss1 = be1.getBusinessServices();
BusinessService serviceProjection = bss1.get(0); // Desired service
// Update a business and include the service projection
BusinessDetail bd2 = proxy.get_businessDetail(bk2);
BusinessEntity be2 = (BusinessEntity)bd2.getBusinessEntityVector().elementAt(0);
BusinessServices bs = new BusinessServices();
bs.add(serviceProjection);
be2.setBusinessServices(bs);
Vector entities = new Vector();
entities.addElement(be2);
proxy.save_business(token2.getAuthInfoString(),entities);
|
Services can be examined to determine if they are projections using the following code. In this example, information regarding a business entity is retrieved, including a list of its services. The services can be examined to determine if they are native to that business or belong to the related business. Services which are projected will specify the businesskey of the business they are projected from, rather than the business being queried.
// How to look at services and see if one is a service projection
BusinessDetail bd = proxy.get_businessDetail("businessKey");
BusinessEntity be = (BusinessEntity)bd.getBusinessEntityVector().elementAt(0);
BusinessServices bss = be.getBusinessServices();
for (int i = 0; i < bss.size(); i++) {
BusinessService bs = bss.get(i);
String businessKey = bs.getBusinessKey();
if (!businessServiceKey.equals(businessKey)) {
System.out.println("Service " + bs.getName() + " is a projection");
}
}
|
Several descriptive strings are implemented as objects to allow language specific identifiers. UDDI handles internationalization by allowing the user to specify a collection of these objects where each object has a value and a language identifier. If a single value is provided, the language identifier defaults to a language determined by the registry at the time the publisher account was created, typically English. Language values are those allowed for the xml:lang attribute, specified in RFC 1766.
A common source of confusion is thinking that multiple values are concatenated to allow for a longer string. This is not the case. Each provided object is unique to a language. It is a usage error to specify more than one object with the same (or missing) language identifier. UDDI4J does not validate the values. An error will be generated from the UDDI registry.
New NLS capabilities have been added with the addition of a language identifier to the Name class.
Name(string, language)
The find_business and find_service methods on UDDIProxy now accept a collection of 'Name' objects rather than a single value.
The org.uddi4j.datatype.Description class available since UDDI version 1 has similar behavior and usage.
Query operations have been consolidated so that a single find_business() call can be used to search based on DiscoveryURLs, IdentifierBag, CategoryBag and TmodelBag without having to cycle through multiple searches.
The new signature for the find_business() method on UDDIProxy is:
BusinessList find_business (FindQualifiers findQualifiers,
Vector names,
DiscoveryURLs discoveryBag,
IdentifierBag identifierBag,
CategoryBag categoryBag,
TmodelBag tModelBag
Int maxRows);
|
Additional findQualifiers have also been added as documented in the UDDI v2 specification.
This article has summarized the changes that have gone into UDDI4J version 2, package name and samples changes, ability to specify a SOAP transport, support for debug logging, including enhanced usability, support for UDDI version 2, configuration capabilities including choosing which SOAP transport to use, debug logging, proxy, usability enhancements, and of course, support for UDDI version 2. The UDDI version 2 concepts of business relationships and service have been discussed and code fragments presented. Given this information, you are now armed with information to be able to use UDDI4J to further explore UDDI version 2.
More detailed information on the changes between version 1 and version 2 can be obtained by consulting the UDDI version 2 specification and follow on errata. Latest news and releases related to UDDI4J can be found on uddi4j.org
- Read Doug Tidwell's UDDI4J: Matchmaking for Web services.
- The UDDI4J project site.
- The UDDI organization site
- developerWorks article "Understanding UDDI: Tracking the evolving specification" by Tom Bellwood
- Read the three part developerWorks series on WSDL/UDDI mapping, "Understanding WSDL in a UDDI registry" parts 1, 2, and 3.
- Check out this uddi.org white paper on WSDL/UDDI mapping, Using WSDL in a UDDI Registry, Version 1.07: UDDI Best Practice.
David Melgar has had a diverse career with a background in the retail industry, systems management, Java technology, and Web services. The original author of UDDI4J, David is a member of the Emerging Technologies division of IBM software group, and is currently focusing on Web services security within the Web Services Toolkit. You can contact David at dmelgar@us.ibm.com.
Comments (Undergoing maintenance)





