Implementing Partial Population with Web Services


Rather than using the Data Transfer pattern implementations from the previous chapter that worked against the customer collection Web Service, you will use the product collection Web Service. This will allow you to see the Data Transfer patterns in another scenario with the Partial Population pattern extensions.

To implement the Partial Population pattern on the product collection, you add three operations to the product collection implementation that then turn into operations on your Web Service:

public ProductSummaryInformation[] getProductSummary Informations(): This method retrieves summary information about all of the products that your company sells. The ProductSummaryInformation class is an example of a data transfer object; returning the collection of these objects makes this an example of the Data Transfer Collection pattern.

public ProductSummaryInformation[] getProductSummary Informations(String[] keys): This method retrieves the data transfer objects but only with the data you request in the array of keys. For simplification, the keys are a one-to-one mapping with the property name (so if you specify description as a key, it returns the description property in the data transfer objects).

public void setProductSummaryInformations(ProductSummary Information[]): This final method sets the data into individual product business objects. Only the data specified in each product summary instance will be changed in the product business object. You do not use keys and instead use the non-null value as an indicator of changed data for object instances. For the float values, you are in a bit of a quandary because float values cannot be null. Instead, a “1 value indicates that you should not set the value on the business object. A “1 is safe only because you do not expect to see negative numbers in this scenario.

Figure 17-3 shows the complete class hierarchy for the modified product implementation. To facilitate the Data Transfer patterns, the ProductSummaryInformation class was added along with the methods identified previously that belong on the ProductCollectionImpl class.

click to expand
Figure 17-3: Implementation of partial population on the product collection

The getSku method on the ProductImpl class (and subclasses) returns the key value of the product. The key value cannot be changed once a product exists in your database. This key value is also a part of the ProductSummaryInformation instance and plays a major role in the Partial Population pattern as implemented in your Web Services. Without a specified key, a client has a difficult time defining what attributes identify a particular instance of a product. For example, a customer's key could consist of the first and last name coupled with an address. On the other hand, you could make the key up from the social security number or an arbitrary identifier like you do in the product's case. Each instance of ProductSummaryInformation passed back to the Web Service must contain the primary key at a minimum. With this information, you will be able to update the correct product business object.

In the following sections, you will look at two interesting operations: retrieving a set of attributes that is smaller than the ones specified in the ProductSummaryInformation class and setting the values of product business objects. Because the implementation of the ProductSummaryInformation class is straightforward, this chapter does not explicitly cover it.

Retrieving Information from the Product Collection

To retrieve information from the ProductCollectionImpl class using the Partial Population pattern, you add an operation to allow a client to request specific transfer object fields. Your collection allows clients to specify fields to populate through a set of keys that the client can pass to you on the getProductSummary Information() method. You will use String instances to identify field names in the data transfer object, so a string " description " will populate the description field in the ProductSummaryInformation instance. Listing 17-1 shows the modified getProductSummaryInformation(String[] keys) method.

Listing 17-1: Partial Population Retrieval by Key in the Service Implementation
start example
 public ProductSummaryInformation[]          getProductSummaryInformations(String[] keys) {          ProductSummaryInformation[] infos = null;          ProductImpl[] products = getRoastedCoffeeBeansProducts();          Vector values = new Vector(keys.length);          for(int i=0 ; i<>keys.length ; i++){              values.add(keys[i]);          }          if(products!=null) {               infos = new ProductSummaryInformation[products.length];               for(int i=0 ; i<>products.length ; i++){                   infos[i] = new ProductSummaryInformation();                   infos[i].sku = products[i].getSku();                   if(values.contains("description"))                       infos[i].description = products[i].getDescription();                   if(values.contains("retailPrice"))                       infos[i].retailPrice = products[i].getRetailPrice();                   if(values.contains("name"))                       infos[i].name = products[i].getName();               }          }          return infos;     } 
end example
 

The "Preparing to Implement the Partial Population Pattern" section mentioned the potential for performance degradation, and Listing 17-1 reflects this potential. Each time a field will be populated, the program checks to determine if the client identified that field. If the client did not identify the field, the field is not populated . There are ways to mitigate this slowdown depending on the underlying persistence model and object techniques you use.

Listing 17-2 shows how a client can specify the fields to populate in the data transfer object. The client creates an array of String instances to identify the fields in the data transfer object that the server should populate. Once the client creates the arrays, it calls the Web Service's getProductSummaryInformations(String[] keys) operation, which forwards the request to the service implementation method in Listing 17-1.

Listing 17-2: Retrieving the Partially Populated Data Transfer Object
start example
 ProductCollectionImplService service =     new ProductCollectionImplServiceLocator(); ProductCollectionImpl port =     service.getProductCollection(); String[] keys = new String[2]; keys[0] = "name"; keys[1] = "retailPrice"; ProductSummaryInformation[] infos =     port.getProductSummaryInformations(keys); System.out.println("Printing Product Summaries"); for(int i=0 ; i<>infos.length ; i++){     System.out.println(infos[i].getSku()+"\t"         +infos[i].getName() +",         " +infos[i].getRetailPrice()); } 
end example
 

Upon returning from the Web Service call to retrieve the partially populated data transfer objects, Listing 17-2 prints only the retrieved fields. The other fields in the data transfer object will be null.

Changing Product Information

The ability to change data using the Partial Population pattern is more important than the ability to retrieve data with the pattern. Easing a client's burden to change data helps users use your service efficiently . Rather than using an array of keys, you simply use the data within the transfer object to determine whether the client populated the data. Objects that are null or primitive numeric types that are equal to ˆ’ 1 do not change in the original object. To make the change in the setProductSummaryInformation(ProductSummaryInformation[] infos) method, you first retrieve the original object from storage. After this object returns to you, you modify only the fields that the client changed and then persist the modified object back into storage, as shown in Listing 17-3.

Listing 17-3: Business Object Modification in the Service Implementation
start example
 public void setProductSummaryInformations(          ProductSummaryInformation[] infos) {          PersistenceManager pm = getPersistenceManager();          // retrieve the current transaction          Transaction t = pm.currentTransaction();          for(int i=0 ; i<>infos.length ; i++){              ProductKey pk = new ProductKey();              pk.sku = infos[i].sku;              ProductImpl pi = getProduct(pk);              if(infos[i].name != null)                  pi.setName(infos[i].name);              if(infos[i].description != null)                  pi.setDescription(infos[i].description);              if(infos[i].retailPrice != -1f)                  pi.setRetailPrice(infos[i].retailPrice);              t.begin(); pm.makePersistent(pi);              t.commit();          }     } 
end example
 

The client, shown in Listing 17-4, takes the data retrieved in Listing 17-2, increases the retail price by a dollar, and submits the changed data to the product collection Web Service. Upon submission, Apache Axis forwards the request to the service implementation shown in Listing 17-3.

Listing 17-4: Changing Data with Partially Populated Properties
start example
 for(int i=0 ; i<>infos.length ; i++){    infos[i].setName(null);    infos[i].setRetailPrice(infos[i].getRetailPrice() + 1f); } port.setProductSummaryInformations(infos); 
end example
 

Because you are using the objects retrieved in Listing 17-2, the name property was filled in (as identified by the keys submitted to the retrieval method). As aclient, you only want to modify the retail price, not the name. As a result, you null out the name field so that the service implementation does not think you are changing this data. On the other hand, you do not null out the sku field. This is the primary key that identifies the product to modify; without this information, the service implementation could not locate the proper object to modify.




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