This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative.
The license (Mozilla version 1.0) can be read at the MMBase site. See http://www.mmbase.org/license
Abstract
Technical reference for [the new framework that was added as part of the queryResult cache release strategy project]
Table of Contents
The introduction of a new event model is part of the query cache release strategy project. Because the current MMBase node events yield to little information for advanced query invalidation rules, we needed a more detailed node and relation change event. NodeEvent and RelationEvent objects were introduced to cover this.
The core of the system is the EventManager. A singleton instance of this class is instantiated at startup time. This event manager is being loaded with brokers for a number of (MMBase) events. These are: NodeEvent, RelationEvent, and Event (by means of the AllEventBroker, used by the clustering application). If you want MMBase to load other event brokers as well, add them to the cluster manager configuration file eventManager.xml in the config directory. The event manager manages the brokers (one for each event type), and accepts listeners for these event types, as well as events (of any supported type) to pass on to the brokers. The event manager tries to find an event broker for every listener that is registered with it, and passes it on to the broker (that actually manages the listeners for it's event type`). are So what happens when an event is fired? 1 some code calls EventManager.propagateEvent(Event event). All event classes need to extend from event, so it can be any event. 2 the event manager iterates over it's event brokers, and asks each one if it can broker for this event (which mean it can deliver it to the right listeners. 3 The event broker (a specialization of AbstractEventBroker) calls canBrokerForEvent(Event event), (one of AbstractEventBroker's abstract methods you have to override to create an actual broker) to discover if this event is for him. 4 if so, the broker iterates over it's listeners, and propagates the event.
It is easy to add your own type of event. These can be MMBase related events or events that are pertinent to some application/extension you created. The great bonus is that your events are delivered across your mmbase cluster.
For every type of event you have to have two classes and one interface: an EventBroker, an Event and an EventListener interface.
Your event class has to extend org.mmbase.core.event.Event. This serves as a base type and also keeps track of the location in the cluster that the event originated from. One of the big advantages of using MMBase to send your application events is that they are send to all mmbase nodes in your network (that are configured to receive each others multicast messages), so it is more easy to write scalable web applications. (See for more information the document about mmbase clustering). To take advantage of this you have to make shure that the event is serializable though.
The EventListener interface has to extend org.mmbase.core.event.EventListener. It has to define one method that will be called by your event broker. (so what ever method name you choose is up to you, just make sure it accepts an instance of your event object and your event broker calls it).
Every class that wants to be notified of your type of event has to implement this interface and implement it's methods.
First you need a broker for you event type. The function of an event broker is to manage all listeners for your event type. It also determines for the event manager if it can handle an event. Event brokers have to be registered with the event manager. This is all you have to do to make it accept listeners for your event type, and notify them.
To create your own event broker simply extend AbstractEventBroker and implement the abstract methods. For an example it is a good idea to take a look ad NodeEventBroker.
This section tells you what you need to know about node and relation changes, how to use them, and how they all bounce and bounce inside MMBase these days.
This section tells you what you need to know about node and relation changes, how to use them, and how they all bounce and bounce inside MMBase these days.
Some things have changed in respect to the previous implementation using the org.mmbase.module.core.MMBaseObserver interface. This interface provided different methods for local and remote node changes. It was felt that this is not very useful; the usual practice seems to be to create one method to handle both types of events. It is still possible to determine if an event was local or remote by comparing the machine name of the event to the local one.
On the other hand was the information about the event provided to these methods very poor. This was the main motivation to change the event model.
The new org.mmbase.core.event.NodeEventListener and org.mmbase.core.event.RelationEventListener interfaces create a distinction between node and relation events. The classes org.mmbase.core.event.NodeEvent and org.mmbase.core.event.RelationEvent (and through them the events) provide much more information than before.
When you register a NodeEventListener or a RelationEventListener with the EventManager all node or relation events are propagated to it. This is many times what you want. In stead you want to listen to the events for nodes of a specific type. To make it as easy as it was before to register listeners to node and/or relation events of a specific builder, Some wrapper classes were created for NodeEventListener and RelationEventListener instances, that will filter the events for you (take a look at org.mmbase.core.event.TypedNodeEventListenerWrapper and org.mmbase.core.event.TypedRelationEventListenerWrapper. But you don't even have to use those directly. Both the MMBase and MMObjectBuilder classes have convenience methods to register your listeners. Take a look at Mmbase.addNodeRelatedEventsListener(String builder, Object listener) and MMObjectBuilder.addEventListener(Object listener). The object is your class implementing either NodeEventListener or RelationEventListener or both (discovered through introspection). Wrappers are created accordingly and registered as listeners.
This section provides insight into what happens when node and relation events are fired.
This section describes what happens when a local node or releation changes.
Nodes are committed to the database by the StorageManager. When this has happened ChangeManager.commit() is called. Just as the StorageManager is there to handle all changes to the database when a node changes, the ChangeManager has this responsibility towards MMBase (i.e. Make sure every 'client' that needs to know about the change does do).
The ChangeManager creates a NodeEvent instance and propagates it to the EventManager. If the changed node is a specialization of Insrel, a RelationEvent is subsequently created and propagated to the EventManager (EventManager.propagateEVent(Event)).
The EventManager will find the brokers that can handle events of this type, and the event will be propagated to the broker's listeners. In case of a node or relation event, those include the builder matching the type of the event, the Obsterver instance for the event type. Mind you, for a node event the 'type' of the event is the builder of the node, while for a relation event it's type is both the relation source type as the relation destination type. The ClusterManager will receive the event regardless of it's type.
The builder (all builders implement the NodeEventListener and the RelationEventListener) receiving the event will update it's node caches.
The Observer receiving the event will iterate over all queries it holds reference to and evaluate the event against it to discover it the query must be flushed (for more information about QueryCache#Observer see the 'QueryCache Release Strategy' document).
The ClusterManager implements the AllEventListener, so it will be notified for any and all event types. It will first check if the event is local. If this is so, it will serialize the event, and send it across the network to other nodes in the MMBase cluster.
This section describes what happens when a node changes somewhere in the cluster.
An event has been fired somewhere in the cluster. It was serialized and send across the network, and has been picked up by the local ClusterManager. The event is desiralized and propagated to the EventManager.
The EventManager will handle the event as in 4.2.1, item 3. Note that the ClusterManager will receive the event it just propagated to the EventManager again. That is why the ClusterManager checks if events are local before serializing them and sending them into the network.
This is part of the MMBase documentation.
For questions and remarks about this documentation mail to: [email protected]