Notifications in standard MBeans
In plain JMX there are three methods to enable make standard MBean send notifications:
- directly implement NotificationEmitter or NotificationBroadcaster interfaces,
- make MBean class inherit from proper support class (implementing one of above mentioned interfaces),
- include an instance of support class as a member in our MBean implementation.
First method is obviously the most time-consuming and discouraged in normal circumstances. The second and third should support or real-life situations. But the problem with all these methods it that they destroy the clean and
declarative standard MBean design by introducing
imperative notification handling. In NetMX, we decided to extend a little the core of the engine to extend the declarative model to cover also notifications.
In NetMX (besides the methods inherited from JMX) there is one another way of publishing notifications. It uses a unique .NET feature called
events. Events are a special kind of properties that are of
delegate types. They are functional equivalent for Java notification interfaces and
AddXXXListener and
RemoveXxxListener methods. Event-declaring class looks like this:
public class EventEmitter
{
public event EventHandler SomethingHappened;
}
Inside this class, a method can emit an event by simply calling
SomethingHappened like a method. Other objects can subscribe and unsubscribe for events using code like this:
public class EventListener
{
public void Subscribe(EventEmitter ee)
{
ee.SomethingHappened += this.HandleEvent;
}
public void Unsubscribe(EventEmitter ee)
{
ee.SomethingHappened -= this.HandleEvent;
}
private void HandleEvent(object source, EventArgs e)
{
//Handle the event
}
}
NetMX uses this approach to enable event publishing in standard MBeans while maintaining their PONO (
Plain
Old .
Net
Object) character. One must only declare an event in MBean interface and decorate it with proper
attribute (equivalent to Java's
annotiation). The attribute is necessary to provide
event type name for this event. All the plumbing is done by standard MBean wrapper class. There is no need for maintaining sequence numbers manually. Notification-enabled MBean interfaces looks like this:
public interface NotificationEnabledMBean
{
public int Value { get; set};
[MBeanNotification("sample.value")] //define the type for notification
public event EventHandler<NotificationEventArgs> ValueChanged; //notifaction event declaration
}
Implementation of this MBean is also straightforward:
public class NotificationEnabled : NotificationEnabledMBean
{
private int _value;
public int Value
{
get { return _value; }
set
{
_value = value;
if (ValueChanged != null)
{
ValueChanged(this, new NotificationEventArgs("Value changed", _value));
}
}
}
public event EventHandler<NotificationEventArgs> ValueChanged;
}