Enhancing Event Driven Architectures With Event-Bus Types

6 downloads 8027 Views 458KB Size Report
connection or dependency between the software component ... approach for event management. ... elaborates on the event-bus concept, Section IV describes.
Enhancing Event Driven Architectures With Event-Bus Types Martin S. Kew, Timothy Ferris Defence and Systems Institute University of South Australia Mawson Lakes, SA 5095, Australia Email: [email protected], [email protected]

Abstract—With the aim of reducing dependencies, software systems have used event-based techniques for a number of years. We provide an overview of a model-driven technique that uses simple models to specify an event-driven system. A demonstration model-driven code generator using a meta modelling framework is presented that supports model to Java code implementation. A strength of this approach is that different groups of events, modelled as event-bus types, may be implemented using different event-based techniques within a single software system. We compare this approach with other approaches and outline possible future developments of the concept. Keywords-model driven architecture; events; publish subscribe; meta modelling

I. I NTRODUCTION The purpose of event-based software is to avoid any direct connection or dependency between the software component that triggers an operation and the component that performs it. This technique has become popular in recent years because it can be used to partition development concerns, and reduce the impact of requirement and implementation change on the software. This technique goes by a number of names, chief of which are the Observer Pattern and Publish-Subscribe. However, guidance on the implementation of event-based software [2], [3], [4], typically uses a centralised middleware approach for event management. This paper investigates: 1) If a distributed approach could be used to define and implement event-based software. 2) If repetitious event code could be automatically generated from a simple event-based software model. A typical event-based software solution uses a Message Oriented Middleware (MOM). For example, the Open Message Queue (OpenMQ) implements the publish-subscribe capabilities of the Java Messaging Service (JMS) API approach 1 . Such solutions provide robust and reliable management of events, but typically provide a one size fits all mechanism for event organisation & access, and no automation support. Figure 1 presents a model of a simple power-plant, using our proposed event-based software model notation. From the 1 https://mq.dev.java.net/

Georg Grossmann, Markus Stumptner Advanced Computing Research Centre University of South Australia Mawson Lakes, SA 5095, Australia Email: [email protected], [email protected]

control console display

remote web display view connector

view connector mv bus model connector power plant model

boiler pressure sensor

actuator connector

sensor connector

model connector

sensor connector boiler temperature sensor

fuel_valve

model connector

ms bus

ma_bus model connector

sensor connector

actuator connector cooling water valve

actuator connector

model connector turbine speed sensor

feed water pump valve

sensor connector

model io monitor

condenser pressure sensor

Figure 1.

Simple Power-Plant Software Model

figure we see that the example power-plant software has two different display components (remote web display, control console display), a single power-plant model component (power plant model), four sensor components (boiler pressure sensor, boiler temperature sensor, turbine speed sensor, condenser pressure sensor), three actuator components (fuel valve, cooling water valve, feed water pump valve), and a model input-output monitor component (model io monitor). The example also has three distinct event-buses, a modelview bus (mv bus), a model-sensor bus (ms bus), and a model-actuator bus (ma bus). For this example, measurements from the sensors are used to update a dynamic mathematical model of the powerplant that functions as a feedback control system, used to automatically change actuator settings. The power-plant Operator, via either display component, can receive sensor and power-plant state information derived from the mathematical model. The Operator then uses this information to define the power-plant’s mode of operation and other settings, again via either display component. To meet the performance requirements of the example power-plant. It is assumed that the model-sensor and modelactuator buses need to be more reliable and responsive than the model-view bus. If a centralised MOM approach is used to implement all event-buses in Figure 1, then the reliability and responsiveness of the MOM needs to be

high enough to meet the needs of the model-sensor and model-actuator buses. However, such an solution would over specify the performance of the model-view bus. This is a prime disadvantage of a centralised approach for event implementation. Alternatively, if we can use different implementation strategies for different event-buses, then for a given level of performance, the overall cost and complexity of a software system could be reduced. Our approach uses a graphical decomposition of a software system that fits comfortably with event-based development, and is directly amenable to model-driven generation of event-code. A prime advantage of this technique is that it distributes event-code, thereby allowing different implementation strategies to be employed for different event-buses. The paper has the following structure, Section II discusses related event-based software development work, Section III elaborates on the event-bus concept, Section IV describes the Model Driven Architecture (MDA) approach used to move from an event-based model to auto-generated eventcode implementation, and finally Section V presents some conclusions and possible future work.

