Using YANCEES - Project Documentation



Introduction |

Writing Simple Clients | Starting YANCEES Server

Sample Configurations 

Understanding The Design Dimensions | Examples |

Yancees Project Main Page

Updated on August 18th, 2006 

Introduction to the YANCEES framework

YANCEES is a versatile publish/subscribe infrastructure. The current implementation provides an extensible and configurable event-based framework. Extension points are layd over the main design dimensions of a publish/subscribe system. These dimensions are the subscription, notification, publicatoin, event and protocol models. Additionally, YANCEES provides support for static plub-ins (a.k.a. services). The architecture is flexible enough to allow the distribution of components through client and server sides, providing flexibility to the resource model.

Subscription and notificatoin models are defined in terms of extensible languages, that syntactically describe the primitives, commands and messages of each model; Associated to each sets of elements in these languages are plug-ins. The dynamic binding of plug-ins with syntactical constructs in the language provides the desired functionality in each dimension. Internally, this dynamic plug-in allocation is performed by dynamic parsers associated to the subscription, notification and protocol models.

In short, YANCEES provides:

The Publish/subscribe architectural style

Publish/subscribe infrastructures (or publish/subscribe for short) are message-oriented middleware (or MOMs) that implement the publish/subscribe architectural style. This architectural style provides an inherent loose coupling communication mechanism between information producers (publishers) and information consumers (subscribers), which defines clear separation of communication from computation and carries the potential for easy integration of autonomous, heterogeneous components into complex systems that are easy to evolve and scale. They also provide a one-to-many communication mechanism with which multicast and broadcast-based applications can be implemented.  The following picture illustrates this communication paradigm. One one end, publishers produce information in the form of events; on the other end, subscribers express interest on those messages (based on a special message field -- topic-based subscription, or on the whole content -- content-based subscriptions). The pub/sub core routes messages according to the subscriptions provided by different subscribers, notifying them whenever a message matching their subscription (or query) is published in the system.
Publish/subscribe

Writing simple clients (publishers and subscribers) in YANCEES

In our simple example, YANCEES is configured as a centralized server running in a predefined host in the distributed system (possibly the localhost), and with a content-based routing and subscription language similar to Siena.  

A simple publisher

In order to be able to publish events, the user first needs to connect to the YANCEES server. YANCEES uses Java RMI to export its server interface, and requires the client to know the machine name where the server is running. RMI URLs are usually in the form \\hostname.mydomain.com\instancename. YANCEES instance name default value is 'yancees' and 'hostname.mydomain.com' must be replaced with the host name or IP address of the machine where YANCEES server instance is running.

After the connection is stablished, the users can start publishing events with the publish() command. Due to the use of RMI, this command throws a java.rmi.RemoteException. It also generates edu.uci.isr.yancees.YanceesException in case the subscription or event formats are incorrect.

The class edu.uci.isr.yancees.client.rmi.YanceesRMIClient encapsulates all the RMI connection concerns from YANCEES providing a simple interface with which users can publish and subscribe to events remotely. A publisher is presented below.
import edu.uci.isr.yancees.YanceesEvent;
import edu.uci.isr.yancees.YanceesException;
import edu.uci.isr.yancees.client.rmi.YanceesRMIClient;
...

public class YanceesPublisher {

YanceesRMIClient
client;


...

// this is the same code as the client
public void connectToYanceesClient() {

/*
* connects to YANCEES server at
* host: hostname.mydomain.com
*/
client = new YanceesRMIClient("hostname.mydomain.com");

}

...

public void publishAnEvent() {

YanceesEvent event = new YanceesEvent();
event.put("name", "Roberto");
event.put("Office", 247);
event.put("inHisOffice", true);
event.put("idleTime", 300000);

try {
client.publish(event);
} catch (YanceesException ex) {
// handle the exception
}
}

public static void main(String[] argv) {
YanceesPublisher myClient = new YanceesPublisher();
myClient.connectToYanceesRMIClient();
myClient.publishAnEvent();
}

}

