Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Build asynchronous applications with the Distributed Event-Based Architecture for Web Services

Implement the Observer pattern in the web services realm with this alphaWorks technology

Francis Geysermans, Solution Architect, IBM e-Business Solutions Center
Francis Geysermans is an e-business architect with the IBM EMEA Advanced Technical Support e-Business Solutions Center in La Gaude, France. He has 12 years of software development experience as a developer and architect. Francis has worked for Manpower, Belgacom, and SchlumbergerSema, among others, and was a founding partner and VP of Pacc, an Internet and Web design consulting company. His current work at IBM focuses on Web and enterprise application modelisation, architecture, and design. He works with partners and customers, consulting, mentoring, coding, and teaching. Francis received his master's diplôme from the EPHEC in Brussels. You can contact Francis at GEYSERMA@fr.ibm.com.
Jeff Miller, e-Business Architect, IBM Developer Relations
Jeff Miller photo
Jeff Miller is a software consultant with IBM ISV & Developer Relations Worldwide Developer Skills program. He has over 24 years of software development experience as an electrical engineer, software developer and architect. His focus at IBM is Java EE application architecture, design, development, Web services, SOA and security. Jeff consults, codes, teaches, writes technical articles and speaks to universities and groups. He is an IBM-certified On Demand Solution Designer and Solution Technologist, an IBM Certified Solution Designer -- Service Oriented Architecture, and is IBM-certified on Rational Application Developer and WebSphere Application Server. Jeff is a CompTIA Security+ Certified Professional. He received his Masters degree in Computer Science from Rensselaer Polytechnic Institute.

Summary:  Web services are already proving their usefulness in real-world applications. However, the current standard web service model is a synchronous one, based on a request/response architecture. Now, thanks to a new framework available from alphaWorks, you can overcome this synchronous limitation. In this article, Francis Geysermans and Jeff Miller outline the Distributed Event-Based Architecture for Web Services, which will help you build web services applications based on the Observer pattern.

Date:  10 Mar 2003
Level:  Introductory

Activity:  11957 views
Comments:  

The advent of web services is revolutionizing enterprise application communication, expanding applications' reach and making it much easier for disparate applications to communicate with one another. The beauty of a web service is that it can be accessed with a remote procedure call mechanism that has self-describing interfaces decoupled from implementation. Services adhere to an architecture based on open Internet standards, and can be published and discovered dynamically.

Web service interfaces can be described using Web Services Description Language (WSDL), an XML-based vocabulary whose data types and structures can be realized in multiple programming languages. The dynamic nature of web services is partially based on a clear-cut division between service requesters and service providers -- which in older terminology were called clients and servers. The provider can offer a web service and the requester can look up, bind to, and invoke that web service. The process is unidirectional: one component makes the call and the other responds. Though the communication is flexible, the stateless process is fixed. Normally there is a request followed by a synchronous response. Regardless of the higher-level choreography underway, each web service invocation involves a request sent by a service requester followed by a response sent by the service provider -- a synchronous request/response model. Though web service discovery can be dynamic, the web service provider still needs to publish the interface of the web service in one way or another. In this sense, the use of web services is fixed, requiring an initial offering of the interface of the web service, followed by either development time or runtime discovery of the web service.

In this article, we'll show you how to overcome this synchronous limitation. We'll introduce a Java framework that you can use to build a variety of asynchronous architectures with web services. You can download the code that accompanies this article, along with an FAQ and other resources, from alphaWorks; see the Resources section below for a link.

The Observer pattern

In application architecture, a common technique for reducing coupling between components that must communicate with each other is to use a design pattern called the Observer. The traditional Observer pattern specifies two primary actors: a subject and an observer. The observer is interested in state changes of the subject. Figure 1 illustrates how the Observer pattern works.


Figure 1. Observer pattern sequence diagram
Observer pattern sequence diagram

In this pattern, the observer wants to be informed of state changes on the subject. The observer registers with or attaches to the subject, which maintains a list of observers that it will notify when a particular state change occurs. At an overall level this is an asynchronous sequence, since the first attach() method call goes in one direction.

After attaching to the subject, the observer proceeds with its own processing. At some unspecified later time, when the subject's state changes, the subject notifies the observer of the change event with the update() method callback.

Thus, at a high level, the Observer pattern provides a simple asynchronous model. Figure 2 shows the relationships among the classes.