Subject

observes

Observer

+attach(o:Observer) +detach(o:Observer) +notify()

ConcreteSubject

+update()

subject

ConcreteObserver

-data

-data

+getData() +setData()

+update()

Figure 2.

Observer Pattern UML Class Diagram

class contains the actual data of interest and sends a notification to it’s clients by executing their callback operations. For a specific client, the ‘ConcreteObserver’ class provides an implementation of the callback operation used to keep the client’s data synchronised with that of the supplier. A prime disadvantage of the Observer pattern is code bloat, where the pattern needs many (i.e. four) classes to manage a single data item of interest. This situation typically forces a software developer to manage a set of data items as a single unit, which subsequently places additional overhead on the client, to deduce which data items in the set have changed. C. The Eiffel ‘Event Type’ Library

II. R ELATED W ORK A. Access Coordination - Data ‘Push’ or Data ‘Pull’ To manage the sharing of data in a software system, two approaches have been devised to coordinate access, namely, data push and data pull. For the push approach, a data client registers (or subscribes) a callback operation with the data supplier. Upon update of data at the supplier, the supplier notifies each registered client by executing the client’s callback operation using some policy for the timing and order of callback operation execution. In its simplest form, upon update of the data, the operations are sequentially executed in the order in which they were registered. However this policy can also be ‘asynchronous’, ‘buffered’, ‘parallel’, and ‘prioritised’. For the pull approach, the client periodically checks for new data by directly querying the data supplier. B. The ‘Observer’ Pattern The ‘Observer’ software design pattern [3] is a common implementation of the data push approach. The purpose of the pattern is to ensure consistency between related objects without tightly coupling them, this is achieved by moving the coupling between a data client and it’s supplier from compile-time to run-time. Figure 2 presents a UML class diagram for the Observer pattern. From the figure we see that the ‘Subject’ class (or abstract supplier) provides a means for a client ‘Observer’ class to subscribe (attach) to the data supplier. The ‘Observer’ class identifies the callback operation (update) used by all clients to update their data. The ‘ConcreteSubject’

With the goal of improving reuse, the Eiffel Event Type [4] is a reusable library implementation of the Observer pattern, consisting of a single Generic Eiffel Class. However the simplicity of its implementation (as a specialisation of a list class) relies on some advances features of the Eiffel programming language, namely, multiple inheritance, generics, tuples and agents2 . As an example, to define an event x. The event can be created and referenced with an instance variable of the Event Type class, using a statement like: x : EVENT TYPE [ TUPLE [STRING ] ]

where the tuple is a generic class parameter used to define the parameter signature of a callback operation associated with the event. To subscribe to the event, a data client creates a callback operation and provides a reference to the operation using the Eiffel agent mechanism. As an example, lets assume that some client object c has created the operation: h a n d l e x ( d a t a : STRING}

to be used as the callback operation for the event. To subscribe to the event, the following statement is needed: x . subscribe ( agent c . handle x ( ? ) )

where the question mark is an open parameter conforming to the tuple, that receives a specific value when the callback operation is executed. 2 Not to be confused with a ‘software agent’ of an Agent Based Model (ABM). In Eiffel, the agent mechanism is used to create an object that represents a software ‘routine’ or ‘operation’.

Figure 4.

Figure 3.

Data Bus Pattern (Push Version) UML Class Diagram

To publish the event, a data supplier calls the publish operation for the event, providing specific event data in the process: x . publish ([ data ])

The Eiffel Event Type is a substantial improvement on the Observer pattern, providing a compact reusable implementation of the data push approach. But it is not without it’s issues, notably: 1) Limited guidance is provided on what entity owns the events (client, supplier, or some other entity) and how these events are organised. 2) For a large software system with many events, the overhead associated with subscribing and publishing events on an individual basis could become prohibitive. D. The ‘Data Bus’ Pattern Even though it has a similar name, the Data Bus Pattern [2] has a very different structure to the ‘Event-Bus Type’ proposed by this paper. The Data Bus Pattern is a derivation of the Observer Pattern with a centralised data repository (including metadata), to which suppliers post data and clients receive it. The pattern can be implemented in either a push or pull version, but only the push version will be discussed here. Figure 3 presents a UML class diagram for the Data Bus Pattern, obtained from [2]. From the figure we see that the Listener object subscribes to a data item in a similar manner to the Observer Pattern. Listener objects