Internally, the YanceesEvent object generates an XML representation of the event. In the example above, the event is represented as:

<event>

<attribute>
<name> myName </name>
<value type="yanceesString">
Roberto </value>
</attribute>
<attribute>
<name> Office </name>
<value type="yanceesString">
247 </value>
</attribute>

<attribute>
<name> inHisoffice </name>
<value type="yanceesBoolean">
true </value>
</attribute>
<attribute>
<name> idleTime </name>
<value type="yanceesLong">
300000</value>
</attribute>


</event>



A simple subscriber 

In order to cope with extensibility, subscription in YANCEES are defined according to an extensible subscription language defined in XMLSchema. This allows different subscription commands and languages to be defined. In this example, we use a content-based subscription language similar to the one provided by Siena. In Siena, filters represent simple content-based subscriptions, For the event produced by the client above, one could write a subscription that identifies when the user 'Roberto' is in his office and 'typing on the keyboard', i.e. the idle time is of some seconds, less than 10 seconds for example. The subscription looks as follows:
<subscription>
<filter>
<EQ>
<name> name
</name>
<value type="yanceesString">
Roberto </value>
</EQ>
<GT>
<name> idleTime </name>
<value type="yanceesLong">
10000 </value>

</GT>
</filter>
</subscription>

The gramar, XMLSchema, defining the content-based Siena-equivalent subscription language is defined in the file:  sienaSubscription.xsd available at: http://awareness.ics.uci.edu/~rsilvafi/yancees/xsd/

In order to receive notifications of events, the subscriber client needs to implement the edu.uci.isr.yancees.SubscriberInterface. This interface  has two methods: notify(EventInterface myEvent) and notify(EventInterface[] myEventList) which receive a single event or a pattern matching of events.  The subscriber then registers itself as a listener for notifications in the method subscribe(). After that, it starts receiving notifications whenever the subscriptioin is match, in response to an event publication.

After understanding the basic Siena subscription language, and the basic publish/subscribe mechanism, one can start writing a subscription client as follows:

import edu.uci.isr.yancees.YanceesEvent;
import edu.uci.isr.yancees.YanceesException;
import edu.uci.isr.yancees.client.rmi.YanceesRMIClient;
import edu.uci.isr.yancees.SubscriberInterface;
...

public class YanceesSubscriptionClient implements SubscriberInterface {

YanceesRMIClient
client;


...

// this is the same code as the client
public void connectToYanceesClient() {

/*
* connects to YANCEES server at
* host: hostname.mydomain.com
* RMI name: yancees
*/
client = new YanceesRMIClient("hostname.mydomain.com");

// optionally one could use YANCEES default name and do:
//
client = new YanceesRMIClient("hostname.mydomain.com");
}

...

public void subscribeToEvents() {

// A GenericMessage class can be used to represent an event, or in this case,
// a subscription.
GenericMessage msg = new GenericMessage("" +
" <subscription>" +
" <filter>" +
" <EQ>" +
" <name> name </name>" +
" <value type=\"yanceesString\"> Roberto </value>" +
" </EQ>"+
" </filter>" +
" </subscription>");
client.subscribe(msg, this);

try {
client.publish(event);
} catch (YanceesException ex) {
// handle the exception
}
}

public void notify(EventInterface[] myEvents) {
// handle the event list (pattern match) sent by the server when events are match
 }

public void notify(EventInterface myEvent) {
YanceesEvent yanceesEventHelper = (YanceesEvent) myEvent;
// handle the received event, in this case represented as an YanceesEvent object
// (It could be a GenericEvent object if a pure XML event is published instead.  
}

public static void main(String[] argv) {
YanceesSubscriptionClient myClient = new YanceesSubscriptionClient();
myClient.connectToYanceesRMIClient();
myClient.subscribeToEvents();

// keeps the subscriber alive, listening to events that match the subscription
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
}
}

}

