CEP Breaking News, Articles, Feature Stories and Blog Posts

CEP on Ulitzer

Subscribe to CEP on Ulitzer: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get CEP on Ulitzer: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


cep Authors: Tony Shan, Liz McMillan, Bob Gourley, Charles Rich, AppDynamics Blog

Related Topics: CEP on Ulitzer

cep: Article

EVENT Management & Enterprise JavaBeans

EVENT Management & Enterprise JavaBeans

This is the first in a two-part series on Event management in large distributed applications built on top of Enterprise JavaBeans (EJB). This installment will cover the architecture and the implementation of a local (single VM) version of the event distribution system. The second article will implement an EJB version of the system that will handle distributed events from remote VMs.

One of the goals of Enterprise JavaBeans is to make it easy to write applications. Application developers won't have to understand low-level transaction and state management details, multithreading, resource pooling and other complex low-level APIs. In the nominal case this extrapolation of the complexities of building large, complex distributed applications has been accomplished well. It doesn't take much more effort to implement an interface to a database table object using EJB than it does to implement it locally. If the EJB object is deployed using a high-end EJB server, the object can be replicated among multiple machines, providing load balancing and fault tolerance with little or no effort on the bean developer's part.

The model that EJB is predicated on, transaction-based processing, works well in many circumstances, the most prominent being client/server and n-tiered systems in which the server layer manages some form of persistent store. A number of other distributed application needs, however, don't fit as well into the EJB model. One of them is event-based processing.

EJB still provides many benefits to applications that don't directly match the transaction-based EJB model. It just takes a bit more understanding of what EJB provides for you and what you have to do to get it to work. Event processing happens to be an application that begs for a middleware server but doesn't fall into the transactional model.

Events happen on a regular basis in our daily lives. We get up, go to work and so on. The same can be said of our software - events happen regularly in our software systems. The user logs into the application, requests a new client's data, etc. Some events, such as handling an order, are handled in the regular course of processing; others, such as an I/O failure, are considered exceptional processing.

In large distributed systems a frequent problem is that events often need to be processed by a component that resides far from the component that detected the event. Maybe the middle tier detected that the logon attempt failed, but a logging component on the server needs to know about this failure. On the other hand, the component that detected the problem shouldn't need to know what components are interested in this specific event. For distributed applications the event distributor needs to handle both the receiving and the transmitting of events to remote components.

