Implementing the Service Factory Pattern


Different parts of the case study application can leverage the Service Factory pattern. The most likely place is within a business activity in a business process, but business objects and object collections may be common as well; it really depends on your application domain.

A service factory can be a stand-alone object, or it can be integrated into an overall business process. This example illustrates the mechanisms rather than where the mechanism fits. For this purpose, you will concentrate on an existing business object collection: the product collection.

You will locate all product collections that adhere to an expected tModel and that are a part of the coffee industry. For example, if 20 coffee supply vendors implemented the same tModel for the product collections, you would find all 20. From that group of 20, you apply an arbitrary algorithm to select one for the main path of the application to use. This scenario might be useful in a portal application where you want to present the lowest price you can find for a particular product.

To build a service factory, you need to build a single class implementation that locates the candidate services in a UDDI directory and chooses a single service to return to the service factory client. The service factory is a Singleton pattern, which means zero or one instance of the service factory lives in your process space at a time. A client retrieves the instance and calls the getService() method on the class. Figure 15-3 shows the ProductCollectionServiceFactory instance with the public instance retrieval method, getInstance() , and the public method call, getService() .

click to expand
Figure 15-3: Sample implementation of the product collection service factory

The self-association in Figure 15-3 is the result of the Singleton pattern. The Singleton pattern helps you because it is useful to cache data in the service factory. Further, the instance itself will have low contention in terms of accessors, so the single instance turns into an optimization rather than a bottleneck.

The code to manipulate UDDI and get the information you are looking for is nontrivial. The key to the code is simply knowing how to traverse the complex UDDI structures and knowing which objects in the registry to use for information. The following sections walk you through the steps of a sequence diagram. After that, you will look at a short program that leverages the service factory implementation.

Note  

This chapter has less implementation code than previous chapters. The code to traverse UDDI is outside of the scope necessary to understand the pattern.You can download the source code for the book if you would like to browse the code in depth.

Following the Flow of the Product Collection Service Factory

The sequence begins with an external class requesting an architecture adapter that will allow the class to interact with a product collection. The class first calls the getInstance() method, which returns the instance of ProductCollectionServiceFactory . Next, you call the getService() method, which returns an instance of ProductCollectionImpl . The ProductCollectionImpl instance is an architecture adapter that was generated using WSDL2Java. Before the adapter was generated, you obtained the Web Services Description Language (WSDL) file that represented a product collection.

From this point to the point where the factory returns an instance of the product collection adapter, the service factory goes through a considerable number of steps and interactions with the UDDI directory. Figure 15-4 shows a high-level sequence diagram; the code has more private method calls to collect other information, but this diagram should be enough to outline the entire process.

click to expand
Figure 15-4: Product collection service factory execution sequence

After the call to the service factory, the factory goes through two high-level steps, denoted as 2.1 and 2.2 in Figure 15-4. Step 2.1 retrieves references to all of the Web Services in the coffee industry using the appropriate North American Industry Classification System (NAICS) code. This step contains several sub- steps, each interacting with the UDDI registry to achieve the step's responsibility. These substeps are the ones that make the code long and involved. Traversing UDDI structures and querying a UDDI registry is not necessarily difficult work, but it is code intensive .

Step 2.2 applies an algorithm to retrieve a single service from all of those returned from step 2.1. This code could be as complex as locating a catalog with all of the products you are searching for at the lowest price or as simple as taking the first element of the array. Figure 15-4 assumes that step 2.2 may actually interact with the individual services to select a single service. Without this assumption, you could pass UDDI structures between the steps.

Step 2.1 goes through two major substeps. First, step 2.1.1, getBusinesses SupportingModel() , queries UDDI and returns a list of businesses in the form of a BusinessList object from the UDDI4J API. Second, in step 2.1.2, you take each business from the list and instantiate an architecture adapter to the Web Service. To do this, you must interact with UDDI for each of the businesses in the list and retrieve the binding template from UDDI. The binding template contains the access point for the product collection offered by each business. You use this access point to construct your architecture adapter, as shown in Listing 15-1.

Listing 15-1: Constructing an Adapter from the Access Point Structure
start example
 String url = accessPoint.getText(); ProductCollectionImplServiceLocator pcisl =     new ProductCollectionImplServiceLocator(); stub = pcisl.getProductCollection(new URL(url)); 
end example
 

This process repeats, starting with locating the binding template, for each of the businesses returned from step 2.1.1. You insert each adapter into an array that you subsequently return to the main body of step 2.1. Once you build the entire set of adapters, you move to step 2.2, already described, to find the one you want to return to your client.

Using the Product Collection Service Factory

The best part of using a service factory is the cleanliness of the main program's code. Listing 15-2 illustrates using a service factory, the one described in the previous sections, to get an array of products from a product collection and print the product names in the collection.

There are two lines of code to interact with the service factory, one to retrieve an instance of the factory and the other to retrieve a service instance. Beyond this code, the main program works as if you had only one product collection to choose from, thus simplifying the main line code.

Listing 15-2: Using the Product Collection Service Factory
start example
 public static final void main(String args[]){          ProductCollectionServiceFactory serviceFactory = null;          serviceFactory = ProductCollectionServiceFactory.getInstance();          ProductCollectionImpl pci = serviceFactory.getService();          try {              Product[] pArray = pci.getProducts();              System.out.println("Products in Collection");              for(int i = 0 ; i<>pArray.length ; i++){                  System.out.println(pArray[i].getName());              }          } catch (Exception e) {              e.printStackTrace();          }      } 
end example
 

As you can see, there is a significant benefit in terms of code simplification and isolation of responsibilities. You can even go so far as to isolate the UDDI interactions to the factory components and thus allow pure Java platform programmers to concentrate on the flow of the main program.

Considering Sample Variations

There are many possible variations of the internal workings of the service factory. Most variations have to do with understanding your environment and working to optimize the performance of the factory based on that environment.

Perhaps the most extreme variation of the internal workings of the pattern is to leverage the UDDI notification mechanisms, available in version 3, to maintain a cache of access points to possible services. The Service Cache pattern is available from SourceForge (http:// sourceforge .net/projects/websvcdsnptn). The purpose of the service cache is to remove the collection of valid access points from the service factory. This navigation of UDDI to obtain access points is time consuming and requires nontrivial coding. By maintaining a service cache, you can improve the performance of the service factory proper and move the factory complexity into a separate object.




Web Service Patterns
Web Services Patterns: Java Edition
ISBN: 1590590848
EAN: 2147483647
Year: 2003
Pages: 190

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