OpenMQ Architecture and Components

are then notified when a subscribed data item is updated. Due to its use of a data repository, the Data Bus Pattern is extensible, where new data items can be added at run-time without modification of the pattern’s implementation. Prime disadvantages of this approach are: 1) A single data repository and a ‘one size fits all’ approach is used to support event-based communication between data clients and suppliers. 2) Like the Observer Pattern and Eiffel Event Type, the quantum of subscription used is a single data item only, implying that significant overhead could be placed on data clients when using the pattern. E. The ‘Middleware’ Approach As an example of the middleware approach, an overview of the Open Message Queue (OpenMQ) MOM is presented. This software implements the Java Message Service (JMS) API and is designed to support reliable, asynchronous, buffered, and loosely coupled communication between software components. Figure 4, obtained from the OpenMQ website (https:// mq.dev.java.net/), presents the main components of the middleware, from the figure we see that the message ‘Broker’ is the central component. This server component manages the bidirectional exchange of messages between OpenMQ clients and specific ‘Message’ or ‘Topic’ destinations stored on the server, where ‘Topic’ destinations are needed for the implementation of data push, publish-subscribe messaging systems3 . Interestingly, even though only a single event class is supported for a given ‘Topic’ destination. The JMS API 3 Noting that ‘Message’ destinations coupled with event ‘Channels’ or ‘Queues’ are needed to implement point-to-point data pull messaging systems.

control console display

remote web display view connector

publish x

x: String

handle x

view connector mv bus model connector

Figure 6.

An Event

power plant model

Figure 5.

Model-View Bus Interactions

allows for the construction of an event hierarchy using class inheritance, where the Java Reflection mechanism is used to support and manage the hierarchy. By design, middleware uses centralised message repositories for communication, and as such, is unsuitable for fast communication between tightly coupled components. In other words, middleware covers one part of the spectrum of ‘data push communication mechanisms’, but does not cover the region associated with tightly coupled communication. More suitably handled by techniques like the Eiffel Event Type previously discussed. III. O UR A PPROACH : ‘E VENT-B US T YPES ’ In the development of non-trivial software systems, a key characteristic of an interface between system components is that the interface is innately complex, consisting of tens if not hundreds of operations. Therefore to manage this complexity, additional structure is needed to help organize these operations. For a systems engineer such complexity is not new, where systems engineers actively manage complexity by using the concepts of a system and an interface [5]. However unlike its interpretation in the software engineering domain, an interface in the systems engineering domain is closer to the concept of a communication link, an electrical / hydraulic / pneumatic / mechanical cable assembly, or an electronic circuit board / backplane i.e. in this domain. An interface is a thing or object to be built, where this thing physically links components together, and as such, has the form of a communication & control structure. However, event-based software can be easily built in the form of a communication & control structure, thereby making it an ideal candidate to perform a function analogous to a systems engineering interface. Concentrating on the model-view bus and its interactions from Figure 1, repeated here as Figure 5, we see that the event-based software modelling notation used has three concepts, namely, components, buses, and connectors. More specifically, this notation is a bipartite graph4 G = (C, B, K) in which components C represent one graph vertex set (rectangles), event-based buses B represent the second graph vertex set (ovals), and connector graph edges 4 A bipartite graph has two disjoint sets of vertices, where every graph edge connects a vertex in one set to a vertex in the other.

K define the form of connection provided by buses, to components. Referring to Figure 5, we see that this small but complete event-based software model has: 1) Two display components (remote web display, control console display) connected to the model-view bus (mv bus) using a connector type (view connector). 2) A single power-plant model component (power plant model) connected to the model-view bus using a connector type (model connector). where the connector types (view connector, model connector) provide access to one or more of the events defined and managed by the model-view bus. Now moving attention to the internal structure of an eventbus, and the model-view bus in particular. In its simplest form, an event is a structure containing a list of callback operation references. The structure providing a subscribe operation to add a callback operation reference to the list, and a publish operation to trigger the event, which in turn causes the execution of all callback operations in the list. Figure 6 presents a graphical representation of an arbitrary event x, from the figure we see that the event has the following characteristics: 1) The event has a callback operation (handle x). 2) The event has a publish or event trigger operation (publish x). 3) The publish relation is represented by a solid arrow to the event. 4) The subscribe relation is represented by a dashed arrow to the event. 5) The event has a type (String), where the type defines the data passed as a parameter between the publish and callback operations. Using the conventions of Figure 6, we are now in a position to define an Event Bus Graph for the model-view bus i.e. Figure 7, where this figure is a complete graphical representation of all the events handled by the bus. As an example, the graph supports the following sequence of operations: 1) A view connected to the ‘view connector’ publishes a ‘start’ event used to change the mode of operation of the power-plant by powering it up. In this example we assume that the power-plant has four modes of operation (0 = stopped, 1 = startup, 2 = running, 3 = shutdown). 2) The model-view bus triggers the handling of the ‘start’ event by a model connected to the ‘model connector’; by executing the ‘handle start’ operation of the model.

