Implementing the Observer Pattern Using Web Services


Object-oriented computing uses observers heavily, and Web Services promise to use them just as heavily. There are some interesting twists to a Web Service implementation of the Observer pattern.

The first consideration is what the implication of the Web Services is on the base interfaces and concrete implementations of the Observer pattern. Essentially, each interface becomes a WSDL interface definition published in UDDI. Clients are then able to retrieve the WSDL file and build their own Observer implementation and, subsequently, register it with an Observable Web Service. Because neither the Observer nor the Observable knows each other's underlying service implementation architectures, both concrete implementations must be Web Services and adhere to the WSDL interface published by the Web Service owner. Further, registering the Observer with the Observable uses binding information rather than object references. This is a critical difference because binding information is not tied to an underlying service implementation architecture so you can safely pass it between Web Services.

Perhaps the most interesting corollary to the previous information is that the client must implement a Web Service interface. This requirement brings considerable weight to the client application deployment. You look at this requirement in more depth and learn ways to lighten your burden in Chapter 13, "Exploring the Physical Tiers Pattern" and Chapter 14, "Exploring the Faux Implementation Pattern." Figure 11-4 shows a sample deployment diagram for the scenario just discussed.

click to expand
Figure 11-4: Deployment scenario for the Observer pattern in Web Services

The Observer pattern can apply to any one of your four base types (business object, business object collection, business process, or asynchronous business process). For the sample implementation, you will enhance the ProductOrderManager from the case study one last time. By using the Observer pattern, you will end up publishing an Observer interface to UDDI in addition to the process interface. Clients will use the Observer interface, a ProductOrderObserver , to implement their own Web Service to receive change notifications for your processes and collections, including the ProductOrderManager Web Service.

Building an Observer

The observer for this sample is a simple Java class that prints a message upon having its update method called. You deploy the class, shown in Listing 11-2, with Apache Axis to make a stand-alone Web Service that is ready to receive update messages from an outside Web Service, which is a modified ProductOrderManager Web Service. You also want to take the WSDL interface from this class and publish it to UDDI to ensure that outside applications could build their own Web Service that receives messages from the ProductOrderManager Web Service.

Listing 11-2: ProductOrderObserver Implementation
start example
 public class ProductOrderObserver {     public ProductOrderObserver() {     }     public void update(String orderId){         System.out.println(             "Received an order change event for order: "+orderId);     } } 
end example
 

The update method in ProductOrderObserver receives an order identifier from the ProductOrderManager Web Service. With this simple mechanism, you can reuse the single observer instance to listen for changes to multiple processes. In the next section, you will notice that there is a similar mechanism for adding an observer to a particular business process because the ProcessOrderManager handles all product order business processes.

Enhancing a Business Process to Facilitate Observer Registration and Notification

There are two parts to enhancing ProcessOrderManager to be an observable Web Service. The first is to enhance the service interface and implementation, and the second is to adjust the interactions between the business processes and the manager. This book discusses only the first task. The second task, adjusting the inner workings of the business process manager, is actually an effort in applying the Observer pattern within a Java environment.

Adhering to the pattern description, you will add three new operations to the ProductOrderManager service implementation ” addObserver , removeObserver , and notify ”with only the first two being exposed through the Web Service interface. The addObserver and removeObserver operations keep track of observers, and notify centralizes the logic for delivering messages to the observers. Listing 11-3 contains the implementations of the addObserver and removeObserver operations, and Listing 11-4 contains the notify implementation.

Observer maintenance in this example is an exercise in Hashtable and Vector maintenance. You would likely use a more robust mechanism, such as persistent objects, because of the inability of clients to realize when they need to reregister with the Web Service if the service implementation goes down and loses its registrations. In Listing 11-3, a Hashtable ( listeners ) maintains a set of vectors keyed on orderId . Each vector contains URLs identifying the location of the observers interested in the change of state for a particular business process.

Listing 11-3: Observer Maintenance
start example
 public void addObserver(String orderId, String subscriptionUrl){         Vector orderListeners = null;         orderListeners = (Vector)listeners.get(orderId);         if(orderListeners==null){             orderListeners = new Vector(2);             listeners.put(orderId, orderListeners);         }         if(!orderListeners.contains(subscriptionUrl)){             try {                 URL url = new URL(subscriptionUrl);                 orderListeners.add(url);             } catch (MalformedURLException mue){                 mue.printStackTrace();             }         }     }     public void removeObserver(String orderId, String subscriptionUrl) {         Vector orderListeners = null;         orderListeners = (Vector)listeners.get(orderId);         if(orderListeners!=null){             orderListeners.remove(subscriptionUrl);         }     } 
end example
 

Upon discovery of a change to the state of one of the business processes managed by the ProductOrderManager , the Web Service calls the update method on any registered Web Services. For each URL registered as an observer through the addObserver operation, the observable builds an architecture adapter with the appropriate URL from the registration list. After building the architecture adapter, the observable calls the update method on the target Web Service with the order identifier of the order that changed state. You isolate all of the notification code in a notify method that is local to the ProductOrderManager class, as shown in Listing 11-4.

Listing 11-4: Notification Process Observers of Changes
start example
 protected void notify(String orderId){          Vector orderListeners = null;          orderListeners = (Vector)listeners.get(orderId);          if(orderListeners!=null){              for(int i=0 ; i<>orderListeners.size() ; i++){                  try {                      ProductOrderObserverService service =                          new ProductOrderObserverServiceLocator();                      ProductOrderObserver port =                          service.getProductOrderObserver(                              (URL)orderListeners.elementAt(i)                          );                      port.update(orderId);                  } catch (Exception e){                      e.printStackTrace();                  }              }          } } 
end example
 
Note  

The link between changes to a business process and the notification process from Listing 11-4 is available in the source code accompanying this book.

Running the New Web Services

With the registration mechanism and deployed observer, you can order products and register the observer with one or more of the business processes built to support the product order. Listing 11-5 illustrates the creation of the product order (the same code from the last two chapters) and adds the observer in the last line of code, which is the call to addObserver .

Listing 11-5: Registering an Observer from a Client Program
start example
 ProductOrderManagerService service =       new ProductOrderManagerServiceLocator(); ProductOrderManager port = service.getProductOrderManager(); String customer = "1035664203330"; String productSkus[] = {"1035664206840"}; int quantity[] = {2}; String jobIdentifier = port.createProductOrder(        customer,        productSkus,        quantity); port.addObserver(        jobIdentifier,        "http://localhost:8080/axis/services/ProductOrderObserver"); 
end example
 

Listing 11-5 presents several interesting problems that are not initially obvious. First, the code is not a part of the Observer Web Service, but it takes responsibility for registering the Observer Web Service with the Observable Web Service. This implies that the client code knows the address of the observer. Keeping the WSDL file nearby the client with the binding information addresses this problem. Second, there is no route between the Web Service running within the Apache Tomcat process and a client program running within its own process. Consequently, notifications delivered to the observer go unacknowledged by a client program. The Physical Tiers pattern addresses the second problem. Chapter 13, "Exploring the Physical Tiers Pattern" and Chapter 14, "Exploring the Faux Implementation Pattern," elaborate on this problem.




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