Note that YanceesSubscriptionClient implements the SubscriberInterface. It also has a loop to keep it active indefinitely, reveiving notifications.

Starting the YANCEES Server

In order to properly use YANCEES, the server configured with the required features must be started in one or more hosts in the network. A configuration file specifying the location of the implementation of different components must be provided. This file describes, for example, the router component, the subscription language plug-ins, optional input and output filters, as well as protocol and notification plug-ins. The next session describes in more detail the configuration and development of such components.

In order to start YANCEES with a basic content-based configuration, suitable for routing the aforementioned examples, one can use the startLocalSienaYancees.bat file which does the following (note that it is a single line command, they are presented in different lines here for readability):

java -cp %CLASSPATH%;.\classes;.\bin;.\lib\siena-1.5.0.jar;.\lib\Yancees-SNAPSHOT.jar -Djava.rmi.server.codebase=file:/./lib/Yancees-SNAPSHOT.jar -Djava.security.policy=java.policy.all  edu.uci.isr.yancees.server.rmi.RemoteYanceesImplementation ./configurations/simpleLocalSienaConfiguration.xml

The configuration file ./configurations/simpleLocalSienaConfiguration.xml basically specifies the plug-ins, filters, langauge extensions and pub/sub cores to use in the YANCEES implementation. This particular configuration uses Siena as a content-based routing component, and requires Siena to be in the %CLASSPATH%.

The class RemoteYanceesImplementation reads the configuraton file and assembles the YANCEES router with all the ad-on components. We assume that the user had downloaded the Yancees-SNAPSHOT.jar file and placed it in the .\lib folder as well as the last version of Siena.

We suggest that users download the full distribution of YANCEES that comes with the .bat scripts, configuration files and some examples.

Downloading Sample Configurations

For your convenience, we provide some examples of YANCEES bundled in different configurations. Those buldes include  a Yancees-SNAPSHOT.jar file with the publisher and  subscriber source codes. windows and unix shell scripts are provided as well as the configuration file used to customize YANCEES.

Minimal YANCEES: Configured with a fast switch core, the subscription language has only one command, <require>, which filters messages with the specified attribute name.

Siena YANCEES: Configured with Siena as the routing core, it provides siena configuration language with an extra sequence detector plug-in. This is the version used in our example above.

Extending and Configuring YANCEES

This section is for those interested in extending YANCEES for their own needs

Understanding YANCEES Design Dimensions

In this section, we briefly explain the main extensibility dimensions, their models and how to extend them. At the end of this section, full examples are provided. All design dimensions are represented by a language, defined in XMLSchema, and plug-ins, implemented to provide the functionality.

Event Model

What is it

The event model deals with the way events are represented. The basic event model supported by current YANCEES implementation is tuple-based. In this model, an event is a set of attribute/value pairs. This model is very flexible and allows the implementation of more restrictive models such as record-based (fixed set of attributes/types) and subject-based (having a special attribute to distinguish events from different types) models. The enforcement of these rules can be achieved by the use of input and output filters as will de discussed later.

Note: Event models are usually bound to the event router used in the framework. Currently, we support Elvin, Siena, and a proprietary fast switch router. Other event representations can be defined provided that a router, that understands that representation, is installed in the framework. Different routers can be simultaneously used.

How to represent events

Events are represented as sets of attributes which have name, type and value. Events in YANCEES can be represented as YanceesEvent objects or in XML format as the example below.

 
 <event>
   <attribute>
      <name> attribute name </name>
<value type="yanceesString">
the value </value>
</attribute>
<attribute>
<name> another name </name>
<value type="yanceesInt">
12 </value>
</attribute>
<attribute> ... </attribute>
...
</event>