publish start

start: String

publish stop

stop: String

handle power plant mode

power plant mode: Integer

handle start

ms bus handle stop

ma bus model connector

model connector

publish power plant mode

actuator filter

sensor filter

log data handle power plant efficiency

handle power output

handle boiler pressure

power plant efficency: Real

power output: Real

boiler pressure: Real

publish power plant efficiency

log view

log display

handle turbine speed

handle condenser pressure

handle fuel valve

handle cooling water valve

handle feed water pump valve

Figure 7.

turbine speed: Real

condenser pressure: Real

fuel valve: Integer

cooling water valve: Integer

feed water pump valve: Integer

power plant

publish boiler temperature

Figure 9.

Event System Graph Hierarchy - Level Interactions

publish turbine speed

publish condenser pressure

publish fuel valve

publish cooling water valve

publish feed water pump valve

Model-View Bus (Event Bus Graph) a Component

Event System Graph (like Figure 1)

Level (n)

Event Bus Graphs (like Figure 7)

Level (n+1)

the Component’s decomposition

Figure 8.

auto alerts

model io monitor

publish boiler pressure model connector

boiler temperature: Real

log view

publish power output

view connector handle boiler temperature

log data log bus

Event System Graph Hierarchy

3) The model changes the power-plant’s mode of operation to ‘startup’ and indicates as such, by publishing a ‘power plant mode’ event. 4) The model-view bus triggers an update of the view, by executing the ‘handle power plant mode’ operation of the view. a similar sequence of operations applies to the ‘stop’ event used to shutdown the power-plant. Concurrent to these operations, the model periodically publishes sensor and derived power-plant state information events like ‘boiler pressure’, where the ‘boiler pressure’ event has the following sequence of operations: 1) A model publishes a ‘boiler pressure’ event used to indicate a change in the boiler’s pressure value. 2) The model-view bus triggers the handling of the ‘boiler pressure’ event by a view; by executing the ‘handle boiler pressure’ operation of the view. Now moving our attention away from the model-view bus

and back to the power-plant as a whole. By using Figures 1, 7, and similar figures to Figure 7 for the other eventbuses, a complete graphical representation for the powerplant software could be constructed. Extrapolating to a more complex system, such a system: 1) Could be decomposed into a set of components and event-buses, represented by a single Event System Graph (like Figure 1). 2) Could have the internal event structure for each eventbus represented by an Event Bus Graph (like Figure 7), with one graph for each event-bus. where applying this process recursively for each system component, would results in a hierarchical set of graphs as depicted in Figure 8. This process is similar (but not identical) to functionaldecomposition. It is proposed that the process be used only for the highest levels of decomposition for a complex software system. Leaving object-oriented design as the preferred approach for lower software system levels. To support interaction between the hierarchical levels in Figure 8. An Event System Graph must allow for components at a lower hierarchical level (n+1) to access the eventbuses at the parent level (n) i.e. in an Event System Graph, a component may connect to the event-buses in it’s parent component’s Event System Graph, where the component is required to implement the event-bus connectors used at the parent level. As an example, Figure 9 presents a subset of the power-plant model associated with the ‘model io monitor’ component. In the figure, which presents two levels of the power-plant’s hierarchy concurrently, we see that the ‘sensor filter’ and ‘actuator filter’ sub-components of the ‘model io monitor’ component are connected to the model-view bus and model-actuator bus at the parent level. It should be noted, that if we ‘flatten’ the Event System Graph hierarchy by expanding all levels into a single graph. The resulting graph would still be a valid event-based bipartite graph. A significant advantage of the proposed event-based technique is that it is distributed, with related events bundled