Figure 2. Class relationships
Class relationships

The Observer pattern and web services

A unique use of the Observer pattern is to implement it using web services. In Figures 1 and 2, consider the attach(), update(), and detach() method calls to be web services. (setState() and getState() can be web services as well, although this is not relevant for now.) If each is a web service call, then by definition, each is a synchronous web service invocation consisting of a request and a response. Figure 3 illustrates this. The only difference between Figures 2 and 3 is that in the former the classes are treated as standard design pattern components, whereas in the latter they are treated as web service components.


Figure 3. Web service component relationships
Web services component relationships

One thing to note in Figure 3 is the optional use of a data bean, which describes the event and contains the changed state, passed as a parameter to the ServiceRequester.update() method. This can take the place of the service requester calling back to the ServiceProvider.getState() method.

In web services terminology, the observer is initially the service requester and the subject is initially the service provider. However, the subject and observer become both clients and servers of each other when they are implemented using web services. During the update() call, the subject is initiating a callback to the observer; thus, at that point, the subject is the service requester and the observer is the service provider. Each component is a service requester at some points in the process and a service provider at others. Hence, by implementing the observer callback pattern using web services, we provide a new mechanism for an asynchronous architecture over a synchronous infrastructure.


The Distributed Event-Based Architecture for Web Services

The implementation of this pattern over web services is compelling because it suggests an architecture that has unique flexibility. This architecture for web services is called the Distributed Event-Based Architecture, or DEBA. DEBA for web services benefits from the decoupled nature of web services and the asynchronous nature of the Observer pattern.

DEBA is characterized by distributed active components waiting for events. Systems built on DEBA can be thought of as always moving towards equilibrium, with participants joining and leaving at will, based on application logic. DEBA components are able to act as subjects, called observables, and as observers, not based on what they publish about themselves but based on what they are -- namely, extenders of one of the DEBA base classes.

DEBA components can be both observables and observers. Each observer decides what to observe, so the overall workflow is based on individual decisions rather than an overriding flow controller. Thus, DEBA provides a truly dynamic workflow model that is highly decoupled and does not need to be described in advance.

DEBA component can establish peer-to-peer, one-to-many, or many-to-many relationships with one another. A variety of structures are therefore possible. Figure 4 shows a distributed state machine in which each observer determines its own subsequent action based on its current state and the state change of its corresponding observable(s).


Figure 4. DEBA distributed state machine
DEBA distributed state machine

As notification of state changes are received at an observer (at the arrowhead), the observer, acting as an observable, can decide which of its own observers it will notify further.

DEBA components can act as routers, as illustrated in Figure 5.


Figure 5. A DEBA component acting as a router
A DEBA component acting as a router

In Figure 5, the router node in middle is the only observer of the observables on the left, and each observer on the right only observes the router.

Figure 6 depicts bidirectional workflow implemented by the middle node. The central controller node could use a flow language to store the desired workflow sequences.


Figure 6. DEBA workflow with a central controller
DEBA workflow with a central controller

In Figure 7, we combine some of the models already presented, illustrating DEBA's flexibility. A workflow model central node controls the nodes participating in a distributed state machine and two router models; the entire system is implemented with DEBA. DEBA is unique because it allows the inherently synchronous web services model to provide the foundation for such an entirely asynchronous architecture.


Figure 7. A composite DEBA model
A composite DEBA model

The capabilities of the DEBA event model are quite different from those that the limited WSDL Notification operation can provide. In the Notification operation, the endpoint (i.e., the service provider) sends a message. It is a one-way callback. All messages in DEBA are request-response operations. It is the Observer pattern on top of the base web services infrastructure that gives DEBA its callback capability. (The bindings for the Notification operation are not defined in WSDL 1.1, however. For more information on WSDL Notification, see the links to the WSDL 1.1 specification in the Resources section below.)


The DEBA framework

We've implemented a framework for DEBA for web services as set of Java classes. The primary components are the Observer and Observable classes and their support classes. Table 1 shows the correspondence between the Observer pattern, the standard web services model, and the Observer pattern's implementation in the DEBA framework classes.

Table 1. DEBA framework classes as they correspond to the Observer pattern

Observer pattern Web services DEBA framework
Subject ServiceProvider AbstractWebObservable
Subject.attach() ServiceProvider.addRequester() AbstractWebObservable.addObserver()
Subject.detach() ServiceProvider.removeRequester() AbstractWebObservable.deleteObserver()
Observer ServiceRequester AbstractWebObserver
Observer.update() ServiceRequester.update() AbstractWebObserver.update()

