Title: Apache Felix Event Admin The Event Admin Service Specification, part of the OSGi Compendium specification, defines a general inter-bundle communication mechanism. The communication conforms to the popular publish/subscribe paradigm and can be performed in a synchronous or asysnchronous manner. The main components in a publish/subscribe communication are: * *Event Publisher* - sends events or messages related to a specific *topic* * *Event Handler* (or *Subscriber*) - expresses interest in one or more topics and receives all the messages belonging to such topics. Events are composed of two attributes: * a *topic* defining the nature of the event; topic names are usually arranged in a hierarchical namespace, where slashes are used to separate the levels (i.e. "org/osgi/framework/FrameworkEvent/STARTED") and * a set of *properties* describing the event. ## Creating an Event Publisher An event publisher is a simple Java class that creates events and sends them using the `EventAdmin` service interface, for example: public void reportGenerated(Report report, BundleContext context) { ServiceReference ref = context.getServiceReference(EventAdmin.class.getName()); if (ref != null) { EventAdmin eventAdmin = (EventAdmin) context.getService(ref); Dictionary properties = new Hashtable(); properties.put("title", report.getTitle()); properties.put("path" , report.getAbsolutePath()); properties.put("time", System.currentTimeMillis()); Event reportGeneratedEvent = new Event("com/acme/reportgenerator/GENERATED", properties); eventAdmin.sendEvent(reportGeneratedEvent); } } The `EventAdmin.sendEvent()` method sends the `Event` object synchronously. To send it asynchronously, use the `EventAdmin.postEvent()` method, such as: //.. Event reportGeneratedEvent = new Event("com/acme/reportgenerator/GENERATED", properties); eventAdmin.postEvent(reportGeneratedEvent); ## Creating an Event Handler Creating an event handler is as simple as implementing the `EventHandler` interface: public class ReportEventHandler implements EventHandler { public void handleEvent(Event event) { String reportTitle = (String) event.getProperty("title"); String reportPath = (String) event.getProperty("path"); sendReportByEmail(reportTitle, reportPath); } //.. ## Registering an Event Handler To receive event notifications, the event handler must be registered as a OSGi service under the object class `org.osgi.service.event.EventHandler`. When registering the service, a `String\[\]({{ refs..path }})` property named `*EVENT_TOPIC*` must be specified; this property describes the list of topics in which the event handler is interested. For example: String[] topics = new String[] { "com/acme/reportgenerator/GENERATED" }; Dictionary props = new Hashtable(); props.put(EventConstants.EVENT_TOPIC, topics); bundleContext.registerService(EventHandler.class.getName(), new ReportEventHandler() , props); It is possible to use '*' as a wildcard in the final character of the EVENT_TOPIC, like in this example: String[] topics = new String[] { "com/acme/reportgenerator/*" }; Dictionary props = new Hashtable(); props.put(EventConstants.EVENT_TOPIC, topics); bundleContext.registerService(EventHandler.class.getName(), new ReportEventHandler() , props); Finally, it is possible to specify an additional `EVENT_FILTER` property to filter event notifications; the filter expression follows, the normal LDAP syntax: String[] topics = new String[] { "com/acme/reportgenerator/GENERATED" }; Dictionary props = new Hashtable(); props.put(EventConstants.EVENT_TOPIC, topics); props.put(EventConstants.EVENT_FILTER, "(title=samplereport)"); bundleContext.registerService(EventHandler.class.getName(), new ReportEventHandler() , props); ## OSGi Events Every OSGi framework sends (asynchronously) a number of events that can be captured by any bundle. ### Framework Events * org/osgi/framework/BundleEvent/STARTED * org/osgi/framework/BundleEvent/ERROR * org/osgi/framework/BundleEvent/PACKAGES_REFRESHED * org/osgi/framework/BundleEvent/STARTLEVEL_CHANGED * org/osgi/framework/BundleEvent/WARNING * org/osgi/framework/BundleEvent/INFO ### Bundle Events * org/osgi/framework/BundleEvent/INSTALLED * org/osgi/framework/BundleEvent/STARTED * org/osgi/framework/BundleEvent/STOPPED * org/osgi/framework/BundleEvent/UPDATED * org/osgi/framework/BundleEvent/UNINSTALLED * org/osgi/framework/BundleEvent/RESOLVED * org/osgi/framework/BundleEvent/UNRESOLVED The followig properties are always present in a bundle event object: * *bundle.id* * *bundle.symbolicName* ### Service Events * org/osgi/framework/ServiceEvent/REGISTERED * org/osgi/framework/ServiceEvent/MODIFIED * org/osgi/framework/ServiceEvent/UNREGISTERING The following properties are always present in a service event object: * *service* * *service.id* * *service.pid* Each of the aforementioned events actually contains a wider set of properties. Check the OSGi Compendium specification, section 113.6, for a complete list. ## Configuration The Apache Felix Event Admin implementation is trying the deliver the events as fast as possible. Events sent from different threads are sent in parallel. Events from the same thread are sent in the order they are received (this is according to the spec). A timeout can be configured which is used for event handlers. If an event handler takes longer than the configured timeout to process an event, it is denied. Once a handler is in a denylist, it doesn't get sent any events anymore. The Felix Event Admin can be configured either through framework properties or through the configuration admin using PID `org.apache.felix.eventadmin.impl.EventAdmin`. This is a list of configuration properties: ---- **Thread Pool Size** *Property*: org.apache.felix.eventadmin.ThreadPoolSize *Default*: 20 *Type*: Integer The size of the thread pool used for event delivery. The default value is 20. Increase in case of a large amount of events. A value of less then 2 triggers the default value. If the pool is exhausted, event delivery is blocked until a thread becomes available from the pool. Each event is delivered in a thread from the pool unless the ignore timeouts is configured for the receiving event handler. ---- **Async/sync Thread Pool Ratio** *Property*: org.apache.felix.eventadmin.AsyncToSyncThreadRatio *Since*: Release 1.4.2 *Default*: 0.5 *Type*: Double The ratio of asynchronous to synchronous threads in the internal thread pool. Ratio must be positive and may be adjusted to represent the distribution of post to send operations. Applications with higher number of post operations should have a higher ratio. ---- **Timeout** *Property*: org.apache.felix.eventadmin.Timeout *Default*: 5000 *Type*: Integer The deny-listing timeout in milliseconds. The default value is 5000. Increase or decrease at own discretion. A value of less then 100 turns timeouts off. Any other value is the time in milliseconds granted to each event handler before it gets denied. ---- **Require Topic** *Property*: org.apache.felix.eventadmin.RequireTopic *Default*: true *Type*: Boolean Are event handlers required to be registered with a topic? This is enabled by default. The specification says that event handlers must register with a list of topics they are interested in. Disabling this setting will enable that handlers without a topic are receiving all events (i.e., they are treated the same as with a topic=*). ---- **Ignore Timeouts** *Property*: org.apache.felix.eventadmin.IgnoreTimeout *Default*: empty *Type*: String Configure event handlers to be called without a timeout. If a timeout is configured by default all event handlers are called using the timeout. For performance optimization it is possible to configure event handlers where the timeout handling is not used - this reduces the thread usage from the thread pools as the timout handling requires an additional thread to call the event handler. However, the application should work without this configuration property. It is a pure optimization! The value is a list of strings. If a string ends with a dot, all handlers in exactly this package are ignored. If the string ends with a star, all handlers in this package and all subpackages are ignored. If the string neither ends with a dot nor with a start, this is assumed to define an exact class name. ---- **Ignore Topics** *Property*: org.apache.felix.eventadmin.IgnoreTopic *Since*: Release 1.4.0 *Default*: empty *Type*: String For performance optimization it is possible to configure topics which are ignored by the event admin implementation. In this case, a event is not delivered to registered event handlers. The value is a list of strings (separated by comma). " +If a single value ends with a dot, all topics in exactly this package are ignored. If a single value ends with a star, all topics in this package and all sub packages are ignored. If a single value neither ends with a dot nor with a start, this is assumed to define an exact topic. A single star can be used to disable delivery completely. ---- **Log Level** *Property*: org.apache.felix.eventadmin.LogLevel *Note*: This property can't be set through the OSGi configuration. *Default*: 2 (=WARNING) *Type*: Integer This sets the log level used for messages outputted by the event admin implementation. Valid values are 1 (=ERROR), 2 (=WARNING), 3 (=INFO), and 4 (=DEBUG). The default is 2 and an invalid value sets the level to the default value. ----