into event-buses and distributed throughout the software system. Such an approach lends itself to the use of different implementation strategies for different event-buses. For expediency, the implementation described in Section IV uses a simple single application thread approach. However it is conceivable that a more complex multithreaded TCP/IP networked (and/or middleware) approach could also be used, allowing parts of the software to be widely and remotely distributed. By using different implementation strategies for different event-buses, it is possible that a more efficient and robust software system could result. Due to the use of a broad spectrum of event-based implementation techniques, rather than the use of a single technique. Stepping back for a moment from the proposed Event System Graph representation. A review of the computer science literature showed that the use of bipartite graphs is not new. Particularly in the field of knowledge representation, where entity-relationship diagrams [1] and conceptual-graphs [6] are both bipartite graphs. Taking an analogy between these different forms of knowledge representation and our eventbased software, we see that a software ‘component’ could be analogous to a knowledge representation ‘entity’ (or ‘concept’ for a conceptual graph), and an ‘event-bus’ could be analogous to a knowledge representation ‘relation’. However, a key point taken from the knowledge representation literature is that an ‘entity’ and a ‘relation’ are peer concepts, with neither taking precedence over the other. Folding this idea back to our event-based software model, implies that their could be some benefit in regarding an ‘event-bus’ as a peer rather than a subservient concept to a software ‘component’. IV. M ODEL -D RIVEN I MPLEMENTATION Model Driven Engineering (MDE) is a software development methodology that has been widely accepted in research and industry. Its core paradigm is the application and development of models that abstract from executable code on different levels. One main driver in the MDE area is the Model Driven Architecture (MDA) initiative from the Object Management Group [7]. The concept of the Event Type Bus in Section III fits well into this concept because it abstracts from underlying code and can be regarded as a platform independent model. One proposal of the MDA is an automated transformation of platform independent models to platform specific models and executable code. We have implemented this idea in a prototype using the Domain Modelling Environment (DoME) 5 . DoME is an open-source meta model framework developed by Honeywell which allows the specification of a modelling language using a visual notation and the generation of an editor for the language from the specification

automatically. It includes a built-in Document Generator which we have used to generate executable code from a model editor. DoME is written in Smalltalk and we adapted it to the current Cincom VisualWorks (VW) 7.6 development environment 6 which was included in the official VW 7.6 distribution. We first give an overview of the meta model specifications for the Event Bus Type concept in DoME and then describe the transformation process from an Event System Graph model to executable code. A. Meta Model Specifications The specification of the Event Bus Type in DoME consists of two meta models also called DoME Tool Specifications (DTS). The first meta model specifies the Event System Graph shown in Figures 1 and 5, and the second describes the Event Bus Graph which is the internal specification of a bus as shown in Figure 7. A screenshot of the Event System Graph DTS editor is depicted in Figure 10. The specification includes three node specifications called Bus, Connector and Component visualised by rectangles with rounded corners and a double-lined border. They specify the bus, a connector and a component respectively for the Event System Graph as explained in Section III. The Connector specification is linked to the Bus specification by an Accessory relationship depicted by a triangle with label “a” and the name “ports(0;*)”. This means that a connector can be attached to a bus in the form of a port which can support either zero or many connectors. Further we specified a connector specification called Connection which is visualised by a rectangle with a double-lined border. It specifies a connection between a component and the connector of a bus. The directed arrows set between the node specifications Connector and Component define the constraints in which a connection can be created, allowing a connection from a a connector to a component or the opposite way. Further explanation of the DTS editor and its visual syntax can be found in the DoME Guide 7 . The Event Bus Graph is specified by a separate meta model and is linked to Event System Graph meta model as a subdiagram of the Bus node specification. By this means a user can create an Event Bus Graph inside a bus by double-clicking on the bus which opens an Event Bus Graph in a new editor. Figure 11 shows the meta model specification of that graph. The important elements are the two node specifications Event and Connector which represent an event and a connector respectively and two connector specifications called Publish and Subscribe. The Connector specifications are depicted in grey with a single line border because they refer to an external specification in the Event System Graph meta model and cannot be 6 http://www.cincomsmalltalk.com

