Level: Introductory Peter Brittenham (peterbr@us.ibm.com), Web Services Architect, IBM Corporation
01 Nov 2001 In the first two parts of this series, Peter described how to map WSDL service descriptions to a UDDI registry and provided specific WSDL usage scenarios. In the conclusion, you will learn how to develop two Java applications which publish WSDL service descriptions in a UDDI registry. One application will be used to publish WSDL service interface descriptions, the other to publish WSDL service implementation descriptions.
Before you start writing the code for publish applications,
you need to understand two basic requirements for this type of application.
First, the publish applications must read and understand the
contents of a WSDL document. Second, they must send requests to a UDDI
registry and then process any responses. Fortunately, there are two
existing Java class libraries that provide this functionality: the Web
Services Description Language for Java (WSDL4J) and the UDDI Java API (UDDI4J).
WSDL4J provides a standard Java interface which can be used to parse existing WSDL documents
or to programmatically create new WSDL documents. WSDL4J is an open source
project located on the IBM developerWorks site (see Resources) whose purpose is to provide a
reference implementation for Java
Specification Request 110 (JSR 110): Java APIs for WSDL (please also see
Resources for more on this). This JSR is being developed through the Java Community
process.
The programming examples in this article use WSDL4J V0.8. Most of the
WSDL4J classes represent the elements that can appear in a WSDL document.
For example, the <definition> element is
represented by the Definition class, and the <service> element is represented by the Service
class. There are also utility classes that make it easy to read and parse
a WSDL document, as well as write out the contents of the WSDL4J objects
as an XML document.
UDDI4J provides a Java client-side interface that
can be used to publish and find service descriptions in any UDDI registry.
This too is an open source project hosted on the IBM developerWorks site
(again, see Resources for a link).
For the publish applications, I will be using UDDI4J V1.03. This
version provides a complete implementation of the UDDI V1 application
programming interface. The UDDI4J classes include a complete
representation of the UDDI data entities. For example, a TModel class
represents a UDDI tModel and a BusinessService
class represents a businessService. UDDI4J also
includes a UDDI registry proxy class. This class is used to send publish and find requests
to a UDDI registry.
Publishing a WSDL service interface as a UDDI tModel
I'll start off by developing the code that will be used to publish a WSDL
service interface description as a UDDI tModel. In the first part of this
series, I reviewed the steps that were required to properly publish a
WSDL service interface definition. I will go through these steps as the
requirements for developing the publish application. Here is a brief
summary of these steps:
- Set the
tModel name from the targetNamespace for the WSDL document.
- If there is a documentation element within the description element, then use it to create a
tModel description.
- Put the network-accessible location for the WSDL service interface document in an overviewDoc.
- Add at least one
keyedReference that indicates that the tModel contains a reference to a WSDL service description.
The code associated with each of these steps is described in detail
below. You can also view and download the complete PublishServiceInterface
application (see Resources for a link).
Step 1: Create the tModel
and set the name from the targetNamespace
Before processing this step, you need to read and parse the WSDL
document. You do this using the WSDLReader class in WSDL4J. After reading
the WSDL document, you create a new tModel
object and set its name from the targetNamespace in the WSDL document.
Listing 1: First read and parse the WSDL document
// Read WSDL service interface document
Definition def = WSDLReader.readWSDL(null, wsdlURL);
...
// Create tModel from WSDL service interface
TModel tModel = new TModel();
// [STEP 1: tModel} Set the businessService name from targetNamespace
tModel.setName(def.getTargetNamespace());
|
Step 2: Set the tModel description from the WSDL documentation element
Setting the tModel description is optional.
If the documentation element is specified within a definition element,
then it can be used to set the tModel
description.
Listing 2: Setting a tModel description
// Get documentation element
Element element = def.getDocumentationElement();
// [STEP 2: tModel] Set default tModel description
String desc = DOMUtils.getChildCharacterData(element);
tModel.setDefaultDescriptionString(desc);
|
Step 3: Create the overviewDoc for the tModel
The overviewDoc will contain the network accessible location for the
WSDL service interface document. In this code segment, the overviewURL is
set to the location of the WSDL document.
Listing 3: Setting the overviewURL
// Create overview doc
OverviewDoc overviewDoc = new OverviewDoc();
// Create overview URL
OverviewURL overviewURL = new OverviewURL(wsdlURL);
// Set overviewURL
overviewDoc.setOverviewURL(overviewURL);
// [STEP 3: tModel] Set the overviewDoc
tModel.setOverviewDoc(overviewDoc);
|
Step 4: Categorize the tModel as a WSDL service description
Since a tModel can reference a service
description that can be specified in any markup language, it is important
to indicate that this tModel represents a WSDL
service description. Adding one additional entry in the tModel's categoryBag will do this. In this sample
code, there are two keyedReferences. One
indicates the type of service description, and the other one indicates the
business purpose of a service that implements this service interface.
Listing 4: Editing the tModel's categoryBag
// Create a categoryBag and get the CategoryBag
categoryBag = new CategoryBag();
// Create a keyedReference for wsdlSpec
KeyedReference kr = new KeyedReference("uddi-org:types", "wsdlSpec");
kr.setTModelKey("UUID:C1ACF26D-9672-4404-9D70-39B756E62AB4");
krList.add(kr);
// Create a keyedReference for the category of service
Vector krList = new Vector();
kr = new KeyedReference("Stock market trading services", "84121801");
kr.setTModelKey("UUID:DB77450D-9FA8-45D4-A7BC-04411D14E384");
krList.add(kr);
// Set keyed reference vector
categoryBag.setKeyedReferenceVector(krList);
// [STEP 4: tModel] Set the category bag
tModel.setCategoryBag(categoryBag);
|
Publishing a WSDL service implementation as a UDDI businessService
The second application will publish a WSDL service implementation
description in a UDDI registry as a businessService. To do this, you must create both a
businessService and a bindingTemplate. The steps listed below are based on
the process that was defined in the first part of this series. These
steps show how to create both a businessService
and a bindingTemplate, and will be used as the
basis for building your publish application. The code associated
with each of these steps has been extracted from the complete PublishServiceImplementation application.
I will review the steps for creating a businessService first. Here is a summary of these
steps:
- Set the
businessService name from the name of the service element.
- If it is specified, use the contents of the documentation element to create a description for the
businessService.
Step 1: Create the businessService and set the name from the service name
Start by reading and parsing the contents of the WSDL document. You
do this using the WSDLReader class in WSDL4J. After reading the WSDL
document, you can create a new businessService
object and set its name from the service name in the WSDL document.
Listing 5: Creating and naming a new businessService object
// Read WSDL service implementation document Definition
wsdlDefinition = WSDLReader.readWSDL(null, wsdlURL);
// Get the first service element only
Service wsdlService =
((Service[]) wsdlDefinition.getServices().values().toArray(new Service[0]))[0];
...
// Create businessService from WSDL service interface
BusinessService businessService = new BusinessService();
...
// [STEP 1: businessService] Set the businessService name from service name
businessService.setName(wsdlService.getQName().getLocalPart());
|
Step 2: Set the businessService description from the WSDL documentation element
The WSDL documentation element within the service element is used to
set the default description for the businessService:
Listing 6: Setting the default businessService description
// Get documentation element
element = wsdlService.getDocumentationElement();
// [STEP 2: businessService] Set default businessService description
businessService.setDefaultDescriptionString(DOMUtils.getChildCharacterData(element));
|
Now that you have created a businessService,
you can create the bindingTemplate. Here is a
summary of the four steps for creating the bindingTemplate:
- If the port element contains a documentation element, then use its contents to create a description for a
bindingTemplate.
- Use the location within the port element to set the
accessPoint.
- Add a
tModelInstanceInfo to the bindingTemplate. This element contains the tModelKey.
- Create an overviewDoc element that contains a reference to the WSDL service implementation document.
Step 1: Create the bindingTemplate and set the description from the WSDL documentation element
Create a new bindingTemplate object, and
then set its default description from the WSDL documentation element that
was within the port element.
Listing 7: Create and set a bindingTemplate object
// Create a bindingTemplate
BindingTemplate bindingTemplate = new BindingTemplate();
// Get the first port element
Port wsdlPort = ((Port[]) wsdlService.getPorts().values().toArray(new Port[0]))[0];
// Get documentation element
element = wsdlPort.getDocumentationElement();
// [STEP 1: bindingTemplate] Set default bindingTemplate description
bindingTemplate.setDefaultDescriptionString(DOMUtils.getChildCharacterData(element));
|
Step 2: Set the access point within the bindingTemplate
The access point is set from the extensibility element that is within
the port element. For this sample code, I assumed that the SOAP binding
was used and that the access point uses an HTTP protocol.
Listing 8: Setting the bindingTemplate access point
// Get first extensibility elementExtensibility
Element ext = (ExtensibilityElement) wsdlPort.getExtensibilityElements().get(0);
// Create access point (assume that it is always SOAP binding and HTTP protocol)
AccessPoint accessPoint = new AccessPoint(((SOAPAddress)ext).getLocationURI(), "http");
// [STEP 2: bindingTemplate] Set the access point
bindingTemplate.setAccessPoint(accessPoint);
|
Step 3: Create a tModelInstanceInfo which will reference the service interface
The bindingTemplate must contain a
reference to the tModel that is associated with
the service interface definition. This is done by creating a tModelInstanceInfo which contains the tModelKey for this tModel.
Listing 9
// [STEP 3: bindingTemplate] Create tModelInstanceInfo using the tModelKey
tModelInstanceInfo = new TModelInstanceInfo(tModelKey);
|
Step 4: Create the overviewDoc in the instanceDetails
This step is similar to that for the service interface document, except
that the overviewDoc will contain the location of the WSDL service
implementation document.
Listing 10
// Create overview URLOverviewURL
overviewURL = new OverviewURL(wsdlURL);
// Set overviewURL
overviewDoc.setOverviewURL(overviewURL);
// [STEP 4: bindingTemplate] Set the overview doc
instanceDetails.setOverviewDoc(overviewDoc);
|
Using the publish applications
The publish applications that you developed can be used to
publish WSDL service interfaces and WSDL service implementations. You can
use the following WSDL service descriptions, which are listed in the
Resources section, to test these applications:
- SQS-interface.wsdl -- WSDL service implementation description for a stock quote service
- SQS.wsdl -- WSDL service interface description for a stock quote service
These service descriptions appeared in the first article in this
series. To use them, you should put them in a location where they are
accessible through a Web server. Also, you must update the location
attribute on the import element in the WSDL service implementation
document. This attribute must contain the network accessible location for
the WSDL service interface document. An example of the value for the
location attribute would be http://localhost:8080/wsdl/SQS-interface.wsdl.
Selecting a UDDI registry to use
To run the publish applications, you also need to select a UDDI
registry to use. This section describes the different types of UDDI
registries, and shows how to use the class to access them.
There are two types of UDDI registries that you can use to run the
publish applications in this article: the UDDI test registries
available on the Internet, or a private UDDI registry -- which can (but
needn't) be run on your own system. When running test code, you should
never use one of the public UDDI registries: the public UDDI registries
can be effective only if they contain reliable data; publishing test data
to these registries will diminish the reliability of their data.
After you have selected a UDDI registry to use, you must register
yourself with that UDDI registry. When you register, you will specify a
userid and password, which you will need to publish data to the registry.
UDDI test registries
There are two public UDDI test registries. IBM hosts one and the
other one is provided by Microsoft. Each registry has two interfaces.
The inquire interface is used to find
information in the registry, and the publish
interface is used to publish and unpublish data in the registry. The two
test registries are accessible at the following locations:
IBM Test Registry
Private UDDI registry
An example of a private UDDI registry is the IBM WebSphere UDDI
Registry Preview (see Resources for a link). A
private UDDI registry must be installed on one of your own systems. After
a private registry is installed on your local system, it should be
accessible using the following set of URLs:
- Inquiry:
http://localhost:80/services/uddi/inquiryapi
- Publish:
http://localhost:80/services/uddi/publishapi
Creating the UDDI proxy
In UDDI4J, the UDDIProxy class provides the interface to a UDDI registry. Each
of the publish applications contains a get
method. This method does two things. First, the UDDI proxy is created
using the inquiry URL and publish URL. Second, it adds the support that is
needed to use SSL (all publish messages are sent to the UDDI test
registries using an SSL connection. Both of the publish
applications in this article use IBM's SSL support, but other
implementations can be used by changing the protocol handler and the
security provider.)
Listing 11: Create the UDDI proxy for a UDDI registry
/**
* Create the UDDI proxy for a UDDI registry.
* @param inquiryURL the inquiry URL for the UDDI registry
* @param publishURL the publish URL for the UDDI registry
* @return Returns the UDDI proxy of the IBM test registry.
*/
public static UDDIProxy get(String inquiryURL, String publishURL)
throws Exception
{
UDDIProxy uddiProxy = null;
// Add SSL support (this is IBM's SSL support
// but it can be replaced with other implementations)
System.setProperty("java.protocol.handler.pkgs",
"com.ibm.net.ssl.internal.www.protocol");
java.security.Security.addProvider(new com.ibm.jsse.JSSEProvider());
// Create UDDI proxy
uddiProxy = new UDDIProxy();
uddiProxy.setInquiryURL(inquiryURL);
uddiProxy.setPublishURL(publishURL);
// Return UDDI proxy
return uddiProxy;
}
|
Running the publish applications
The following table provides a brief description of each publish
application, as well as their command-line arguments.
|
Application
|
Description
|
Command-line arguments
| |
PublishServiceInterface
| Read a WSDL service interface document and publish it as a UDDI tModel. | PublishServiceInterface <wsdlURL> <userid> <password> [<inquiryURL> <publishURL>] | |
PublishServiceImplementation
| Read a WSDL service implementation document and publish it as a UDDI businessService. | PublishServiceImplementation <wsdlURL> <userid> <password> <businessKey> <tModelKey> [<inquiryURL> <publishURL>] |
The command-line arguments for these commands are:
-
wsdlURL
the network accessible location for the WSDL document
-
userid
the userid that is registered at the UDDI registry
-
password
the password associated with the userid
-
businessKey
the businessKey for the businessEntity where the businessService will be published
-
tModelKey
the tModelKey for the tModel that is associated with the WSDL service interface definition
-
inquiryURL
the inquiry URL for the UDDI registry (the default value is http://www-3.ibm.com/services/uddi/testregistry/inquiryapi)
-
publishURL
the publish URL for the UDDI registry (the default value is https://www-3.ibm.com/services/uddi/testregistry/protect/publishapi)
For the PublishServiceImplementation application, a businessEntity must be published before you can
publish a businessService. To create a businessEntity, you can either use the Web-based user
interface for the UDDI registry, or you can use the UDDI4J. The UDDI4J:
Matchmaking for Web services article (see Resources), which contains an example of how to do
this. Also, the tModelKey command-line argument
can be obtained from the output of the PublishServiceInterface
application.
You can download and run both of the publish applications on
your own system. To do this you must install both WSDL4J and UDDI4J,
along with all of their prerequisites. You will also need an
implementation of the Java Secure Socket Extension (see Resources), since
it provides SSL support.
Another option is to download and install the IBM Web Services Toolkit
(see Resources). The Web Services Toolkit (WSTK)
includes WSDL4J and UDDI4J, as well as all of the other prerequisite
software. If you install the WSTK, you can use the wstkenv command to set up the classpath that is
needed to compile and run the publish applications. The wstkenv command is located in the WSTK bin directory,
and its purpose is to define a set of environment variables. One of these
environment variables is named WSTK_CP; this environment variable contains
the classpath that is required to compile and run the publish
applications. Here's an example of the command that you would use to run the
PublishServiceInterface application on Windows NT or Windows 2000:
Listing 12
java -cp %WSTK_CP% PublishServiceInterface <wsdlURL>
<userid> <password>
|
If you are using one of the UDDI test registries and your system is
located behind a firewall, you will need to use either a socks client or
to specify a socks or proxy server. The WSTK documentation includes a
Toolkit Configuration Guide which contains instructions on how to do this.
Summary
Through this series of articles, I have described how to publish and
find different types of WSDL service descriptions in a UDDI registry. In
this last article, I showed how to use WSDL4J and UDDI4J to publish both
a WSDL service interface and a service implementation. When publishing
services descriptions in a UDDI registry, it is important to follow the
process defined in this series of articles. By following this process,
you will ensure that potential service requestors can easily find and use
your Web services
Resources
About the author  | |  |
Peter Brittenham is currently the lead architect for the IBM Web
Services Toolkit. The Web Services Toolkit contains the tools and
runtime support that are required to build Web services using SOAP and
WSDL, as well as the runtime support to publish and find service
definitions in a UDDI registry. He can be contacted at peterbr@us.ibm.com.
|
Rate this page
|