In reviewing the strengths and weaknesses of EJB and how they fit in an event distribution subsystem, we can determine the following:

  • EJB allows remote components to send events to the event distribution system.
  • EJB doesn't provide a mechanism for the event distribution system to inform the remote components that an event has occurred (no callback mechanism).
  • The EJB server provides all the features required for a highly scalable, fault-tolerant, load-balanced application.
  • EJB's transactional model doesn't help us in the event distribution subsystem, since events are not transactional in nature.

    This article and its sequel will show you one possible way to handle these vast requirements in a simple, straightforward framework so that your application will be able to handle events as easily as it handles normal, transaction-oriented, multitiered processing.

    What Is an Event, Anyway?
    In most Java development circles, when event handling is discussed it's normally in association with the AWT event model. In the AWT model the component interested in the event (consumer) simply registers with the producer of events (producer). The producer then iterates its list of interested parties (consumers), sending the event to all who have registered with it. This is a classic implementation of the observer pattern, and it works well in an application that runs in a single VM.

    When an application begins to span multiple VMs, and components are created on the fly without notification to other components, the AWT model of tight coupling between the consumer of events and the producer of events gets to be unworkable. How does the consumer know that a producer of events has started on a machine somewhere else on the network?

    Consumers of events don't care who generated the event, just that the event occurred. If a database is out of space, the event consumer doesn't care what process detected that the database needs more disk space. It just knows that its job is to notify the administrator of this fact. Conversely, the event producer doesn't care who needs the event, or what they're going to do with it, just that the event was detected and that consumers may be interested in it.

    The mediator pattern can be used to alleviate the tight coupling in the basic event distribution model described above. To alleviate the tight coupling, a third component - the event distributor - is added to act as a mediator between the publisher and the consumer. The producer of events publishes the events to the distributor and thus doesn't know what objects are consuming the events. It just knows that they have been handed off to the proper component.

    Consumers of events, on the other hand, are notified when events they're interested in are received by the event distributor. The consumers don't know what object produced the event, just that it occurred.

    Thus we have three roles that exist in an event distribution system:
    1. Event Producers: Components that detect events and so inform the world
    2. Event Consumers:
    Components that handle events in some manner, e.g., passing them on to other consumers, notifying other applications or triggering some processing in the application
    3. Event Distributors: Distributors that maintain a list of interested consumers and pass the events to the consumers as they are produced

    By chaining event consumers together, an application manages the consumption of complex event hierarchies. Figure 1 shows the major components of the event distribution system. The three listed above are there, as well as the Event object itself.

    Class Diagram
    Figure 2 shows the class diagram for the event distribution system implemented in EJB. Notice that EventDistributor and EventConsumer are interfaces and the EventProducer doesn't even exist! Anyone can produce an event just by creating a new instance of an Event object and calling its publish method. The EventFilter class is an abstract class that implements both EventConsumer and EventDistributor.

    The normal mechanism for creating an event consumer is to extend the EventFilter class, providing a consume method that performs some filtration on the events that are passed on to the consumers that register with it.

    The Event, EventContext, EventConsumer, EventDistributor and EventFilter classes are the basic building blocks for local event distribution. In this article I'll implement these classes and their interfaces. The second article will explain the implementation of the rest of the classes diagrammed in Figure 2. However, for completeness, I'll discuss all of the classes here.

    Enterprise JavaBeans
    The distribution mechanism will be built on top of the classes in EJB. The EJB implementation of the event distributor is modeled as the EventController interface, which extends the EventDistributor interface and also provides the publish service so clients from any VM can inform the event distribution service of new events.

    The EventController is actually an interface as well as a class on the client machine (generated by the EJB compiler). The EventController interface is implemented on the server by the EventControllerBean (as well as the EventControllerHome). With these three classes and one interface, EJB can provide the global interface to all clients who wish to publish events or consume events that meet certain criteria.

    As I mentioned before, EJB has a severe limitation in the area of callbacks, so I've designed the class RemoteEventConsumer, which encapsulates the logic needed to provide a callback for the server when it needs to notify a consumer in another VM of the event. The last class shown in Figure 2 is the EventHelper class, which is used as a holder of two static methods that make the application programmer's job much easier.

    I'm not showing the relationship of Event to the other classes in the diagram as I don't believe it adds anything and it certainly clutters up the rest of the details.

    Event Contexts
    To delineate between different event types, one can create many subclasses of Event, or a type attribute can be added to the Event object. Implementing a large number of classes just to identify types of events is a design that causes application bloat. However, if different events have a vastly different state as well as behavior, they are best implemented as a class hierarchy.

    The design doesn't require either method to be implemented, and you can determine which method is best for your application. The sample implementation that I'll go over later will use an EventContext object to identify the event type. It will also use a dynamic set of attributes (implemented as a hashtable) to contain whatever data is required for this type of event. While this implementation meets my application's needs, yours may vary.

    Generally, events will exist within a context. For example, an invalid logon attempt is a specific type of security violation. This design requires that when a consumer is added to the event distribution system, its context has to be passed as an argument to the addEventConsumer method. For the example code I'll model the context in a string representation based loosely on URLs. Your application's needs may vary and you'll want to change how the context is represented. The URL approach works well for my needs as it's universally recognized and easy to parse.

    The event context hierarchy will match the set of event types produced in your application. For my application a subset of the tree looks like this:

    Security
    Security.Breach
    Security.Breach.InvalidLogin
    Security.IllegalAccessAttempt

    Resource
    Resource.Database
    Resource.Database.Corrupt
    Resource.Database.InvalidAttempt
    Resource.Database.NotFound

    Chart
    Chart.Update

    Inbasket
    Inbasket.NewMessage
    Inbasket.DeleteMessage

    Notice that the first two categories of events (Security and Resource) are generally considered errors and would for the most part be sent from the producer to some sort of administration tool (logging device, paging device, etc.). However, the last two types of events (Chart and Inbasket) are notification from the server to the client that some interesting data has been updated in some manner.

    The EventContext class is constructed by passing in a string containing one of these URLs; it provides all the functionality needed for the rest of the application to obtain all or some part of the context. This allows the rest of the application to be abstracted from the need to understand and parse event contexts.

    Why This Design?
    As with any design, there are advantages and disadvantages. Among the advantages:

  • It's simple. Simple solutions make the design easier to understand, implement and maintain.
  • It takes full advantage of EJB server strengths. It allows the EJB server to replicate the object and provide the fault tolerance, load balancing and other high-end server functionality.
  • It decouples the consumer from the producer. When two components are tightly coupled, the system is considered frail and brittle. Frail systems are hard to extend, and make maintenance difficult at best - impossible at worst.

    The most obvious disadvantage of this design is the central distributor component. Any design that has a single point of failure (as this design appears to have) is suspect. However, with the capabilities of EJB servers, this single point of failure is easily mitigated. The EJB server itself can replicate the distributor, thus reducing the risk of a single point of failure. Two weaknesses in standard EJB are exposed in this design:
    1. It doesn't handle nontransaction-based applications well (which is to be expected of a transaction-based standard).
    2. It doesn't provide callback functionality by default.

    In EJB parlance, one would remedy these weaknesses by building a custom EJB container that fits into the EJB server of choice. This article chooses another direction, that of working within the existing containers of the EJB Server and providing the extra functionality in the bean object itself.

    Proposed Solution
    Enough talk. Let's write the code and see how it works. For the rest of this article I'm going to describe how the base classes needed for event distribution in this model work. (I won't discuss the networking or EJB aspects of these classes until the next article.)

    Why This Design?
    As with any design, there are advantages and disadvantages. Among the advantages:

  • It's simple. Simple solutions make the design easier to understand, implement and maintain.
  • It takes full advantage of EJB server strengths. It allows the EJB server to replicate the object and provide the fault tolerance, load balancing and other high-end server functionality.
  • It decouples the consumer from the producer. When two components are tightly coupled, the system is considered frail and brittle. Frail systems are hard to extend, and make maintenance difficult at best - impossible at worst.

    The most obvious disadvantage of this design is the central distributor component. Any design that has a single point of failure (as this design appears to have) is suspect. However, with the capabilities of EJB servers, this single point of failure is easily mitigated. The EJB server itself can replicate the distributor, thus reducing the risk of a single point of failure. Two weaknesses in standard EJB are exposed in this design:
    1. It doesn't handle nontransaction-based applications well (which is to be expected of a transaction-based standard).
    2. It doesn't provide callback functionality by default.

    In EJB parlance, one would remedy these weaknesses by building a custom EJB container that fits into the EJB server of choice. This article chooses another direction, that of working within the existing containers of the EJB Server and providing the extra functionality in the bean object itself.

    Proposed Solution
    Enough talk. Let's write the code and see how it works. For the rest of this article I'm going to describe how the base classes needed for event distribution in this model work. (I won't discuss the networking or EJB aspects of these classes until the next article.)

    Interfaces
    Two interfaces, EventConsumer and EventDistributor, need to be implemented first. Listing 1 shows how the EventConsumer interface requires the consume method. An important note is that an EventConsumer extends the EventListener interface of Java.

    The EventListener interface, a little-used interface provided in the java.util package, doesn't implement any methods. Rather, it tags the interface or class as one that can be used by an EventListenerList derivative. The EventListenerList class, provided in the com.sun.java.swing.event package, contains all of the mechanisms needed to maintain and process callback lists.

    Listing 2 has the code for the EventDistributor interface. This interface, also very simple, has two methods - one to add a new consumer and another to remove a consumer from the list.

    Event Filter Abstract Class
    The code for the EventFilter class is shown in Listing 3. The class uses the EventListenerList class from swing (discussed above), but the rest of it is very straightforward. The constructor simply creates a list object to handle the consumers that will register with this object. The method consume is the abstract method that children will have to implement. The addEventConsumer method and the removeEventConsumer methods manage the contents of the EventListenerList object. Finally, a protected method called fireEventConsumers handles the actual sending of the event to all consumers currently registered in the list object. Derived classes will want to call this method if the event is deemed to be of interest to the consumer's children.

    Event and EventContext Classes
    Listing 4 contains the code for the Event class. The constructor builds the EventContext object and creates a hashtable object to handle the attributes to be added to this Event.

    The methods getAttributeByName and setAttributeByName are used to assign attributes a value and obtain the value from them. They both operate on a string for the attribute name and an object for the attribute value.

    The method isA takes a string that contains a context portion and returns a Boolean indicating whether this event is of that type.

    The publish method of the Event class is left empty at this time. It will be implemented when we get to the distributed version of the application. For this implementation the test drivers simply call the publish method on the distributor.

    The EventContext class is shown in Listing 5. Its constructor verifies that the URL passed in is of the proper type, and initializes its internal variables. The other two methods of importance are getComponent and nextComponent. The former returns a string with the current component of the URL. A component is defined as ending with either a forward slash (/) or a question mark (?) character. The forward slash is to separate static context information (e.g., Chart Update, FailedLogin). The question mark is used to separate dynamic information (much as it is in many CGI-based URLs). An example of this would be the identifier of the chart that has been updated.

    Distributor
    Listing 6 contains the BasicDistributor class (the real distributor will be provided as an EJB object in the next article but this one will work for local distribution). There are only two points to notice about this distributor. The first is that it is a subclass of EventFilter. The second is that its publish method simply calls fireEventConsumer.

    Consumers
    Listings 7 through 9 show three consumers. Two handle events of type "Security" (SecurityConsumer and FailedLoginConsumer); the third handles events of type "Chart Update." All three consumers print a message when they receive an Event whose context matches the one in which the consumer is interested. The FailedLoginConsumer performs a second check (the attack method) to see whether an oversimplified attack to break into the system is taking place. If so, it prints a message that an attack was detected.

    Test Driver
    Listing 10 contains a test driver to test these classes. It first creates an instance of the BasicDistributor class. Then all three of the consumers are registered, and finally some Events are created and published. The standard output generated by the test driver is shown in Listing 11. It should be run with and without the sleep call commented out to ascertain that the FailedLogin consumer works as described.

    Conclusion
    This code shows how simple it is to implement the basic functionality of this design. In the next segment I'll show how to extend this design on top of EJB so clients running in VMs distributed across the network can be both event consumers and event producers.

    References
    Matena, Vlada et al. (1998). Enterprise JavaBeans 1.0 Specification, Sun Microsystems, Inc., Palo Alto, CA, HYPERLINK http://java.sun.com/products/ejb/docs.html; http://java.sun.com/products/ejb/docs.html.

    Gamma, Helm, Johnson and Vlissides (1995). Design Patterns. Addison Wesley. ISBN 0-201-6336-2.

  • More Stories By Brian Zimbelman

    Brian Zimbelman is a snowboard instructor who moonlights as a senior architect at CyberPlus
    Corporation. He has been working on distributed systems since 1984 in C, C++ and now Java.

    Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.