5 http://www.htc.honeywell.com/dome/

7 http://www.htc.honeywell.com/dome/DOMEGuide.pdf

Figure 12. Event System Graph Editor which includes part of the example shown in Figure 1.

Figure 10. DoME Tool Specification editor for the Event System Graph meta model.

Figure 13. Event Bus Graph Editor which includes part of the example shown in Figure 7.

model connector. The ms bus node contains a subdiagram shown in Figure 13 which is an instance of an Event Bus Graph and which specifies an event called Sensor data. The event is published through the sensor connector depicted by an incoming solid arc and subscribed through the model connector depicted by an incoming dashed arc. C. Code Generation

Figure 11. DoME Tool Specification editor for the Event Bus Graph meta model.

instantiated by the user. A connector is instantiated on the Event System Graph level and attached to a bus and automatically included in the Event Bus subdiagram of the bus. B. Example Figures 12 and 13 show part of the example modelled in the Event System and Event Bus Graph editors which were generated by DoME from the specifications introduced previously. Figure 12 shows the ms bus to which the boiler pressure, boiler temperature, turbine speed sensors, and condenser pressure sensors are connected via the sensor connector. The io monitor is connected to the bus via the

DoME includes a Document Generator that enables the transformation from models to text. An overview of the transformation process is shown in Figure 14. The first step is to create a Generator that queries a DoME model and creates an SGML tree from it. A Formatter then queries the SGML tree and transforms it into document(s) using a style sheet. The style sheet contains document type specific templates, for example, Java code snippets. The Generator, Formatter and style sheet are written in a script language called Alter which is based on Lisp. Further details about the Document Generator and Alter can be found in the DoME Extensions Manual8 and the Alter Programmer’s Reference9 . The structuring of the generation process into different steps allows for step re-use in the generation of different executable code. For example, the generation of Eiffel and Java code differs only in the style sheets. This 8 http://www.htc.honeywell.com/dome/Extensions.pdf 9 http://www.htc.honeywell.com/dome/AlterManual.pdf

mv_bus

MV_Bus #model_list: ArrayList #view_list: ArrayList +connect_view(c:View) +connect_model(c:Model)

MV_Bus_Connector #bus: MV_Bus +isConnected(): boolean +setReference(a_bus:MV_Bus)

Model

View

Figure 14. The DoME Document Generation Process taken from the DoME Extensions Manual.

allows the generation of different implementations from the same model and can be extended to generate code from only parts of a model. This would achieve the requirements of distributed systems development for supporting event implementation strategies. For example, the mv bus in our example could be implemented in a MOM based approach whereas the ma bus might be implemented using a Service Oriented Architecture (SOA) based approach. In the following section we describe how the Formatter and the style sheet are implemented for Java. D. Generation of Java Code from Event Graphs For a simple single application thread implementation, an Event Bus Graph can be easily transformed into self contained Java code for an event-bus. However the transformation of a component from an Event System Graph to Java code requires some thought. Two possibilities have been identified for managing the relationship between automatically generated code and manually generated application code, they are: 1) To store both code types in separate Java classes, with a requirement that the manually generated code class inherits from the automated code class. Unfortunately this solution places a restrictions on how the manually generated code class can be used. As Java only supports single inheritance implying that the manually generated class cannot inherit from any other class. 2) To mixed both code types in a single Java class, with different code sections ‘tagged’ to allow both forward and reverse engineering from the event-based model to Java code. For the Java implementation presented, it is assumed that a single class is used for both code types. By using Java’s ‘inner class’ mechanism, the implementation is straight forward. To define a software system, the system’s constructor creates an instance of each component and event-bus object. To create a connection to a bus, a bus client defines an ‘inner class’ that inherits the relevant bus connector, where the ‘inner class’ defines all manually entered event callback routines without the need of additional wrapper code. Figure 15 presents a simplified UML class diagram which includes

+publish_start(data:String) +publish_stop(data:String) +handle_power_plant_mode(data:int) +handle_power_plant_efficency(data:double) +handle_power_output(data:double) +handle_boiler_pressure(data:double) +handle_boiler_temperature(data:double) +handle_turbine_speed(data:double) +handle_condenser_pressure(data:double) +handle_fuel_valve(data:int) +handle_cooling_water_valve(data:int) +handle_feed_water_pump_valve(data:int)

