Implementing a Collection Sample


The theme of a collection of customers will continue for the sample implementation presented in this chapter. In the previous chapter, you went through a detailed scenario of business object deployment and the structure of the Simple Access Object Protocol (SOAP) messages that flow between the client and the server.

For this chapter, you will assume that deployment of the service implementation as a Web Service is less interesting than the structure of the service and how to access it from Java. This is a subtle change in tempo for the book, but it is necessary when you realize that Web Services are merely architecture adapters that tools generate for you. The real work becomes building implementations that are consumable by other languages yet allow you to leverage the mechanisms of an individual language for implementing and consuming the Web Service.

CustomerCollectionImpl is your service implementation class; it contains instances of CustomerImpl classes. The CustomerImpl class contains an AddressImpl , an instance of CustomerInformationImpl and some simple types, mostly strings. AddressImpl contains strings, and CustomerInformationImpl contains several more nested complex types. Figure 7-3 shows the entire class diagram.

click to expand
Figure 7-3: Customer collection implementation

From this hierarchy, an instance of CustomerCollectionImpl serves as the point object for the Web Service. A parallel hierarchy of serializable JavaBeans exists on the client after deployment of the Web Service and the creation of the client-side classes using WSDL2Java. These classes allow the client to create local data and call methods on the customer collection Web Service, as described in previous chapters.

For your implementation, there is an interesting side effect of your JDO usage. The association between the collection and the customer instances is an indirect relationship that works through the JDO persistence manager. The collection implementation queries extents that represent collections of customers. Figure 7-3 shows the logical structure rather than the actual physical implementation of the system.

Understanding Service Implementation Details

The CustomerCollectionImpl class contains several interesting characteristics. Listing 7-2 is not the complete source code for the class, but it is enough for you to get a feel for the implementation. Of particular interest is the series of query methods: getCustomer, getCustomers, getCustomersLastFirst , and getCustomersLast .

The difference between the getCustomer method and the getCustomers method lies in the expected set of objects returned from the method. The getCustomer method must return zero or one instance because of the unique key on the parameter list. The other methods do not guarantee a single instance and, therefore, return arrays.

A second point to note with the retrieval methods is the lack of method overloading. Overloading methods works well in object-oriented languages, but you cannot guarantee that only object-oriented languages will access your application. Rather than place a burden on the user of the Web Service, this code limits the use of overloading to ease usage of the Web Service.

Listing 7-2: Customer Collection Implementation
start example
 public class CustomerCollectionImpl {  public void removeCustomer(CustomerKey key) {      // see implementation in sample code  }  public CustomerKey addCustomer(CustomerImpl customer) {   CustomerKey key = null;   if (customer.getCustomerId() == null) {    customer.setCustomerId(       KeyGenerator.generateKey(KeyGenerator.CUSTOMER));   }   key = new CustomerKey();   key.customerId = customer.getCustomerId();   PersistenceManager pm = getPersistenceManager();   Transaction t = pm.currentTransaction();   t.begin();   pm.makePersistent(customer);   t.commit();   return key;  }  public CustomerImpl getCustomer(CustomerKey key) {      // see implementation in sample code  }  public CustomerImpl[] getCustomersLastFirst(      String lastName, String firstName) {      // see implementation in sample code  }  public CustomerImpl[] getCustomersLast(String lastName) {   PersistenceManager pm = getPersistenceManager();   Transaction t = pm.currentTransaction();   t.begin();   Extent ext = pm.getExtent(CustomerImpl.class, false);   String filter = "lastName==last";   String parameter = "String last";   Query q = pm.newQuery(ext, filter);   q.declareParameters(parameter);   Collection c = (Collection)q.execute(lastName);   pm.retrieveAll(c);   CustomerImpl returnCustomers[] = new CustomerImpl[c.size()];   Iterator i = c.iterator();   int j=0;   while(i.hasNext()){    returnCustomers[j] = (CustomerImpl)i.next();    j++;   }   q.closeAll();   t.commit();   return returnCustomers;  }  public CustomerImpl[] getCustomers() {      // see implementation in sample code  } } 
end example
 

The addCustomer method from Listing 7-2 is straightforward. The client cannot necessarily guarantee a unique key; therefore, the collection code will generate a unique key for each new customer and return this key to the client. In theory, you could use a social security number or other identifier, but there is no guarantee your customer has a social security number or other state-issued identifier.

The getCustomersLast is a more interesting method. Consider that JDO returns a Collection from the query of the customer extent. This method could return this collection directly to the client. On the other hand, by returning the collection you leave some ambiguity about how your architecture adapters will handle the collection interface along with the data contained in the collection. Rather than leave ambiguity in the interface, the method returns a type-safe array of classes that leaves no ambiguity about their type. This flattening of the data requires you to create a copy of the information contained in the collection and return it to the Web Service that invoked the method.

Querying a Collection

Several client-side scenarios are available to you; you will see a simple one using the getCustomers method. This code actually retrieves the customer collection from the Web Service and removes every customer using the removeCustomer method on the Web Service.

In this method, it is crucial to remember that the customer query returns copies of the collection to you rather than giving you an iterator to the collection that resides on the server. Generic queries that return large numbers of instances cause a heavy load to the network, server, and client in terms of memory and bandwidth. Looking at Listing 7-3, you can see that you use only a single field from each customer, the id field. The amount of data serializing and deserializing to retrieve the customer ID for each customer in the database is enormous .

Listing 7-3: Querying the Customer Collection
start example
 CustomerCollectionImplService service =          new CustomerCollectionImplServiceLocator(); CustomerCollectionImpl port =          service.getCustomerCollection(); Customer[] ci3 = port.getCustomers(); if(ci3!=null) {          for(int i=0 ; i<ci3.length ; i++){     CustomerKey ck = new CustomerKey();     ck.setCustomerId(ci3[i].getCustomerId());     port.removeCustomer(ck);   } } 
end example
 

A second point to note in Listing 7-3 is the use of the array structure. Arrays are not very dynamic; on the other hand, it did not use collection instances on methods. The client code points out another interesting reason to avoid collections as parameters and return types. Consider that you received a collection of objects in a dynamic collection that you could easily expand through an add method call. Changes to the collection only occur on the client side. Modification of the server- side collection must occur through the CustomerCollectionImpl interface. Using the static array structure on the return of the query methods may help you avoid programming errors when clients modify the locally held collection without submitting new data to the Web Service.




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