This format was chosen to provide the ability to represent large attribute values, such as binary files, text files, and long strings in between <value> tags (as opposed to use attribute and value as attributes of the tag, instead of elements as it is represented now). The types supported in current YANCEES implementation are the same as provided by the XML schema: boolean, double, float, long, int, string, hexBinary which, for the sake of limiting the possible attribute types, facilitating the parsing of the events, and coping with extensibility, are represented as: yanceesBoolean, yanceesDouble, yanceesFloat, yanceesLong, yanceesInt, yanceesString and yanceesBinary types.

How to extend an existing event model or define a new one

In order to extend the event model, developers extend the GenericMessage interface and optionally change the event schema with the new features, using the inheritance and extensibilty feautres of the XMLSchema definition. Alternatively, one can define a new event representation (or schemas).

Once the extension is defined, it must be implemented by plug-ins or by the adapter installed in the YANCEES framework. For example, if events are represented as generic HTML pages, it is the responsibility of the notification server adapter to receive this events and transform them, back and forth, from this representation to the native representation of the installed event dispatcher. In our current YANCEES prototype implementation, this is performed by the SienaAdapter or ElvinAdapter, with the help of the SienaEvent and ElvinEvent classes. These last classes convert the internal event representation to the native representation of Siena and Elvin, respectively, and vice-versa. The adapters are responsible for reading publish and subscribe commands and converting them to the native Siena and Elvin formats respectively.

Subscription Language

What is it

The subscription language allows an interested party (or subscriber) to specify its interest in a sub-set of events. The subscription language allows the specification of constraints in both the content and the order the events to be queried (including their type or subject in other event models). This is usually performed through the use logical expressions (or queries), based on special commands. For example, a <sequence> command can be defined to detect sequences of events; a <filter> command inquires about the content of the events and so on. These commands can be combined in subscription expressions that are interpreted by the Yancees SubscriptionParser

How to represent subscriptions

In the point of view of the YANCEES framework, simple subscriptions are represented as combinations of operators over events and their attributes. These operators are combined in logical expressions that, when matched, result in the delivery of the events to the end user. Operators are combined in a reverse polish notation as shown in the example below (in other words, it uses a LISP-like function composition syntax where operators comes before operands).

Complex subscriptions can be defined to generate new events, combine and abstract them. The classical example are rules. Rules are composed of a simple subscription part and an action part. The action can produce new events, and usually operate on the results of the subscription (condition). 

 
 <subscription type="subscriptionExtensionType">
   <op1 type="op1Type">
      <op2 type="op2Type"> ... </op2>
      <op3 type="op2Type"> ... </op3>
   </op1>
 </subscription>

 <notification>
   <policy1/>
   <policy2/>
 </notification>

Example of a rule specification...

 
 <subscription type="subscriptionExtensionType">
   <rule type="ruleType">
      <condition type="conditionType"> 
        <filter>... </filter>
</condition>
<action type="actionType"> ... </action>
</rule>
</subscription>

<notification>
<policy1/>
<policy2/>
</notification>

 

How to extend the subscription model

The subscription model is extended by two combined steps: (1) the extension of the subscription language, which is defined in XMLSchema, by the definition of  new tags (operators); (2) the implementation of plug-ins to handle those new tags, according to their syntax rules, defined in the XMLSchema extension. The plug-ins and their tags are then installed in the system using the configuration file, which associates their binaries with the appropriate XML tags in the plug-in manager.

Notification Language

What is it

The notification language specifies policies and procedures that deal with the delivery of events after their matching by a subscription expression. It allows, for example, the specification that events must be delivered as soon as they are produced, using <push> policy, or over subscriber request, using <pull>. Examples of extensions, or additional options, of such policies may include validity (the time an event should be kept in the server waiting for a deliver request); or a time interval (period) that all events matched in a subscription and stored for delivery, up to a certain point of time, must be delivered.

The notification policies are usually included at the end of a subscription message to the server, in the <notification> section, as presented in the following example.

How to represent notification options (or policies)

 
 <subscription type="subscriptionExtensionType">
	...
 </subscription>

 <notification>
   <policy1/>
   <policy2/>
 </notification>

How to extend the notification model