+handle_start(data:String) +handle_stop(data:String) +publish_power_plant_mode(data:int) +publish_power_plant_efficiency(data:double) +publish_power_output(data:double) +publish_boiler_pressure(data:double) +publish_boiler_temperature(data:double) +publish_turbine_speed(data:double) +publish_condenser_pressure(data:double) +publish_fuel_valve(data:int) +publish_cooling_water_valve(data:int) +publish_feed_water_pump_valve(data:int)

power_plant_model

control_console_display



MV_Bus_View

MV_Bus_Model

+handle_power_plant_mode(data:int) +handle_power_plant_efficiency(data:double) +handle_power_output(data:double) +handle_boiler_pressure(data:double) +handle_boiler_temperature(data:double) +handle_turbine_speed(data:double) +handle_condenser_pressure(data:double) +handle_fuel_valve(data:int) +handle_cooling_water_valve(data:int) +handle_feed_water_pump_valve(data:int)

Control_Console_Display +mv_bus_view: MV_Bus_View

ActionListener

Figure 15.

+handle_start(data:String) +handle_stop(data:String)

Power_Plant_Model +mv_bus_model: MV_Bus_Model -power_plant_mode: int -power_plant_efficiency: double -power_output: double -boiler_pressure: double -boiler_temperature: double -turbine_speed: double -condenser_pressure: double -fuel_valve: int -cooling_water_valve: int -feed_water_pump_valve: int

JFrame

Model-View Bus Java UML Class Diagram

only the control console display object for the model-view bus using this implementation approach. Alternatively, if the Eiffel language was used to implement the event-based software. The preferred approach of storing automated and manual code types in separate classes could be employed, since Eiffel supports the use of multiple inheritance, as well as generic classes. In such an implementation the software system’s constructor (or Eiffel make routine) would create an instance of each component and eventbus object, with bus connectors implemented as deferred or virtual classes. Again because of the use of multiple inheritance, bus connectors could be implemented as part of the bus client, where bus clients could define event callback routines without the need for additional wrapper code. To allow a bus client to connect to an event-bus, the implementation provides an event-bus with a ‘connect routine’, where internally, this routine defines a reference to the event-bus for bus connectors. During development, some thought was given as to whether support should be provided for a connector disconnect routine. However, after some reflection it was decided that such a routine would be unnecessary. Since software systems can dynamically control their capabilities based on their mode of operation, and as such, they can suspend publishing events, and callback

operation actions, based on their operating mode. Also, the provision of a disconnect routine would complicate the implementation in support of a feature that could be met by other means. For all Java code listings presented below, the following conventions apply: 1) Entity names from the event-based model (like component, bus, connector and event names) are bracketed by # signs in the code listings. 2) The ’case’ of the entity names in the code listings signifies their use as either a variable (i.e. #abc#), or as a class (i.e. #Abc#). 1) Add a Bus to an Event System Graph: When a #bus# is added to an Event System Graph. An empty Event Bus Graph is created in the model and template code is created for the bus (in the file #bus#.java). Also, template code (in the file #bus# connector.java) is created for the abstract connector class inherited by all connectors associated with the bus. Finally, the bus’s parent component code is modified to create and initialise the bus. 2) Add a Connector to an Event Bus Graph: When a new connector type #con# is added to an Event Bus Graph, the code for the bus is modified to create: 1) A ‘list’ used to store connector references. 2) A ‘connect routine’ used to add a connector reference to the list. The relevant code segments are presented in Listing 1. Listing 1.