As shown in Table 1, when implemented in the Java DEBA framework, the subject becomes AbstractWebObservable, a subclass of java.util.Observable. The observer becomes AbstractWebObserver, a partial implementation of java.util.Observer. Thus, the Observable and Observer classes are the basis of the framework. Since an observer needs to be able to access an observable, the observer client can use two primary framework helper classes to make that easier. The RemoteObservable and (from a SOAP infrastructure point of view) the RemoteObservableProxy classes run in the same JVM as the observer client. The RemoteObservableProxy accesses the user implementation of the AbstractWebObservable as a web service (more on this coming up; see Step 3 in Figure 9 for details).

There are two layers of proxies in the DEBA framework: SOAP proxies and the framework's own, all packaged in deba.core. The SOAP proxy classes have Proxy as part of their name. In Figures 8 through 11, the initial service provider classes are on the left and the service requester classes on the right. (In Figures 9 and 11, these are represented as JVM 1 for the provider and JVM 2 for the requester, but this of course applies only to the DEBA framework, and a non-Java requester or provider can certainly participate at runtime.)

Also note that in these figures the MyObservable and MyObserver classes represent sample user implementations built on the DEBA framework. These two example classes should be used as guidelines for using the framework. We'll discuss this further in a little while.

Figure 8 shows the main components around the observable side of the framework.


Figure 8. Class model for the observable components
Class model for the observable components

Instances extending the AbstractWebObservable class implement the actual service provider. AbstractWebObservable maintains a vector of RemoteObservers (see Figure 10) in the form of URI/URL pairs. At notification time, each RemoteObserver on this list will be called and updated as a web service.

Instances of the RemoteObservable and RemoteObservableProxy classes are invoked on the service requester side. Names that start with Remote indicate classes that live at the service requester but represent or are proxies for the observable at the service provider. The RemoteObservable class is a wrapper above the generated SOAP proxy allowing an even greater degree of freedom for client application classes from the SOAP infrastructure. The RemoteObservable class uses its corresponding proxy to:

  • Store the observableURI and observableURL of the observable service provider
  • Store the observerURI and observerURL of the observer it represents (e.g., MyObserver)
  • Invoke the underlying SOAP web services request and receive the synchronous response

The URI/URL combination plays the role of object reference in a local implementation.

Not shown in Figure 8 is an externalization (Strategy pattern) of a validation class used by the RemoteObservable to verify that the URL of the service provider is valid. DEBA is able to support variations in the web services implementations and various types of precall checking by externalizing validation. And the validation class itself could be accessed as a web service. We'll discuss this class in more detail in a bit.

Figure 9 illustrates the flow of an observer registering with or attaching to an observable. Using the DEBA framework, developers extend AbstractWebObservable to implement their own observable web services on top of the framework. In Figures 8 and 9, the MyObservable class represents such an extension.


Figure 9. Observer attaching to an observable
Observer attaching to an observable

In Figure 9, the user classes -- specifically MyObserver and MyObservable -- are emphasized. To add itself as an observer, the MyObserver user class (or, more accurately, its superclass, AbstractWebObserver) calls an instance of RemoteObservable, which represents the remote service provider. The RemoteObservable.addObserver() method is shown in Listing 1.

				
    public void addObserver(String observerEndPointURL, String observerURI) 
        throws Exception
    {
        this.soapProxy.addObserver(observerEndPointURL, observerURI);
    }