The notification model is extended in the same way as the subscription model. Extensions in the notification language need to be implemented by the plug-ins that will handle that commands expressed in the subscription message. Whenever the subscription is matched, the result is sent to the specified notification plug-in. Extensions such as pull may store the events in a temporary repository. These events are then collected by the subscriber with the help of protocol plug-ins.

 Protocol Model

What is it

The protocol model allows the specification of more complex interaction modes with the service (apart from the common publish/subscription of events). The idea is to allow the addition of new services to the common publish/subscribe model. Examples of protocols may include the identification and browsing of event source hierarchies (with primitives similar to CASSIUS); support for mobile clients (with move-in/move-out primitives); authentication protocols and so on.

How to represent protocol messages

Protocols are implemented by plug-ins that externalize the protocol API using Remote interfaces in Java RMI. These plug-ins are dynamically loaded, being created and accessed through factory methods in YANCEES API. This way, a protocol can implement an arbitrary complex interface, representing protocol messages, which adds flexibiltiy to the model. Protocol plug-ins can interact with other YANCEES plug-ins. In order to locate installed plug-ins YANCEES internal plug-in registry stores a reference to all active plug-ins (static or dynamic) at any given time. 

How to extend the protocol model

The current implementation of YANCEES uses RMI. A plug-in must implement a remote interface and responds to the remote method invocations. A session is created between the client and the plug-in, through the plug-in manager, based on the service requested through YANCEES API.

The Resource Model

What is it

The resource model allows the definition of the components of the system, and their location. In the current implementation, the resource model is provided by a configuration language. This language allows the configuration of plug-ins, services and filters that are installed in the server, as well as the dispatcher components to be used. 

How to represent a configuration

The configuration file allows the specification of the files that implement the plug-ins, services, filters and adapters of the whole system. It is subdivided in 5 sections, the dispatcher section, which configures the adapter(s) and the notification server(s) used in a configuration, the subscription section which defined subscription plug-ins; the notification and protocol sections with the same syntax as the subscription, defining their plug-ins. Finally services and input and output filters can also be defined. A configuration file looks like the one presented below.

<architecture>
<dispatcher>
<server>
<name>siena.server</name>
<uri>tcp:localhost:1234</uri>
</arch:server>
<adapter>
<javaClassName>
edu.uci.isr.yancees.server.dispatcher.siena.SienaAdapter
</javaClassName>
</adapter>
</dispatcher>

<subscription>
<plugin>
<name>
filter.plugin
</name>
<description>
This is a content-based filtering plug-in
</description>
<mainClass>
<javaClassName>
edu.uci.isr.yancees.server.plugin.subscription.filter.FilterPlugin
</javaClassName>
</mainClass>
<factoryClass>
<javaClassName>
edu.uci.isr.yancees.server.plugin.subscription.filter.FilterPluginFactory
</javaClassName>
</factoryClass>
</plugin>

<plugin>
<name>
sequence.plugin
</name>
<description>
This is a sequence detection plug-in
</description>
<mainClass>
<arch:javaClassName>
edu.uci.isr.yancees.server.plugin.subscription.sequence.SequencePlugin
</arch:javaClassName>
</arch:mainClass>
<arch:factoryClass>
<arch:javaClassName>
edu.uci.isr.yancees.server.plugin.subscription.sequence.SequencePluginFactory
</arch:javaClassName>
</arch:factoryClass>
<arch:depends>
filter.plugin
</arch:depends>
...
</arch:subscription>


<notification>
...
<notification>

<arch:protocol>
...
</arch:protocol>

<inputFilters>
<filter>
<name>
performance.input
</name>
<description>
This is a performance collector filter
</description>
<mainClass>
<javaClassName>
edu.uci.isr.yancees.server.filter.performance.InputPerformanceFilter
</javaClassName>
</mainClass>
</filter>
</inputFilters>

<outputFilters>
...
</outputFilters>