New connector modifications to (#bus#.java).

/ / Connector L i s t s . A r r a y L i s t # con # l i s t = new A r r a y L i s t (INITIAL LIST SIZE ) ;

/ / Event Routines . public void p u b l i s h # event #(# Data type # d at a ) { f o r ( # H con # c : b u s . # h con # l i s t ) c . handle # event #( data ) ; }

Also, the code for the handle connector is modified (as per Listing 3) to provide a default callback handler routine for the event. Listing 3.

New event modifications to (#h con#.java).

/ / Event Routines . p u b l i c v o i d h a n d l e # e v e n t # ( # D a t a t y p e # d a t a ) {}

4) Add a Component to an Event System Graph: When a new component #com# is added to an Event System Graph. An empty Event System Graph is created in the model for the new component, this graph can then be used to define sub-components and event-buses for the new component. Also, template code (in the file #com#.java) is created for the new component, and finally, the new component’s parent component code is modified to create and initialise the new component. 5) Add a Connection on an Event System Graph: When a new #connection# between a component #com# and a #bus# is made on an Event System Graph, using one of the valid connector types of the event-bus (#con# say). The component code is modified (as per Listing 4) to create a Java ‘inner class’ for the connection, where the ‘inner class’ inherits from the connector. Inside the ‘inner class’, manually generated callback handler code can be entered to override the default ‘do nothing’ behaviour supplied by the connector. Listing 4.

Add a connection modifications to (#com#.java).

/ / Connect R o u t i n e s . p u b l i c v o i d c o n n e c t # con # ( # Con# c ) { # con # l i s t . add ( c ) ; c . setReference ( this ); }

/ / Connection inner c l a s s e s . public # Connection # # connection #; p u b l i c c l a s s # C o n n e c t i o n # e x t e n d s #Con# { / / Manually e n t e r e d a p p l i c a t i o n e v e n t h a n d l e r code . }

Also, template code (in the file #con#.java) is created for the new connector, where the new connector’s class inherits from the bus’s abstract connector. 3) Add an Event to an Event Bus Graph: When a new #event# with an event data type #data type# is added to an Event Bus Graph. Code is not immediately generated for the event, because the code needs to reside in the relevant connector classes for the bus, and at this point the relevant connectors have not been identified. Lets assume that a ‘publish link (solid arrow)’ has been created from a connector #p con# to the event, and that a ‘handle link (dashed arrow)’ has been created from a connector #h con# to the event. Given these assumptions, the code for the publish connector is modified (as per Listing 2) to provide a publish routine for the event.

Also, the parent component code is modified (as per Listing 5) to pass the connection reference to the bus.

Listing 2.

New event modifications to (#p con#.java).

Listing 5.

Add a connection modifications to (#par com#.java).

/ / Create subconnections . # b u s # . c o n n e c t # con # ( # com # . # c o n n e c t i o n # ) ;

This completes the description of the process needed to transform Event Graphs from the model to Java source code for a simple single application thread implementation approach. V. C ONCLUSION The initial goal of this paper was to define event-based software that would overcome limitations in the Observer Pattern and the Eiffel Event Type Library. The end result is a graphical event-based modelling approach that is directly amenable to automatic code generation using

MDA techniques. Unique contributions of this approach are threefold: First, a further abstraction from the Data Bus Pattern using a Bus Type concept simplifies the design of event based systems and supports the development of a distributed environment. Second, by using a bipartite graph representation as the underlying concept for the event-based software model, the importance of separating peer concepts is emphasised. These concepts are the communication and control structure, namely, an ‘event-bus’, and the software ‘component’, and third, our approach has the potential to produce more robust and flexible software systems by using a model driven approach to selectively generate different event-code implementation strategies. The work described by this paper represents an initial demonstration of the event-bus concept. Significant future work is needed to progress this work into a robust event modelling technique for general use. Some initial activities proposed are the identification of a set of complementary event-based implementation techniques that can be automated using the proposed event-based graphical model notation and the analysis of a number of implementation casestudies in different software domains using the proposed approach, to evaluate the performance. R EFERENCES [1] P. Chen, The Entity-Relationship Model - Toward a Unified View of Data, ACM Transactions on Database Systems 1 (1): 9-36, 1976. [2] B. P. Douglass, Real-Time Design Patterns, Addison-Wesley, 2003. [3] E. Gamma, R. Helm, R. Johnson and J. Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995. [4] B. Meyer, The power of abstraction, reuse and simplicity: an object-oriented library for event-driven design, Festschrift in Honor of Ole-Johan Dahl, eds. Olaf Owe et al., Lecture Notes in Computer Science Vol 2635, Springer-Verlag, 2003. [5] USA DoD, Systems Engineering Fundamentals, Defense Acquisition University Press, 2001 [6] J. Sowa, Conceptual Structures: Information Processing in Mind and Machine, Addison-Wesley, 1984. [7] A. Kleppe, J. Warmer and W. Bast, MDA explained - The Model Driven Architecture: Practice and Promise, AddisonWesley, 2003.

Suggest Documents