In the previous post A Short Dissertation for EDA, I try to describe what is EDA, and why it is important.
Having established that EDA is indeed desirable, the next step is to determine how does one actually author an event-driven application. That is, what are the new abstractions, models, and design patterns that we should be using for EDA.
This is analogous to the problem that enterprises faced before Java EE came about. Before Java EE, developers would have to go long ways to create enterprise applications in Java. EE brought the necessary abstractions to facilitate this, by defining, among other things, the concepts of Session Beans, Entity Beans, Message-Driven Beans, and Enterprise Archives (i.e. EAR), which packaged and assembled these entities together.
So what abstractions do we need for EDA? That is, what would be a good programming model for creating event-driven applications?
To no surprise, the needed abstractions for the EDA programming model are:
- Event Sources and Event Sinks: application code that respectively generate events and receive events
- Streams: channels through which events flow, these channels don’t hold on to events, they actively stream events
- Processors: agents capable of processing events; the processing function or capability varies per agent
- Event Types: metadata defining the properties of events
Developers author event-driven applications by creating instances of these abstractions.
For example, consider a simple financial market pricing application. The goal of this pricing application is to determine what would be the best price to quote its clients that wish to trade stocks. This event-driven application creates two event sources, each receiving stock tick events from two different exchange markets. For sake of simplicity, the stock tick event contains only two event properties, its stock symbol (e.g. BEAS) and the latest traded price of the stock. The application further defines a processor that is configured to calculate and output the price of a stock symbol as being the average price received from the two event sources. Finally, there is a single event sink that publishes the calculated average stock price to a well-known JMS destination. The event sources are connected to the processor by having the event sources send events to a common stream that the processor listens to. Likewise, the processor is connected to the event sink by sending its event, the average stock price, to a shared stream that the event sink listens to.
The events flow from the two event sources, to the first stream, then to the processor, then to the second stream, and finally to the event sink. This flow of events across the EDA components forms a Event Processing Network (EPN).
An EPN is another abstraction of the EDA programming model. Formally, it is defined as:
- A directed graph of event sources, event sinks, streams, and processors; all collaborating towards fulfilling the function of a event-driven application. A EPN models horizontal composition and vertical layering of event processing.
Essentially, an event-driven application specifies a EPN, and the EPN assembles the EDA components (e.g. event sources, event sinks, processors, streams) together.
In the previous example, why do you need a stream to begin with? Couldn’t one just link together the event sources to the processor and then to the event sink? Actually, you could, but streams are useful for several reasons:
- Streams de-couple event sources from event sinks; this is similar to what a JMS destination does to JMS publishers and subscribers
- Streams manage the flow of events; this is done by providing queuing capability, with different rejection policies, and by providing different dispatching mechanisms, such as synchronous and asynchronous dispatching
As long as we are defining a new programming model, let’s also consider some other lessons that we have picked up along the way. For instance, it is important that the specification of a EPN be declarative, in another words, we want to assemble the event driven application by using some declarative mechanism, such as XML. Furthermore, it is also equally important that we keep the business logic de-coupled from the technology. Finally, we would like to pay-as-you-go for functionality. This latter means that if you don’t need a service, for example persistence or security, then you should not need to configure, reference (e.g. implement some technology interface), or otherwise be impacted by this service that you don’t intend on using to begin with.
WebLogic Event Server (EvS) has native support for this EDA programming model.
In EvS, a user application is a EPN, and has first-class support for creating event sources, event sinks, streams, processors, and event types.
Event sources and event sinks may be bound to different plug-able protocols, such as JMS. A event source or event sink that is bound to some specific protocol and is responsible for converting or passing along external events to and from the EPN are known as Adapters. Processors support BEA’s Event Processing Language. Java Beans may be registered in the EPN as Event Types. Streams support dynamic configuration of queuing and concurrency parameters.
The EPN itself is specified in a XML configuration file, called the EPN assembly file.
To be able to support the de-coupling of the user code from (infrastructure) dependencies, we have created our own dependency injection container, supporting both setter and constructor injection…
Just kidding! The EPN assembly file is a custom extension of a Spring framework context XML configuration file. What this means is that we leverage Spring’s Inversion of Control (IoC) container in its entirely, thus allowing one to seamlessly use Spring beans (and any other Spring feature, such as AOP) in the assembly of a EPN. EvS defines its own custom tags for the EDA components, hence a developer does not need to understand how the Spring framework works to create event-driven applications. The EDA programming model extensions to Spring is called Hot-Spring.
Back to our pricing application example, if you consider that the event sources and event sinks are re-using existing adapter implementations respectively that understand the market exchange protocol and JMS, then the whole EDA application can be authored without the developer having to write a single line of Java code! The developer only has to specify the EPN assembly file and configure the processor and adapters that it is using, all done through XML files or through a command-line interface (CLI) Administration tool.
What if the developer needs to use some custom business logic somewhere in the EPN? Well, the developer can always create Java POJOs (Plain-Old-Java-Objects) functioning in the roles of event sources or event sinks and assembled them together in the EPN. This reflects a common manifest from the Spring community, “simple things are easily done, complicated things are still possible”.
Finally, after having authored the EvS application, how do you deploy the application to EvS?
EvS deployment unit is a Spring-OSGi bundle. What is this? To begin with, a bundle is a regular JAR file. The Spring aspect of it means that this JAR file must contain a Spring context configuration, which in the case of EvS is a EPN assembly file, within the directory META-INF/spring. The second aspect of this is OSGi. OSGi is a service-oriented, component-based backplane. Why do you care? Well, generally speaking the developer does not need to care about this. Essentially, a OSGi bundle contains special OSGi entries in its MANIFES.MF file within the JAR file that specify, among other things, service dependencies and service advertisement. The fact that a EvS application is a OSGi bundle helps promote maintainability, re-use, and interoperability. The idea here is that we are bringing SOA directly to the code.
In summary, if you must remember only two things from this article, please remember:
- In the same way that Java EE created a new programming model for server-side Java enterprise development, there is a need for a new EDA programming model
- The EDA programming model must not only abstract and provide first-class support for the EDA concepts, but it must also promote re-use, openness, and dependency de-coupling
We have tried to achieve these in WebLogic Event Server. Please let us know how we have done.