10.2 Programming with UDDI::Lite


If the explanation of UDDI thus far has seemed short on examples, it's simply because there is no need to handcode UDDI applications. The SOAP::Lite module provides UDDI support in the form of the UDDI::Lite class and supporting elements. Because UDDI itself uses ordinary SOAP methods for communication, working with the toolkit elements will be as familiar and comfortable as the previous SOAP::Lite examples. The classes and their methods are also present in the reference presented in Appendix C.

At present (as of SOAP::Lite Version 0.55), UDDI support is primarily limited to version 1, with no available hooks to the new API routines in Version 2.

10.2.1 The UDDI::Lite Family

The classes in the UDDI support set all inherit from their SOAP::Lite counterparts, which means that their interfaces are very similar. Most of the application-level work is done through objects instantiated from the UDDI::Lite class. The new method, the constructor, takes the same style of arguments as the constructor for SOAP::Lite . Like that class, most methods return the object reference upon success, to enable chaining of method calls.

The UDDI::SOM and UDDI::Data classes are made available for managing the response objects and the encoding of input parameters, respectively. The UDDI::Data class also manages an object-oriented interface to the UDDI structures that are returned from calls. This object model is covered in greater detail later on.

The UDDI support extends to two more classes, UDDI::Serializer and UDDI::Deserializer . These classes inherit from and extend the functionality of their SOAP::Lite counterparts with UDDI-specific considerations. As with the SOAP classes, these are rarely needed for use within an application. They are instantiated by the UDDI::Lite object behind the scenes.

10.2.1.1 Connecting through UDDI::Lite

Using the UDDI::Lite class for connections is very like using SOAP::Lite . The simple application in Example 10-6 shows the basic steps of connection to and communicating with a UDDI registry. It simply calls find_business with an initial letter 26 times (from A to Z), printing the number of businesses under each initial, and listing them. (Note that running this application may produce considerable output.)

Example 10-6. A simple UDDI application
 #!/usr/bin/perl     use strict; use UDDI::Lite;     my $uddi =     UDDI::Lite->proxy('http://uddi.microsoft.com/inquire');     for my $letter ('A' .. 'Z') {     my $results = $uddi->find_business(name => $letter)                        ->result;     my @list = $result->businessInfos->businessInfo;     printf "%c: (%d)\n", $letter, scalar @list;     printf "\t%s\n", $_->name for (@list); }     exit; 

In this example, the object-model that UDDI::Data implements is first illustrated . The variable $results is assigned the data from the deserialized message returned by the registry. When calling find_business, the return message is an outer businessInfos container tag, within which will be zero or more businessInfo elements with abbreviated content from the businessEntity record. Regardless of the type of message, the model is the same: the reference returned by the UDDI::SOM::result method is blessed into the UDDI::Data package, and from that reference the element names may be called as methods.

10.2.1.2 Getting and reading data from UDDI::Data

The following XML fragment is the basic structure returned by the find_business call from Example 10-6:

 <businessList generic="1.0" xmlns="urn:uddi-org:api">   <businessInfos>     <businessInfo>       <name>...</name>       ...     </businessInfo>     <businessInfo>       ...     </businessInfo>   </businessInfos> </businessList> 

When the application got the UDDI::Data object that resulted from the deserialization of that structure, the only element at the top level was businessList . At this level, the $results variable is primarily useful for referencing the first level of XML tags, businessInfos itself. If the attributes are needed, they can be accessed at this point with the attr method.

However, the object that $results->businessInfos returns is much more useful. For one thing, if the element is a leaf tag (one containing no subelements), the value method returns the content. If there are any attributes present, the attr method returns a hash reference containing them and their values. Each call to such a tag method returns a UDDI::Data object. In the example, rather than save the intermediate object, the application just uses the new reference to call a tag method for the next level, the one that returns the data associated with the businessInfo elements contained within the outer element.

As with the data-manipulation methods in SOAP::Lite , those in this instance are sensitive to being called in a list or scalar context. In the example, the call to the businessInfo method is done in a list context, ensuring that all such subelements of businessInfos are gathered into the array variable @list . One element present in the structure at this level is the name , which contains the business name as presented in its entity record within the registry. For the simple application, that's all that's interesting. To print, the for loop iterates over the collected objects in @list and calls the name method on each.

Another thing this section's example brings to light is the fact that the structures returned from the find_* routines don't always closely resemble the basic data structures. Table 10-9 lists the container tags and their contents for the various find_ * routines.

Table 10-9. Structure of messages from UDDI calls

Call

Returns

find_binding

bindingDetail container with zero or more bindingTemplate structures.

find_business

businessList container, which holds one businessInfos container. Within that are zero or more businessInfo elements, each of which contains name , description , and a serviceInfos container. The container holds zero or more serviceInfo elements, which have serviceKey attributes and contain name elements for the service structures associated with the entity record.

find_relatedBusinesses

(UDDI 2 only)

relatedBusinessesList container, with one relatedBusinessesInfos container within it. This holds zero or more relatedBusinessInfo structure. These contain name , description , businessKey (as an element rather than an attribute), and up to two sharedRelationships elements. These reference the business relationship through keyedReference record.

find_service

serviceList container element with one serviceInfos container. This holds zero or more serviceInfo structures as detailed previously.

find_tModel

tModelList containing a single tModelInfos container. This holds zero or more tModelInfo elements, which have tModelKey attributes and contain name elements for the tModel structures they refer to.

Fortunately, the returned values from the get_* routines are much clearer. Each returns basic UDDI data structures, the number of which depends on how many keys were passed in the request and how many keys were found in the registry.

10.2.2 Showing More Detail for a Business

