Requirements summary
We do not support remote management notifications yet, so all registered notification handlers need to be in-vm. The current/obvious way to register a notification handler is to implement a subsystem to register these notifications, however that is quite complicated to do for end users. The aim is to make it simpler for users to register their own implementations of notification listeners by having people implement a NotificationRegistrar interface, and register that class in a central place in the management model.
This is quite a straightforward requirement. Users specify the NotificationRegistrar implementation, and it gets called when the resource defining the NotificationRegistrar implementation is added.
Since this feature is already implemented, the detail is in the following design notes.
Design notes
In the standalone case the notification registrars are registered under:
/core-service=management/service=notification-registrat/registrar=*
In the host controller case the notification registrars are registered under:
/host=<host-name>/core-service=management/service=notification-registrar/registrar=*
These resources are used to register implementations of the NotificationRegistrar interface, which is explained later. In the HC case, the NotificationRegistrar implementation is instantiated and started on both the HC itself, and on the servers it controls.
In both cases the resource takes the following parameters:
- code - the class name of the NotificationRegistrar implementation. It is a required string.
- module - the module containing the NotificationRegistrar implementation. It is a required string.
- properties - a map of key/value pairs which can be used to configure the NotificationRegistrar.
Interfaces
There are three new, central interfaces involved. The user implements the NotificatioRegistrar interface, and they then make use of the NotificationRegistrarContext and NotificationRegistry references that they get passed to register notification handlers.
NotificationRegistrar
The NotificationRegistrar interface to be implemented by users looks like:
/**
* {@code /core-service=management/service=notifications} resources.
*
* @author Kabir Khan
*/
public interface NotificationRegistrar {
/**
* Registers notification handlers. The notification handlers will be automatically removed when this registrar
* is removed.
*
* @param context the context
*/
void registerNotificationListeners(NotificationRegistrarContext context);
/**
* Callback to do any cleanup required when removing this registrar.
*/
default void cleanup() {
}
}
When the resource is added, a service is installed in the add handler's RUNTIME stage. When that service starts, NotificationRegistrar.registerNotificationListeners() gets called. Note that the add handler's RUNTIME stage gets called regardless of if we are running in admin-only mode, or normal mode.
NotificationRegistrar.registerNotificationListeners() then instantiates and registers notification handlers using the NotificationRegistrarContext. Any notification handlers that get registers during this call are automatically removed when the handler is removed. The cleanup() method can be used to perform additional cleanup of the registered handlers (such as closing a connection), and it is called after the handlers are unregistered.
NotificationRegistrarContext
The NotificationRegistrarContext contains operations to register the notification handlers, and to get information about the process we are running in:
org.jboss.as.controller.notification;
import org.jboss.as.controller.ProcessType;
import org.jboss.as.controller.RunningMode;
import org.jboss.as.controller.client.ModelControllerClient;
/**
* Encapsulation of data to register notifications via the {@link NotificationRegistrar}
*
* @author Kabir Khan
*/
public interface NotificationRegistrarContext {
/**
* Get the name of this registrar
*
* @return the name
*/
String getName();
/**
* Get the notification registry into which notification handlers will be installed
*
* @return the notification registry
*/
NotificationRegistry getNotificationRegistry();
/**
* Get the process type of the process
*
* @return the process type
*/
ProcessType getProcessType();
/**
* Get the running mode of the process
*
* @return the running mode
*/
RunningMode getRunningMode();
/**
* Get the properties for configuring the notification handler(s)
*
* @return the properties
*/
Map<String, String> getProperties();
* Get the model controller client for the process
*
* @return the client
*/
ModelControllerClient getModelControllerClient();
}
The getName() method is the name of the registrar=* resource installing this NotificationRegistrar.
getNotificationRegistry() gives us access to the NotificationRegistry which will be mentioned below.
When running on a host controller the NotificationRegistrar gets installed on both the host controller and its managed servers. The getProcessType() method allows us to determine which process we are running in. We can then make choices such as whether to install the notification handlers or not, or whether to configure the handlers differently (perhaps writing to different file locations).
getRunningMode() tells us whether we are running in admin-only or normal mode.
getProperties() gives us access to the key/value pairs defined in the properties attribute of the resource defining the NotificationRegistrar implementation. This allows us to configure the notification handlers installed by the NotificationRegistrar implementation.
getModelControllerClient() gives us access to the model controller client. This should never be called during the NotificationRegistrar.registerNotificationListeners() call but can be stored for later use by the installed notification handlers.
NotificationRegistry
The NotificationRegistry is used to register the notifications:
package org.jboss.as.controller.notification;
/**
* Interface exposed to the users to register notifications via the {@link NotificationRegistrar}
*
* @author Kabir Khan
*/
public interface NotificationRegistry {
/**
* Register the given NotificationHandler to receive notifications emitted by the resource at the given source address.
* The {@link org.jboss.as.controller.notification.NotificationHandler#handleNotification(org.jboss.as.controller.notification.Notification)} method will only be called on the registered handler if the filter's {@link org.jboss.as.controller.notification.NotificationFilter#isNotificationEnabled(org.jboss.as.controller.notification.Notification)}
* returns {@code true} for the given notification.
*
* @param source the path address of the resource that emit notifications.
* @param handler the notification handler
* @param filter the notification filter. Use {@link org.jboss.as.controller.notification.NotificationFilter#ALL} to let the handler always handle notifications
*/
void registerNotificationHandler(PathAddress source, NotificationHandler handler, NotificationFilter filter);
}
The NotificationRegistry is used to perform the registration of the notification handlers. During the NotificationRegistrar.registerNotificationListeners() call, the NotificationRegistrar implementation instantiates the notification handlers and calls this method to register them. The parameters of this method are:
- source - the address to register the notification handlers against. Multiple calls can be made to register handlers for different addresses.
- handler - the NotificationFilter (exists in EAP 7.0 already) implementation to filter the notifications we are interested in.
- filter - a NotificationFilter (exists in EAP 7.0 already) implementation to filter the notifications we are interested in.
Issue Metadata
Downstream: https://issues.jboss.org/browse/EAP7-472
Upstream: https://issues.jboss.org/browse/WFCORE-1405
Upstream PR: https://github.com/wildfly/wildfly-core/pull/1553
Development contact: Kabir Khan
QA contact: ???
Related to: https://issues.jboss.org/browse/EAP7-471/https://issues.jboss.org/browse/WFCORE-1157
Polarion Test Plan: TBD
Comments