RemoteObservable uses RemoteObservableProxy as a standard SOAP proxy to do the actual communication with the service provider class, MyObservable (actually calling a method implemented on its superclass, AbstractWebObservable). The addObserver() method of RemoteObservableProxy passes the observerEndPointURL and observerURI parameters via the SOAP call. Later, when an event that warrants notification occurs, the MyObservable class will notify all observers (as we'll see in Figure 11).

Figure 10 describes the class model for the observer components. Once again, the classes making up the initial service provider are on the left and classes for the initial service requester are on the right. These classes correspond closely to the observable components. The one example user class, MyObserver, extends AbstractWebObserver. For simplicity, the externalized validation class does not appear in Figure 10.

You can see the flow of an observable calling back to an observer in Figure 11. Using the framework, developers extend the AbstractWebObserver class to implement their own observer service requester on top of the framework. This is illustrated by the MyObserver class in Figures 10 and 11.


Figure 10. Class model for the observer components
Class model for the observer components

Figure 11. Observable updating an observer
Observable updating an observer

The service provider state can be passed to the service requester directly in the event parameter of the update() method rather than as a separate call to getState(). Alternatively, there can be a web service on the service provider implementing the getState() method, to which the service requester calls back to retrieve the changed state indicated by the update() method. This callback could occur directly within MyObserver's update() method.

We've mentioned the validation classes a couple of times. Figure 11 doesn't show the whole picture. In order to reduce the possibility of exceptions resulting from invalid callback URLs and URIs, or to perform any other type of checking before the update callback of an observer, the framework uses an additional class, DefaultUpdateStrategy, which is illustrated in Figure 12.


Figure 12. DefaultUpdateStrategy
DefaultUpdateStrategy

update(), shown in Listing 2, is the key method of the DefaultUpdateStrategy class.

				
    public void update(Observable observable, Object state) 
    {
        // Do any validation of state or URLs/URIs in this method.
        AbstractWebObservable o = (AbstractWebObservable)observable;
        try 
        {
            String stateString = (String)state;
            this.observer.getSoapProxy().onEvent(o.getEndPointURL(),
                                                 o.getObservableURI(), stateString);
        }
        catch (Exception e) 
        {
            System.out.println(e.toString());
        }
    }

It is actually DefaultUpdateStrategy that calls the RemoteObserverProxy.onEvent() method, which then makes the SOAP call back across the network to the Observer class's onEvent() method (or, more accurately, the onEvent() method of its superclass, AbstractWebObserver). The bottom of Listing 4 below shows how AbstractWebObserver.onEvent() simply calls update(). Figure 13 shows the actual flow using the DefaultUpdateStrategy class, which of course can be substituted with another more specific validation class. A similar Strategy pattern could be used on the observer side as well.


Figure 13. Actual update flow, including DefaultUpdateStrategy
XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width.


Code walkthrough

Now let's look at some code to see how it all works. It's quite simple, actually. We'll start with the basic observable component modeled in Figure 8. Listing 3 is the AbstractWebObservable class, a subclass of java.util.Observable that implements a SOAP mechanism to access the observer. It maintains the vector of registered observers, adding and deleting them as circumstances dictate.

				
package deba.core;

import java.util.Observable;
import java.util.Iterator;
import java.util.Vector;

public class AbstractWebObservable extends Observable 
{
    // Add an observer to the vector of observers
    public void addObserver(String observerEndPointURL, String observerURI)
    {
        RemoteObserver o = this.getRegisteredObserver(observerEndPointURL, observerURI);
        if (o == null) 
       {
            o = new RemoteObserver(observerEndPointURL, observerURI);
            this.addObserver(o);
            this.observers.addElement(o);
        }
    }

    // Remove an observer from the vector of observers
    public synchronized void deleteObserver(String observerEndPointURL, String observerURI)
    {
        RemoteObserver o = this.getRegisteredObserver(observerEndPointURL, observerURI);
        if (o != null) 
       {
            this.deleteObserver(o);
            this.observers.remove(o);
        }
    }

    // Return the registered observer at the passed endpoint URI and URL
    protected RemoteObserver getRegisteredObserver(String observerEndPointURL,
                                                   String observerURI)
    {
        Iterator i = observers.iterator();
        RemoteObserver o = null;
        RemoteObserver temp = null;

        while (i.hasNext()) 
       {
            temp = (RemoteObserver)i.next();
            if (temp.getEndPointURL().equals(observerEndPointURL) &&
                temp.getObserverURI().equals(observerURI)) 
           {
                o = temp;
                break;
            }
        }
        return o;
    }

    // Get this observable's endpoint URL (where is the rpcrouter to this observable?)
    public String getEndPointURL() 
    {
        return endPointURL;
    }

    // Set this observable's endpoint URL
    public void setEndPointURL(String endPointURL) 
    {
        this.endPointURL = endPointURL;
    }

    // Get this observable's URI (what is this observable's web service name?)
    public String getObservableURI() 
    {
        return observableURI;
    }

    // Set this observable's URI
    public void setObservableURI(String observableURI) 
    {
        this.observableURI = observableURI;
    }

    // The URL of this observable, e.g. http://localhost:8080/debaWeb/servlet/rpcrouter
    private String endPointURL;

    // The URI of this observable, e.g. http://tempuri.org/example.Myobservable
    // or urn:example.MyObservable, etc.
    private String observableURI;

    // The list of registered observers
    private Vector observers = new Vector();
}

As you can see, AbstractWebObservable is concerned with managing observers. AbstractWebObservable works closely with its superclass, java.util.Observable, which contains the actual notifyObservers() method. When RemoteObserver and RemoteObserverProxy helper classes are mixed in, there isn't much for a user-written observable to do except handle its own business logic, followed by periodically calling notifyObservers(state).

Listing 4 contains the code for the basic observer component.

				 
package deba.core;

import java.util.Observer;
import java.util.Observable;

abstract public class AbstractWebObserver implements Observer 
{
    // The one method that must be implemented by subclasses
    public abstract void update(Observable observable, Object state);

    public void register(String observableEndPointURL, String observableURI) 
        throws Exception 
    {
        RemoteObservable o = new RemoteObservable(observableEndPointURL, observableURI);
        o.addObserver(this.getEndPointURL(), this.getObserverURI());
    }


    public synchronized void unRegister(String observableEndPointURL, String observableURI) 
        throws Exception
    {
        RemoteObservable o = new RemoteObservable(observableEndPointURL, observableURI);
        o.deleteObserver(this.getEndPointURL(), this.getObserverURI());
    }

    public String getEndPointURL() 
    {
        return endPointURL;
    }

    public void setEndPointURL(String endPointURL) 
    {
        this.endPointURL = endPointURL;
    }

    public String getObserverURI() 
    {
        return observerURI;
    }

    public void setObserverURI(String observerURI) 
    {
        this.observerURI = observerURI;
    }

    public void onEvent(String observableEndPointURL, String observableURI, String state) 
    {
        RemoteObservable o = new RemoteObservable(observableEndPointURL, observableURI);
        this.update(o, state);
    }

    /* These are the URL and URI of the observer itself, for example
    endPointURL = http://localhost:8080/debaWeb/servlet/rpcrouter
    observerURI = http://tempuri.org/example.MyObserver */
    private String endPointURL;
    private String observerURI;
}

AbstractWebObserver, like its counterpart AbstractWebObservable, is responsible for registering and unregistering with an observable. Because it has setters and getters for its own URL and URI, AbstractWebObserver is location-independent reusable code. It is also independent of the observable that is to be observed, for which the URL and URI are passed into the AbstractWebObserver.register() method. Since these two parameters are passed in, an observer is able to observe any number of observables. So, like its counterpart, a user-written subclass of AbstractWebObserver doesn't have much to do except handle the business logic in its own update() method. And speaking of the update() method, notice the AbstractWebObserver.onEvent() method in Listing 4. We'll see how that's used in a moment.


Exceptions in DEBA for Web Services

Since there are no compile-time checks possible, there are three ways for an observable to check that Observer.update() exists:

  • At registration (attach) time. At this point, the observable can reduce later exceptions by checking the WSDL file of the observer, testing the callback method functionality to the observer, or delegating the actual validation test using the Strategy pattern and having the strategy test in some way.
  • At runtime through a SOAPException fault. The lazy way would be to try the callback to observer.update(); if the call fails, this suggests that the method does not exist. In such a case, the fault message would be "Method 'update' is not supported." However, this requires a network call -- the failed attempt to call update() -- which ideally should be avoided.
  • Through a WSDL extension. It would be nice to have an implements statement in WSDL, e.g. implements Listener. This would be added when the WSDL and proxy are generated, where the Listener WSDL has an update() service. In this case, if the update() method is not supported, the observable could remove the observer from list.

There is a great deal of flexibility in the DEBA framework to handle exceptions. We've provided a default validation callout mechanism in the DEBA framework to limit exceptions caused by the lack of availability of the observable or observer.


The example application

Included in the bundle of code available at the alphaWorks site is an example application that can be used to test the DEBA framework. It can also serve as a basis from which you can implement your own DEBA framework applications. The classes in the example application are:

  • MyObservable.java
  • MyObservableProxy.java
  • MyObserver.java
  • MyObserverProxy.java

All are in the example Java package. The corresponding WSDL is also included. example.MyObservable is a subclass of AbstractWebObservable (itself a subclass of Observable). MyObservable starts a thread that reads the system clock. Once a second, it calls notifyObservers() to update any registered observers with the current time. (In production Web applications, threads should be managed by the Web container, not the application. But this example is for illustration only.) You can examine the code in Listing 5.

				   
package example;

import java.net.URL;
import deba.core.AbstractWebObservable;
import java.util.Date;

public class MyObservable extends AbstractWebObservable implements Runnable 
{
    public MyObservable()
    {
        super();
    }

    public String getState() 
    {
        return "An event occurred at " + time.toString();
    }

    public void run() 
    {
        while(this.shouldRun) 
        {
            time = new Date();
            System.out.println("The observable says : " + time);
            super.setChanged();
            this.notifyObservers(getState());
            try 
            {
                thread.sleep(1000);
            } 
            catch (Exception e) 
            {
                e.printStackTrace();
            }
        }
    }

    public void stopClock() 
    {
        this.shouldRun = false;
        this.thread = null;
    }

    public void startClock() 
    {
        if (this.thread==null) 
        {
            this.shouldRun = true;
            this.thread = new Thread(this);
            this.thread.start();
        }
    }

    private static Thread thread = null;
    private static boolean shouldRun = false;
    private Date time = new Date();
}

From Listing 5, you can see that, in order to write an observable that uses the DEBA framework, you have barely anything to do about the underlying SOAP infrastructure. The only code required is the line that is in blue boldface, the call to notifyObservers(). Extending AbstractWebObservable does all the rest for you.

There are also generated sample SOAP test client JSPs for MyObservable and MyObserver, compliments of WebSphere Studio Application Developer (see Resources). Each Result.jsp uses one of the proxy classes to communicate via SOAP with the target implementation, MyObserver or MyObservable. Using the combination of test clients against both halves of the example application, it is possible to invoke the MyObserver web service to register with the MyObservable web service, start the MyObservable thread running, and watch the alternating output from both objects on the system console, as shown in Listing 6.

				
[12/29/02 17:59:56:265 EST] 4ecbbd62 SystemOut  U The observable says : 
Sun Dec 29 17:59:56 EST 2002
[12/29/02 17:59:56:315 EST] 6d49fd63 SystemOut  U The observer is updated by deba.core.RemoteObservable@4d95fd61, event : 
An event occurred at Sun Dec 29 17:59:56 EST 2002
[12/29/02 17:59:57:346 EST] 4ecbbd62 SystemOut  U The observable says :
 Sun Dec 29 17:59:57 EST 2002
[12/29/02 17:59:57:407 EST] 6d49fd63 SystemOut  U The observer is updated by deba.core.RemoteObservable@5c667d66, event :
 An event occurred at Sun Dec 29 17:59:57 EST 2002
[12/29/02 17:59:58:448 EST] 4ecbbd62 SystemOut  U The observable says :
 Sun Dec 29 17:59:58 EST 2002
[12/29/02 17:59:58:568 EST] 6d49fd63 SystemOut  U The observer is updated by deba.core.RemoteObservable@25ddbd6d, event :
 An event occurred at Sun Dec 29 17:59:58 EST 2002
[12/29/02 17:59:59:610 EST] 4ecbbd62 SystemOut  U The observable says :
 Sun Dec 29 17:59:59 EST 2002
[12/29/02 17:59:59:670 EST] 6d49fd63 SystemOut  U The observer is updated by deba.core.RemoteObservable@61947d62, event :
 An event occurred at Sun Dec 29 17:59:59 EST 2002
[12/29/02 18:00:00:701 EST] 4ecbbd62 SystemOut  U The observable says :
 Sun Dec 29 18:00:00 EST 2002
[12/29/02 18:00:00:761 EST] 6d49fd63 SystemOut  U The observer is updated by deba.core.RemoteObservable@14707d63, event :
 An event occurred at Sun Dec 29 18:00:00 EST 2002

And so on. To use both test clients running in WebSphere Studio or externally in WebSphere Application Server, here are some values that need to be entered in the JSP input page. (DEBA and this example application should actually work in any J2EE-compliant application server that can use Apache SOAP for its web services runtime.) Modify these as necessary:

  • Testing MyObservable -- the observable's own values:

    • endPointURL = http://localhost:8080/debaWeb/servlet/rpcrouter
    • observableURI = http://tempuri.org/example.Myobservable


  • Testing MyObserver -- the observer's own values:

    • endPointURL = http://localhost:8080/debaWeb/servlet/rpcrouter
    • observerURI = http://tempuri.org/example.MyObserver


  • Testing MyObserver.register():

    • observableEndPointURL = http://localhost:8080/debaWeb/servlet/rpcrouter
    • observableURI = http://tempuri.org/example.Myobservable

Notice that we have both test clients running on the same server -- inside WebSphere Studio Application Developer 4.0.3, in this example. To test both together, run the MyObservable test client on the server and set its endPointURL and observableURI values. Then run the MyObserver test client, set its corresponding values, and then register it with MyObservable. Finally, start MyObservable's clock to see output like that in Listing 6. There is a FAQ with the code on alphaWorks that explains in more detail how to use the example application and the included TestClients.


DEBA possibilities

Just as distributed systems are moving towards self-management, components in DEBA are as well. Clients and web services can participate in self-managed systems due to the architecture's flexibility. The DEBA architecture ties in very nicely with Grid architectures (see Resources) in that each component can join and leave the grid at will. As each listener is added, the grid expands. The system is a naturally morphing dynamic system in which each participant is responsible for its own participation, but can be additive if multiple participants of the same type are involved. So the DEBA architecture is naturally complementary to Grid computing.

You can implement the Strategy pattern using DEBA for web services. In this model, the strategy provider, as a standard, could periodically search UDDI for a special type of web service called a Request for strategy Service (RFSS web service). The strategy provider registers with the strategy requester, which can be considered a consumer of the strategy. The strategy provider, as a potential observer of a strategy consumer, looks for RFSS web services, checks the type of request, and registers for a callback to execute the particular strategy. Later, when consumers of the strategy providers need the providers to perform the particular strategy, the consumers, as observables, call back to the providers to perform the strategy operation. In this way, a consumer of Strategies can determine which of the strategy execution results best fits the desired result. The overall architecture is one of synchronous web services on top of an asynchronous callback event pattern -- the Distributed Event-Based Architecture for Web Services.

Another design pattern that lends itself well to DEBA is the Visitor pattern, which externalizes an operation that will be performed on another object, a group of objects, or a structure of objects. Since the operation is implemented separately from the objects on which it works, the operation can be changed without changing the target objects. Groups of operations can be packaged into an object called a visitor. The interaction between the target objects and the visitor can be implemented using DEBA.


Conclusion

DEBA, the Distributed Event-Based Architecture for Web Services, uniquely provides an asynchronous method of computing on top of web services, which as a technology provides the ultimate loose coupling of service requester and service provider. The DEBA framework is an implementation of this unique capability. In this article, we've explained the DEBA framework and how you can use it to implement a variety of flexible distributed application architectures using web services. Follow the links in Resources below to download the DEBA framework code and the sample code that accompanies this article. We hope you enjoy working with it!


Resources

About the authors

Francis Geysermans is an e-business architect with the IBM EMEA Advanced Technical Support e-Business Solutions Center in La Gaude, France. He has 12 years of software development experience as a developer and architect. Francis has worked for Manpower, Belgacom, and SchlumbergerSema, among others, and was a founding partner and VP of Pacc, an Internet and Web design consulting company. His current work at IBM focuses on Web and enterprise application modelisation, architecture, and design. He works with partners and customers, consulting, mentoring, coding, and teaching. Francis received his master's diplôme from the EPHEC in Brussels. You can contact Francis at GEYSERMA@fr.ibm.com.

Jeff Miller photo

Jeff Miller is a software consultant with IBM ISV & Developer Relations Worldwide Developer Skills program. He has over 24 years of software development experience as an electrical engineer, software developer and architect. His focus at IBM is Java EE application architecture, design, development, Web services, SOA and security. Jeff consults, codes, teaches, writes technical articles and speaks to universities and groups. He is an IBM-certified On Demand Solution Designer and Solution Technologist, an IBM Certified Solution Designer -- Service Oriented Architecture, and is IBM-certified on Rational Application Developer and WebSphere Application Server. Jeff is a CompTIA Security+ Certified Professional. He received his Masters degree in Computer Science from Rensselaer Polytechnic Institute.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=11762
ArticleTitle=Build asynchronous applications with the Distributed Event-Based Architecture for Web Services
publish-date=03102003
author1-email=GEYSERMA@fr.ibm.com
author1-email-cc=
author2-email=jeffmil@us.ibm.com
author2-email-cc=