This section presents a more in-depth sample application that uses UDDI::Lite to display a greater amount of detail on one or more business, based on command-line arguments. The application itself is too long to list here, but the full code (with annotations) is provided in Appendix E.

10.2.2.1 The idea

The premise for this sample application is simple: given a business name (or partial name), dump the more relevant information from the UDDI registry in a human-readable format. The goal is to become familiar with both the structures of UDDI, and the use of the UDDI::Lite toolkit itself.

While the application can peer down as deeply as the tModel structures themselves , it goes only as deep as the bindings for now. You should take the script and experiment with it, adding the additional functionality as desired. Another useful facet of the example is to run it with full tracing on (using the trace interface defined in Chapter 6). Because the UDDI::Lite class directly inherits from SOAP::Lite , it may also use the SOAP::Trace facility with the same interface. A script can be run with tracing without having to modify the script; it can simply be passed as an argument to the Perl command itself:

 perl -MUDDI::Lite=trace,debug   application [ arguments ]   

Recalling the debug tracing level from Chapter 6, it's especially useful because it shows the SOAP envelopes for messages, which can help you understand the structure of data being returned by the registry.

10.2.2.2 Using UDDI::Lite with auto-dispatch

This application takes advantage of the auto-dispatch capabilities of the SOAP::Lite toolkit. It also chooses to import some handy utility functionality (such as data-building routines name and findQualifiers ) from UDDI::Data . Let's examine some lines from the first part of the application:

 use Text::Wrap qw(wrap $columns); use Getopt::Long 'GetOptions'; use UDDI::Lite +autodispatch =>                proxy => 'http://uddi.microsoft.com/inquire',                import => 'UDDI::Data';     GetOptions(\%opts, qw(case exact showkeys)) and     $name = shift or     die "USAGE: 
 use Text::Wrap qw(wrap $ columns ); use Getopt::Long 'GetOptions'; use UDDI::Lite +autodispatch =>                proxy => 'http://uddi.microsoft.com/inquire',                import => 'UDDI::Data';     GetOptions(\%opts, qw(case exact showkeys)) and     $name = shift or     die "USAGE: $0 [ --case ] [ --exact ] [ --showkeys ] " .         "name\n"; 
[ --case ] [ --exact ] [ --showkeys ] " . "name\n";

The application not only uses the UDDI::Lite classes, but it also uses Getopt::Long for command-line parsing and Text::Wrap for simple text formatting. Here are the options it recognizes:

--case

Tells the application to make the name lookup case-sensitive. The default in UDDI is case-insensitive.

--exact

By default, the UDDI registry takes the name given as an argument and matches it as a partial string to records in their database. This option forces the match to be exact.

--showkeys

Because the UUID keys have no real human-readable meaning, the application doesn't display them by default. This option requests that the keys be printed along with the other data.

The options (except for --showkeys ) can create a set of findQualifier elements for the eventual call to find_business . This segment creates the parameters for the call:

 @qualifiers = ('sortByNameAsc'); push(@qualifiers, 'exactNameMatch')     if ($opts{exact}); push(@qualifiers, 'caseSensitiveMatch') if ($opts{case}); push(@params,      findQualifiers(findQualifier(@qualifiers)),      name($name)); 

This is simple logic: the routines findQualifiers , findQualifier , and name are imported from UDDI::Data . In fact, the sortByNameAsc qualifier isn't actually needed, because it's the default behavior. However, it simplifies the logic to have it here and keeps the application from passing an empty list of qualifiers to the call.

Making the call itself and iterating over the list of businesses returned by the registry are equally as simple:

 my $result = find_business(@params); dump_business($_)     for ($result->businessInfos->businessInfo); 

Note that because auto-dispatching is used, the return value from find_business is already converted to a UDDI::Data object. As with the earlier example, the interim businessInfos containment structure is quietly skipped over, with the application going directly for the list of businessInfo structures. The actual processing of most of the information is simple. While the dump_business routine isn't very special, it calls a routine named dump_service that deserves some attention.

Recalling Table 10-9, the structures returned from find_business aren't complete businessEntity records. For this application, they return enough business-level information to suit the purpose (the name and description fields). They also provide limited information on the services, but in this case it isn't enough for the application's purpose. Consequently, the dump_service routine must take what information it does get and use that to retrieve the full structure:

 sub dump_service {     my $svc = shift;         my ($key, $service);  $key = $svc->serviceKey;   return unless   $service = get_serviceDetail($key);   $service = $service->businessService;  print '    Service: ', $service->name, "\n";     print '    uuid:', $service->serviceKey, "\n"         if $SHOWKEYS;     if (my $description = $service->description) {         $columns = 64;         print wrap("\t    ", "\t    ", $description), "\n";     }     print "\n";     dump_template($_)         for ($service->bindingTemplates->bindingTemplate); } 

The emphasized lines in this segment show where the incoming data, which is a UDDI::Data object that describes a serviceInfo structure, is turned into the key through which the businessService record is retrieved. As a fortunate turn , this structure contains the bindingTemplate records in full, so the dump_template routine won't have to go to the same lengths.

The full application is listed in Appendix E, under the name show_biz . [3] The code is documented (the comments removed from the previous snippets for brevity), and will hopefully provide a good starting point for further exploration of UDDI. Because the publishing routines (both for creation and deletion) require registration and overhead for tasks such as authentication, there aren't any examples here that use them. There are some demonstrations of the routines in the UDDI test suite in the SOAP::Lite package, and the UDDI::Lite classes and methods are documented in Appendix C, along with the rest of the SOAP::Lite interface.

[3] It shows business information, after all, so the pun was too tempting to pass up.



Programming Web Services with Perl
Programming Web Services with Perl
ISBN: 0596002068
EAN: 2147483647
Year: 2000
Pages: 123

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