<services>
<service>
<name>
performance.output
</name>
<description>
This is a performance collector filter
</description>
<mainClass>
<javaClassName>
edu.uci.isr.yancees.server.service.cassius.CassiusService
</javaClassName>
</arch:mainClass>
</arch:service>
</arch:services>


</arch:architecture>

 

Extensibility Summary

DESIGN DIMENSION HOW TO EXTEND EXAMPLE EXTENSIONS
Subscription Model Extensible subscription language together with subscription plug-ins. Services and filters can also be used by the plug-ins Event aggregation
Abstraction
Rules (Event-condition/action
Sequence detection and rules
Event Model Extensible event representation language or GenericMessage interface.
Decoupling provided by the event adapter.
Plug-in to handle adapter-specific features and language.
Tuple-bassed (attribute/value pairs)
Record-based
Object-based
Typed and un-typed events
Publication ModelExtensible FilterInterface.
Filters are insterded in a chain of responsibility fasion that intercepts the publicatoin of events in YANCEES
PublishToPeers plug-in that diverges events to peers in a P2P Yancees model. Type Checking, Event Persistency
Notification Model Extensible notification language together with notification plug-ins that implement event delivery policies Push
Pull (with persistency)
Resource Model Server configuration language which is interpreted by the configuration manager.
It allows the distribution of components through the client side or server side.
Centralized
Partially-centralized
Client-side components
Protocol Model Extensible protocol language together with
Protocol plug-ins. 
Security protocols
Mobility Protocols
Configuration protocols

 

Services and Filters

Once the languages are extended to include new primitives, commands and representations, plug-ins must be defined to actually implement and handle this new functionality. Dynamic (notification, subscription and protocol) parsers perform this dynamic instantiation and composition of plug-ins for each new subscription request. Plug-ins, however, are allocated on demand, usually one set for each subscription posted in the server.

The plug-in life cycle ends when the subscription is not necessary anymore. This model is stateless and usually requires some external persistency that spans different plug-in activations. Another need is access to external resources such as database systems, data models, applications and so on. In order to cope with these extra requirements, services are provided. Services are objects that remain active in the system during the whole execution of the server and can be accessed by plug-ins whenever required. They enhance plug-ins with persistency and other services.

Filters provide extension points in both the input and output buffers of the server, allowing the implementation of pre and post processing tasks, data collection and policy enforcements, for example. They usually apply to all input and output events. For example, plug-ins can collect performance information for further analysis, they can enforce event types, security policies and so on.

Programming Model

This section describes in more detail how to implement the system's plug-ins, services and filters, presenting their interfaces.

Plug-in Interface

interface PluginInterface
      extends PluginListenerInterface {
  long getId();
  String getTag();
  String getFullContext();
  String getFullPath();
  Node getSubtree();
  void addListener (PluginListenerInterface plugin);
  void removeListener (PluginListenerInterface plugin);
  void addRequiredPlugin (PluginInterface plugin);
  PluginInterface[] getRequiredPluginsList();
  boolean hasChildren();
  void dispose();
}

 

Service Interface

public interface ServiceInterface {
public String getName();
public void setName(String name);
public boolean isActive();

}

 

Filter Interface

public interface FilterInterface {
public String getName();
public void setName(String name);
public void handleMessage(EventInterface evt);
public void handleMessage(EventInterface[] evtList);
public void addSuccessor(FilterInterface filter);
public void removeSuccessor();
public FilterInterface getSuccessor();
}

 

Configuration Manager

The configuration manager installs and configures the main components of the system. Configurations are expressed using the YANCEES configuration language, which is provided to the YANCEES runtime during its bootstrap. An example of configuration file was previously presented in the extensibility dimensions section.

Examples

Case study: implementing CASSIUS services with YANCEES

To illustrate the use of the architecture extensibility and configurability, this section presents some examples on how to define and adapt the components of the system to implement different services. It also shows how YANCEES can be customized to provide the functionality required by different application domains.

For example, suppose that YANCEES needs to be adapted to support awareness applications. Notification servers such as Khronika and CASSIUS provide us with a list of the basic services needed. Hence, in order to be functionality-compatible with this domain, YANCEES needs to provide: event persistency and typing, event sequence detection, and the pull notification delivery mechanism. Moreover, a special feature provided by CASSIUS is the ability to browse and later subscribe to the event types that are published by each event source. This service, called event source browsing, provides information about the publishers and the events they publish.

 Implementing a sequence detection mechanism

Sequence detection requires the extension of the subscription model with the addition of a new keyword <sequence>. It will operate over a set of content-based filters, which are natively provided by the event dispatcher component.

The first step is to extend the YANCESS subscription language with the new <sequence> tag. This is illustrated in the code fragment of Table 1 as follows.

<complexType name="SequenceSubscriptionType">
  <complexContent>
    <extension base="sub:SubscriptionType">
      <sequence minOccurs="0" maxOccurs="1">
        <element name="sequence" type= "FilterSequenceType" />
      </sequence>
    </extension>
  </complexContent>
</complexType>
 
<complexType name="FilterSequenceType">
  <sequence minOccurs="1" maxOccurs="unbounded">
    <element name="filter" type="FilterType"/>
  </sequence>
</complexType>

 The next step is to implement the sequence detection plug-in, extending the AbstractPlugin, a convenience class that provides default implementations to the plug-in interface presented in Table 2 as follows.

interface PluginInterface
      extends PluginListenerInterface {
  long getId();
  String getTag();
  String getFullContext();
  String getFullPath();
  Node getSubtree();
  void addListener (PluginListenerInterface plugin);
  void removeListener (PluginListenerInterface plugin);
  void addRequiredPlugin (PluginInterface plugin);
  PluginInterface[] getRequiredPluginsList();
  boolean hasChildren();
  void dispose();
}

 Note that the PluginInterface is a listener to events produced in other plug-ins. It implements the interface in Table 3 as follows.

interface PluginListenerInterface {
  void receivePluginNotification (EventInterface evt, PluginInterface source);
  void receivePluginNotification (EventInterface[] evtList, PluginInterface source);
}

 A simple sequence detection implementation will collect, in the right order, events coming from each one of the filters it observes. When a successful sequence is detected, the sequence plug-in returns the set of events collected, publishing it to higher-level plug-ins (listeners). Note that we are assuming that the event dispatcher guarantees the in-order delivery of events. If this is not the case, more complex algorithms must be used.

A plug-in factory, implementing the interface in Table 4 must also be defined.  

interface PluginFactoryInterface {
  String[] getTags();
  PluginInterface createNewInstance (Node subTree);
}

 A simple factory implementation will return a new instance of the plug-in only each time the createNewInstance() method is invoked in its interface. The plug-in factory must then be registered under the “sequence” tag name in the YANCEES configuration file described in Table 5, followed by the restart or reconfiguration of the YANCEES service. 

<subscription>
...
  <plugin>
    <name> sequence.plugin </name>
    <mainClass>
      <javaClassName>
        plugin.sequence.SequencePlugin
      </javaClassName>
    </mainClass>
    <factoryClass>
      <javaClassName>
        plugin.sequence.SequencePluginFactory
      </javaClassName>
    </factoryClass>
    <depends> siena.plugin </depends>
  </plugin>
...
</subscription>

 The plug-in is then ready to be used. It will be activated each time a subscription is provided that uses the <sequence> tag as its part. An example of a subscription using this new extension is presented in Table 6. The Java DOM parser automatically checks the subscription for syntax errors by using the XML schema defined in Table 1.

<subscription>
  <sequence xsi:type="FilterSequenceType">
    <filter xsi:type="FilterType">
      <EQ>
        <name> status</name>
        <value> Fail </value>
      </EQ>
    </filter>
    <filter xsi:type="FilterType">
      <LT>
         <name> cooler Temp </name>
         <value> 90 </value>
      </LT>
    </filter>
  </sequence>
</subscription>
<notification>
  <push>
</notification>

 Implementing a pull delivery mechanism

 Pull delivery allows subscribers to periodically poll (or check) the server for new events matching their subscriptions. This mechanism copes with the requirements of some mobile applications, where subscribers usually get temporarily disconnected.

This mechanism is provided by a pull notification plug-in. In order to temporarily store the events that are not being delivered, the pull mechanism needs an event persistency service. As a consequence, together with the pull notification plug-in, an event persistency service must also be defined.

Users need to control when to collect and when to store the events being routed to them as a result of a subscription. This usually requires a polling interaction protocol. This interaction is not part of the regular publish() and subscribe() commands of a notification server, so a protocol plug-in must be defined. In short, the implementation of a pull delivery mechanism requires:

The implementation of the pull notification plug-in follows the same steps as the sequence detection plug-in previously described. The same is true for the notification language extension. An extension is provided to the notification language that defines the <pull> tag. Additionally, a factory to instantiate this plug-in is also provided. In order to activate the pull plug-in, a <pull> tag must be provided in the <notification> session of a subscription message (see Table 6). As a consequence, a pull plug-in instance is created and registered to handle the events that match the subscription.

The pull plug-in implementation is very simple; it directs the events to the persistency service component and registers them under their target subscriber interface.

The poll plug-in responds to commands such as <poll-interval>, <stop-polling> and <poll>, which define different polling mechanisms. It collects the events stored in the persistency service, and delivers them periodically to the subscriber (poll-interval command); it then collects the notifications whenever requested (using the poll command) or deactivates the periodic delivery (using the stop-polling command) in case of a temporary disconnection.

These sets of plug-ins define a configuration, a set of components that need to be present in order for a service to operate. The dependencies between these are checked by YANCEES with the help of the <depends> clause in the configuration file.

 Implementing CASSIUS features

 In addition to the features described in the previous sessions, CASSIUS provides event typing and the ability to browse through hierarchies of event sources.

The browsing of event sources in CASSIUS allows publishers to register events in a hierarchy based on accounts and objects. This model and the API required to operate the server are described elsewhere.

In the YANCEES framework, the CASSIUS functionality is implemented by the use of protocol plug-ins and a CassiusService component. The CASSIUS protocol plug-in interacts with the CassiusService, which allows the creation and management of objects, accounts, and their events. These operations include registering/un-registering accounts, objects, and events, as well as polling commands.

CASSIUS uses events with a fixed set of attributes. These events can be easily identified and checked for correctness by an input filter. This filter checks all incoming events for the proper CASSIUS template format. Once a CASSIUS event is identified and validated, it is copied to the CassiusService, which stores it in a database in its proper account/object record.

Polling of events, in this case, is handled by the CASSIUS protocol plug-in, which allows the collection of events by account, object, or sub-hierarchies. Note that this approach does not prevent the simultaneous installation of both services, the simple pull and the CASSIUS pull protocol.

The poll mechanism is not the only way to collect CASSIUS events. At any time, subscriptions can also be performed on regular CASSIUS events.

Currenlty Implemented Features

This section describes the functionality of the components currently available to the YANCEES framework. It is subdivided according to the extensibilty dimensions: event model, subscription model, notification mode and protocol.

Event Model

In the current YANCESS version, the events are represented as sets of attribute/value pairs.

Subscription Mode

Supports conent-based and topic-based subscrtiptins. The content-based language is a XML porting of the Siena Subscription language. The topic-based language, is implemented by the <require> tag with behaves similarly to the Elvin require() command.

Notification Model

Supports <push> and <pull>

Protocol Model

supports polling, to access the event stored on the server side, if the <pull> notification policy is used.


P.S. I will expand these last topics later on...


Research Staff: Roberto Silveira Silva Filho
Professor: David F. Redmiles
Institute for Software Research
Information and Computer Science
University of California, Irvine CA 92697-3425



This page was last updated on June 16th , 2006