In the first paper in this series (see Resources for links to Parts 1,2,3 and 4) you learned about a new approach to constructing a UDDI model of a WSDL description. The second paper described the types of UDDI query this new approach enables, with examples of several queries given in the form of UDDI V2 API requests. The third presented a more complex example than the one in the Technical Note, including screen shots showing you how to publish the UDDI entities and how to construct the types of query described in the Technical Note and in Part 2. The fourth part presented some example Java code showing you how to publish WSDL descriptions to UDDI programatically.
In this fifth paper you see some sample Java code that can issue the queries described in other examples in this series using UDDI4J.
The UDDI registry used in this example is an instance of the UDDI implementation that is shipped with IBM® WebSphere® Application Server Network Deployment, V5.1.
See Part 4 for additional details. You can obtain the results described here by running the sample in Part 4 against a clean registry and then running the sample described here.
The API presented here is at a fairly low level of abstraction in that the caller is required to know that, for example, a portType is mapped to a tModel and to know the various keys.
The API is structured as a single Java class that is a wrapper around an instance of the UDDI4J UDDIProxy class.
An instance of the Query class is constructed from an instance of the UDDIProxy class.
The Query class provides methods to query each of the entities used in the WSDL Technical Note.
For example, there are two methods that return portType tModels. The first takes as parameters only the namespace name and the portType name, either of which can be null.
The second has an additional parameter that is a categoryBag that you can use in the query in addition to the WSDL-related information.
As mentioned before, the API is a single Java class;
its fully-qualified name is uddi.wsdl.v2.query.Query, and the class has a constructor and eight public methods.
Listing 1 shows the class and the constructor.
Listing 1. Definition of the Query class and its constructor
package uddi.wsdl.v2.query;
import java.util.Vector;
import org.uddi4j.UDDIException;
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.BindingDetail;
import org.uddi4j.response.ServiceInfo;
import org.uddi4j.response.ServiceInfos;
import org.uddi4j.response.ServiceList;
import org.uddi4j.response.TModelInfo;
import org.uddi4j.response.TModelInfos;
import org.uddi4j.response.TModelList;
import org.uddi4j.transport.TransportException;
import org.uddi4j.util.CategoryBag;
import org.uddi4j.util.FindQualifier;
import org.uddi4j.util.FindQualifiers;
import org.uddi4j.util.KeyedReference;
import org.uddi4j.util.TModelBag;
import org.uddi4j.util.TModelKey;
public class Query {
private final static String WSDL_ENTITY_TYPE_TMODELKEY =
"uuid:6e090afa-33e5-36eb-81b7-1ca18373f457";
private final static String WSDL_ENTITY_TYPE_KEYNAME =
"WSDL entity type";
private final static String XML_NAMESPACE_TMODELKEY =
"uuid:d01987d1-ab2e-3013-9be2-2a66eb99d824";
private final static String XML_NAMESPACE_KEYNAME =
"XML namespace";
private final static String WSDL_PORTTYPE_REFERENCE_TMODELKEY =
"uuid:082b0851-25d8-303c-b332-f24a6d53e38e";
private final static String WSDL_PORTTYPE_REFERENCE_KEYNAME =
"WSDL portType reference";
private final static String PROTOCOL_CATEGORIZATION_TMODELKEY =
"uuid:4dc74177-7806-34d9-aecd-33c57dc3a865";
private final static String PROTOCOL_CATEGORIZATION_KEYNAME =
"protocol";
private final static String TRANSPORT_CATEGORIZATION_TMODELKEY =
"uuid:e5c43936-86e4-37bf-8196-1d04b35c0099";
private final static String TRANSPORT_CATEGORIZATION_KEYNAME =
"transport";
private final static String XML_LOCAL_NAME_TMODELKEY =
"uuid:2ec65201-9109-3919-9bec-c9dbefcaccf6";
private final static String XML_LOCAL_NAME_KEYNAME =
"XML local name";
private UDDIProxy proxy;
public Query(UDDIProxy proxy) {
this.proxy = proxy;
}
}
|
The parameter of the constructor is an instance of a UDDI4J proxy, which is assumed to be configured with the appropriate URLs, and so on.
The eight methods are made up of four sets of methods, one set for each of the different UDDI entities that can be queried:
query_portType_tModelquery_binding_tModelquery_bindingTemplatequery_service
There are two methods in each set. With the exception of query_bindingTemplate, the difference between the methods of each set is that one method takes an extra parameter of a categoryBag, which you should use in the query in addition to the information relating strictly to WSDL. The second query_bindingTemplate method takes additional parameters of the keys of tModels representing the protocol and the transport and is used when you desire an implementation of a particular protocol or transport.
Each of these sets of methods is described further in the following sections.
Listing 2 shows the query_portType_tModel method that takes only the WSDL-related information.
Listing 2. The WSDL-only query_portType_tModel method
public TModelList query_portType_tModel(String namespaceName,
String portTypeName)
throws TransportException, UDDIException {
return query_portType_tModel(namespaceName, portTypeName, null);
}
|
Listing 3 shoes the query_portType_tModel method that takes an extra parameter.
Listing 3. The query_portType_tModel method that takes an extra parameter
public TModelList query_portType_tModel(String namespaceName,
String portTypeName,
CategoryBag categoryBag)
throws TransportException, UDDIException {
if (categoryBag == null) {
categoryBag = new CategoryBag();
}
KeyedReference wsdlEntityTypeKR = new KeyedReference(
WSDL_ENTITY_TYPE_KEYNAME, "portType",
WSDL_ENTITY_TYPE_TMODELKEY);
categoryBag.add(wsdlEntityTypeKR);
if (namespaceName != null) {
KeyedReference xmlNamespaceKR = new KeyedReference(
XML_NAMESPACE_KEYNAME, namespaceName,
XML_NAMESPACE_TMODELKEY);
categoryBag.add(xmlNamespaceKR);
}
return queryTModel(portTypeName, categoryBag);
}
|
The query_portType_tModel method does the following:
- It adds a WSDL entity type
keyedReferencewith a value of portType to thecategoryBag. - If the namespace name parameter is not null, then it adds an XML namespace
keyedReferenceto thecategoryBag. - It invokes a private
queryTModelmethod with all of the information and returns the result of this private method.
Listing 4 shows the private queryTModel method.
Listing 4. The queryTModel method
private TModelList queryTModel(String name, CategoryBag categoryBag)
throws TransportException, UDDIException {
FindQualifiers findQualifiers = new FindQualifiers();
Vector findQualifierVector = new Vector();
findQualifierVector.add(new FindQualifier("exactNameMatch"));
findQualifierVector.add(new FindQualifier("caseSensitiveMatch"));
findQualifiers.setFindQualifierVector(findQualifierVector);
return proxy.find_tModel(name, categoryBag, null, findQualifiers,
Integer.MAX_VALUE);
}
|
Note that the code does an exact case-sensitive match on the name; it is assumed that the full name is passed in.
Listing 5 shows the query_binding_tModel method that takes only a tModelKey.
Listing 5. The query_binding_tModel method that takes only a tModelKey
public TModelList query_binding_tModel(String portTypeTModelKey)
throws TransportException, UDDIException {
return query_binding_tModel(portTypeTModelKey, null);
}
|
Listing 6 shows the query_binding_tModel method that takes an additional parameter.
Listing 6. The query_binding_tModel method that takes additional parameters
public TModelList query_binding_tModel(String portTypeTModelKey,
CategoryBag categoryBag)
throws TransportException, UDDIException {
if (categoryBag == null) {
categoryBag = new CategoryBag();
}
KeyedReference wsdlEntityTypeKR = new KeyedReference(
WSDL_ENTITY_TYPE_KEYNAME, "binding", WSDL_ENTITY_TYPE_TMODELKEY);
categoryBag.add(wsdlEntityTypeKR);
KeyedReference wsdlPortTypeReferenceKR = new KeyedReference(
WSDL_PORTTYPE_REFERENCE_KEYNAME, portTypeTModelKey,
WSDL_PORTTYPE_REFERENCE_TMODELKEY);
categoryBag.add(wsdlPortTypeReferenceKR);
return queryTModel(null, categoryBag);
}
|
The query_binding_tModel method does the following:
- It adds a WSDL entity type
keyedReferencewith a value of binding to thecategoryBag. - It adds a portType reference
keyedReferencewith a value of theportTypeTModelKeyparameter. - It invokes the private
queryTModelmethod with all of the information and returns the result of this private method.
The first method takes only a single parameter which is the key of a tModel, either a portType tModel or a binding tModel.
Listing 7 shows this query_bindingTemplate method.
Listing 7. The query_bindingTemplate method that takes just a tModel key
public BindingDetail query_bindingTemplate(String tModelKeyString)
throws TransportException, UDDIException {
TModelBag tModelBag = new TModelBag();
TModelKey tModelKey = new TModelKey(tModelKeyString);
tModelBag.add(tModelKey);
return queryBindingTemplate(null, tModelBag);
}
|
Note that this method invokes the private queryBindingTemplate method directly; it does not invoke the other public query_bindingTemplate method.
The second takes two additional parameters which are the keys of a protocol tModel and a transport tModel.
Listing 8 shows this query_bindingTemplate method.
Listing 8. The query_bindingTemplate method that takes three tModel keys
public BindingDetail query_bindingTemplate(String portTypeTModelKeyString,
String protocolTModelKey,
String transportTModelKey)
throws TransportException, UDDIException {
TModelList tModelList = null;
CategoryBag categoryBag = new CategoryBag();
if (protocolTModelKey != null) {
KeyedReference protocolKR = new KeyedReference(
PROTOCOL_CATEGORIZATION_KEYNAME, protocolTModelKey,
PROTOCOL_CATEGORIZATION_TMODELKEY);
categoryBag.add(protocolKR);
}
if (transportTModelKey != null) {
KeyedReference transportKR = new KeyedReference(
TRANSPORT_CATEGORIZATION_KEYNAME, transportTModelKey,
TRANSPORT_CATEGORIZATION_TMODELKEY);
categoryBag.add(transportKR);
}
tModelList = query_binding_tModel(portTypeTModelKeyString, categoryBag);
TModelBag tModelBag = new TModelBag();
TModelInfos tModelInfos = tModelList.getTModelInfos();
Vector v = tModelInfos.getTModelInfoVector();
int tModelCount = v.size();
for (int i = 0; i < tModelCount; i++) {
TModelInfo tModelInfo = (TModelInfo) v.elementAt(i);
TModelKey tModelKey = new TModelKey(tModelInfo.getTModelKey());
tModelBag.add(tModelKey);
}
FindQualifiers findQualifiers = new FindQualifiers();
FindQualifier orAllKeys = new FindQualifier();
orAllKeys.setText("orAllKeys");
findQualifiers.add(orAllKeys);
return queryBindingTemplate(findQualifiers, tModelBag);
}
|
The query_bindingTemplate method does the following:
- It queries binding tModels using the portType tModel key and the protocol and transport tModel keys, if they are not null.
- It adds each binding tModel to a
tModelBag. - It invokes a private
queryBindingTemplatemethod with afindQualifieroforAllKeysto search for all services that have at least one binding Template that refers to at least one of the binding tModels and to accumulate the results of all binding Templates into a single result.
Listing 9 shows the private queryBindingTemplate method.
Listing 9. The queryBindingTemplate method
private BindingDetail queryBindingTemplate(
FindQualifiers findServiceFindQualifiers, TModelBag tModelBag)
throws TransportException, UDDIException {
BindingDetail overallBindingDetail = new BindingDetail();
Vector overallBindingDetailVector = new Vector();
ServiceList serviceList = queryService(null,
tModelBag,
findServiceFindQualifiers);
ServiceInfos serviceInfos = serviceList.getServiceInfos();
Vector serviceVector = serviceInfos.getServiceInfoVector();
int serviceCount = serviceVector.size();
for (int i = 0; i < serviceCount; i++) {
ServiceInfo serviceInfo = (ServiceInfo) serviceVector.elementAt(i);
String serviceKey = serviceInfo.getServiceKey();
BindingDetail bindingDetail = proxy.find_binding(null,
serviceKey,
tModelBag,
Integer.MAX_VALUE);
overallBindingDetailVector.addAll(bindingDetail.getBindingTemplateVector());
}
overallBindingDetail.setBindingTemplateVector(overallBindingDetailVector);
return overallBindingDetail;
}
|
Listing 10 shows the query_service method that takes just WSDL-related parameters.
Listing 10. The query_service method that just takes WSDL-related parameters
public ServiceList query_service(String namespaceName, String serviceName)
throws TransportException, UDDIException {
return query_service(namespaceName, serviceName, null);
}
|
Listing 11 shows the query_service method that takes the extra parameter.
Listing 11. The query_service method that takes an extra parameter
public ServiceList query_service(String namespaceName,
String serviceName,
CategoryBag categoryBag)
throws TransportException, UDDIException {
if (categoryBag == null) {
categoryBag = new CategoryBag();
}
KeyedReference wsdlEntityTypeKR = new KeyedReference(
WSDL_ENTITY_TYPE_KEYNAME, "service", WSDL_ENTITY_TYPE_TMODELKEY);
categoryBag.add(wsdlEntityTypeKR);
if (namespaceName != null) {
KeyedReference xmlNamespaceKR = new KeyedReference(
XML_NAMESPACE_KEYNAME, namespaceName,
XML_NAMESPACE_TMODELKEY);
categoryBag.add(xmlNamespaceKR);
}
// Must use keyedReference in categoryBag for service name
if (serviceName != null) {
KeyedReference xmlNamespaceKR = new KeyedReference(
XML_LOCAL_NAME_KEYNAME, serviceName,
XML_LOCAL_NAME_TMODELKEY);
categoryBag.add(xmlNamespaceKR);
}
return queryService(categoryBag, null, null);
}
|
The query_service method does the following:
- It adds a WSDL entity type
keyedReferenceto thecategoryBagwith a value of service. - If a namespaceName is supplied, then it adds a
keyedReferenceto thecategoryBagfor the XML namespace taxonomy. - If a
serviceNameis supplied then it adds akeyedReferenceto thecategoryBagfor the XML local name taxonomy. - It invokes a private
queryServicemethod to search for the services.
Listing 12 shows the private queryService method.
Listing 12. The queryService method
private ServiceList queryService(CategoryBag categoryBag,
TModelBag tModelBag,
FindQualifiers findQualifiers)
throws TransportException, UDDIException {
return proxy.find_service(null, null, categoryBag, tModelBag,
findQualifiers, Integer.MAX_VALUE);
}
|
The purpose of the sample is to show how you can use the Query API to make most of the queries described in the Technical Note, given the limited model published to UDDI in Part 4.
The sample is written as a Java class with a main method.
The fully-qualified name of the class is uddi.wsdl.v2.query.QuerySample.
Listing 13 shows the class definition and the main method.
Listing 13. The class definition and main method of our sample application
package uddi.wsdl.v2.query;
import java.net.MalformedURLException;
import java.util.Vector;
import org.uddi4j.UDDIException;
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.datatype.binding.BindingTemplate;
import org.uddi4j.response.BindingDetail;
import org.uddi4j.response.ServiceInfo;
import org.uddi4j.response.ServiceInfos;
import org.uddi4j.response.ServiceList;
import org.uddi4j.response.TModelInfo;
import org.uddi4j.response.TModelInfos;
import org.uddi4j.response.TModelList;
import org.uddi4j.transport.TransportException;
import org.uddi4j.util.CategoryBag;
import org.uddi4j.util.KeyedReference;
public class QuerySample {
private final static String SOAP_PROTOCOL_TMODELKEY =
"uuid:aa254698-93de-3870-8df3-a5c075d64a0e";
private final static String HTTP_TRANSPORT_TMODELKEY =
"uuid:68DE9E80-AD09-469D-8A37-088422BFBC36";
public static void main(String[] args) {
UDDIProxy proxy = new UDDIProxy();
try {
proxy.setInquiryURL(args[0]);
try {
Query query = new Query(proxy);
queryPortTypeTModels(query);
queryBindingTModels(query);
queryBindingTemplates(query);
queryServices(query);
} catch (TransportException te) {
te.printStackTrace(System.err);
} catch (UDDIException uddie) {
uddie.printStackTrace(System.err);
}
} catch (MalformedURLException murle) {
System.err.println("inquiry URL malformed");
}
}
}
|
The main method expects a single argument, which is the inquiryURL to be used with the UDDI4J proxy.
The main method constructs the UDDI4J proxy and then constructs an instance of the Query class using this UDDI4J proxy instance.
The main method then calls the following private static methods in turn, passing in the UDDI4J proxy:
queryPortTypeTModelsqueryBindingTModelsqueryBindingTemplatesqueryServices
Each of these methods is described in the following sections.
This method calls the query_portType_tModel method passing in just a namespace name and a portType name, no additional categoryBag is passed.
Listing 14 (contained in this sidefile) shows the code for this method.
This method queries the tModel representing the ManufacturerPortType portType and then uses the key of the tModel to query all bindings of that portType.
It then does a second query to find the WS-I-conformant bindings of the tModel.
This second query is not described in the Technical Note but demonstrates the use of additional information, in this case
the categorization to indicate WS-I conformance.
Listing 15 (contained in this sidefile) shows the code for this method.
This method makes four separate calls to query_bindingTemplate.
The first is to query all implementations of the ManufacturerPortType portType, so it first of all finds the appropriate portType tModel and then calls query_bindingTemplate passing in the key of the portType tModel.
The second query is for all implementations of the WS-I-conformant binding of the ManufacturerPortType portType, so it finds the appropriate binding tModel and then calls query_bindingTemplate passing in just the key of the binding tModel.
The third query is for all SOAP implementations of the portType, so in this case the query_bindingTemplate method that takes three parameters
is called, with the first parameter being the key of the portType tModel, the second being the key of the tModel representing the SOAP protocol, and the third being null.
The fourth query is for all SOAP/HTTP implementations of the portType, so in this case all three parameters are used, with the third being the key of the tModel representing the HTTP transport.
Listing 16 (contained in this sidefile) shows the code for this method.
This method issues a simple query for the WarehouseA Warehouse service, passing in the namespace name and the service name. Listing 17 shows the code for this method.
Listing 17. The queryServices method
private static void queryServices(Query query)
throws TransportException, UDDIException {
System.out.println("\nQuerying the businessService for
the \"WarehouseA's Warehouse Service\" WSDL service (example of
query described in section 3.3.8 of the TN...)\n");
ServiceList serviceList = query.query_service(
"urn:x-warehousea.com:warehouse_service",
"WarehouseA's Warehouse Service");
ServiceInfos serviceInfos = serviceList.getServiceInfos();
Vector v = serviceInfos.getServiceInfoVector();
ServiceInfo serviceInfo = (ServiceInfo) (v.elementAt(0));
String serviceKey = serviceInfo.getServiceKey();
System.out.println("Service key is " + serviceKey);
}
|
To run the sample, execute the uddi.wsdl.v2.query.QuerySample class passing in a single argument which is the inquiryURL to be used.
You should see output similar to that shown in Listing 18 (contained in this sidefile).
This paper described how to implement the approach to query from a Java application as defined in the Technical Note using UDDI4J. I provided a sample class which queries the UDDI model for the WS-I Sample Application.
- Read the other parts of this series:
- "A new approach to UDDI and WSDL, Part 1" (developerWorks, August 2003) describes the new Technical Note on using WSDL and UDDI together.
- "A new approach to UDDI and WSDL, Part 2" (developerWorks, September 2003) describes the queries that are supported by the approach defined in the new Technical Note.
- "A new approach to UDDI and WSDL, Part 3" (developerWorks, October 2003) describes how to publish and query the UDDI model for the WS-I Sample Application, following the approach defined in the new Technical Note.
- "A new approach to UDDI and WSDL, Part 4" (developerWorks, October 2003) describes how to publish and query the UDDI model for the WS-I Sample Application, following the approach defined in the new Technical Note.
- Get the WS-I Sample Application, "Supply Chain Management Sample Application Architecture," published by the Web Services Interoperability Organization.
- Learn more about the Web Services Interoperability Organization (WS-I) and IBM.
- Read about the OASIS UDDI Specifications Technical Committee, which is now responsible for UDDI standards.
- Check out this article based on the Technical Note "Using WSDL in a UDDI Registry, Version 2.0.2," which has recently been published as an official Technical Note by the OASIS UDDI Specifications Technical Committee.
- Explore the previous Best Practice, "Using WSDL in a UDDI Registry, Version 1.08," which has been updated by the OASIS UDDI Specifications Technical Committee since the previous developerWorks articles were written.
- Access Web services knowledge, tools, and skills with Speed-start Web services, which offers the latest Java-based software development tools and middleware from IBM (trial editions), plus online tutorials and articles, and an online technical forum.
- Browse for books on these and other technical topics.
- Want more? The developerWorks SOA and Web services zone hosts hundreds of informative articles and introductory, intermediate, and advanced tutorials on how to develop Web services applications.
Comments (Undergoing maintenance)





