Dev Analysis for listener for lifecycle server events

Version 5

    User Story

    Provide a means to add a listener registration for the new lifecycle server events.

    Something that integrates with the primary management layer.

    Issue Metadata

    EAP issue: https://issues.jboss.org/browse/EAP7-472 - Ability to register a listener (integrated with the management layer) that will be notified of the lifecycle server events

    Related issues: https://issues.jboss.org/browse/EAP7-471 - Management and JMX notifications when ControlledProcessState changes

    Dev Contacts: jmesnil, ehugonnet

    QE Contacts: Martin Simka

    Hard Requirements

    • Notify user code when the server state changes (either the runtime configuration state or if available the running state).
      Block during the listener calls to let user code react to server state changes
    • User code is defined in JBoss module and is configured in the server management model

    Soft requirements

    • Emit core notifications for the server state changes. This allows to leverage JMX but comes with design limitations (limited by the jmx subsystem lifecycle, will miss some state transitions when the jmx subsystem is stopped, notifications are asynchronous and will be emitted after the server state change)

    Non Requirements

    • JMX is not supported. Users that were relying on a JMX notification listener in previous EAP/WildFly version will have to update their code to rely on the new listener mechanism or use the mecanism in
    • Not compatible with core notification listeners. Core notifications allows to register listeners from subsystems but they are by design notified asynchronously.

    Design Details

    Server lifecycle events

    The server rutime configuration lifecycle events are governed by the different state transition based on its ControlledProcessStateService:

    • starting
    • running / ok
    • reload-required
    • restart-required
    • stopping
    • stopped

     

    The server running state events are governed by the different state transition based on its SuspendController :

    • running
    • pre-suspend
    • suspending
    • suspended

    As the SuspendController is only available in server mode (aka standalone or domain server) those transitions don't happen on a Domain or Host Controller.


    These states already exists and the aim of this feature is to allow user code to be notified when they change.
    WildFly will provide an interface that can be implemented by users to be notified of lifecycle server events.

     

    /**

    * Listener that is notified of process state change.

    */

    public interface ProcessStateListener {

      /**

      * Called when the listener is instantiated and add to the server runtime.

      */

      default void init(ProcessStateListenerInitParameters parameters) { }

      /**

      * Called when the listener is removed from the server runtime.

      */

      default void cleanup() { }

    /**

      * Called when the runtime configuration state changes.

      * Call to this method is blocking and affects the performance of the server.

      */

      default void runtimeConfigurationStateChanged(RuntimeConfigurationStateChangeEvent evt) {}

    /**

      * Called when the running state changes.
      * This will <strong>NEVER</strong> be called on a HostController.
      *
      * @param evt the running state change event.
      */
      default void runningStateChanged(RunningStateChangeEvent evt) {}

    }

     

    The listeners will be bound to the ControlledProcessStateService lifecycle and will be able to be called for the following transitions:

    • starting -> running
    • running -> reload-required
    • running -> restart-required
    • reload-required -> restart-required
    • restart-required -> reload-required
    • running -> stopping
    • reload-required -> stopping
    • restart-required -> stopping

     

    The listeners will be bound to the SuspendController lifecycle and will be able to be called for the following transitions:

    • starting -> suspended
    • suspended-> normal / admin-only
    • normal / admin-only -> suspending
    • suspending -> suspended
    • suspended -> stopping


    When WildFly boots, at runtime stage, it will load instances of this interface (specified in a JBoss module) and initialize them with a Properties object (that users can configured in the management model).Every time the server state changes, the instances of this interface will be notified.
    If the process state listener can not be instantiated, it will raise an exception (and prevent the server to start)If the process state listener raise an exception when its stateChange() method is called, it will log a warning with the underlying exception.
    When WildFly is stopped, the listeners will receive the last event change ( xxx -> stopping), the remove() method will be called and they will be removed from the server runtime.
    During reload, the listeners will stop listening when the server is stopping and will be loaded again when the server is starting. Implementations of the interface will have to ensure that they can be loaded, initialized and removed correctly several times inside the same JVM.
    To let implementers react to the server state changes, the notifications to the listeners will be blocking. Implementations of the interface will have to ensure that they do not block or deadlock as it will affect the server lifecycle.Each listener instances will be executed in its own thread and the order is not guaranteed.

    Management API

    The process-state-listener is the resource representing a listener composed of the attributes:

    • class - a STRING attribute representing the fully qualified name of the listener implementation (can not be null, does not allow expressions)
    • module - a STRING attribute representing the identifier of the JBoss module that contains the implementation (can not be null, does not allow expressions)

    • properties - a simple map of attribute representing properties that will be passed to the implementation when it is initialized (values are STRING attributes that allows expressions).
    • timeout - a timeoutr in seconds before cancelling the execution of the lisitener.

    They are marked as ordered child to avoid side-effects.

     

     

    Example to add a process state listener:

     

    /.../subsystem=core-management/process-state-listener=my-listener:add(class=”org.foo.MyListener”, module=”org.foo”, properties = {“foo” = true, “bar” = “${bar.prop:2”}})

    Work Decomposition

    Work is impacting the wildfly-core project only and is self-contained.

     

    An open issue is which management resource should define the process-state-listeners attributes.

    Existing candidates are the core management resource (/core-service=management) or one of its service child resource.

    The feature does not depend on any other management resource (only on the ControlledProcessStateService at runtime) and could be located anywhere.


    A possible candidate would be a new subsystem that complements the core management resource as subsystem resources are well semantically defined (compared to kernel resources such as core management resource)

    QE

    Test that a process state listeners configured in the management model will be notified of all possible state transition (these tests must be included in wildfly-core test suite).