Version 8

    The BarrierController Service

     

    Expressing dependencies between services using the <depends> tag

    (see an example here) is a convenient way to make

    the lifecycle of one service depend on the lifecycle

    of another.

     

    So for example, serviceA <depends> on serviceB means that irrespectively

    of the deployment order, the calling sequence will be:

     

    1. serviceB.create()

    2. serviceA.create()

    3. serviceB.start()

    4. serviceA.start()

     

    The Problem

     

    However, there are cases where services do not conform to the JBoss

    lifecycle model, i.e. they don't expose create()/start()/stop()/destroy()

    methods). For example, this is true for the jboss.system:type=Server MBean

    that represents the JBoss server itself. No lifecycle operations are exposed

    so you cannot simply express, +if JBoss is fully started then start my own

    service+.

     

    Or, even if they do conform to the JBoss lifecycle model, the completion of

    a lifecycle method (e.g. the start() method) may not be what we want.

    For example the jboss.web:service=WebServer MBean that wraps the embedded

    tomcat server in JBoss does not start the tomcat connectors in the start()

    method, until only after the jboss server is fully started. So putting

    a dependency on this MBean, if we want to hit a webpage through tomcat,

    will do no good.

     

    Resolving such non-trivial dependencies is currently performed using JMX

    notifications. For example the jboss.system:type=Server MBean emits

    a notification of type org.jboss.system.server.started when it has

    completed startup, and a notification of type org.jboss.system.server.stopped

    when it shutsdown.

     

    Similarly, jboss.web:service=WebServer

    emits a notification of type jboss.tomcat.connectors.started as of

    JBoss v4.0.2/3.2.8 (see this JIRA

    report).

     

    So you can actually subscribe and react to those notifications in order to

    implement more complex dependencies. This technique has been generalized

    with the BarrierController service; read on.

     

    The Solution (as of JBoss v4.0.2/3.2.8)

     

    The BarrierController is a relatively simple MBean service that extends

    ListenerServiceMBeanSupport and thus can subscribe to receive any

    notification in the system. It uses the received notifications to control

    the lifecycle of a dynamically created MBean called the Barrier.

     

    The Barrier is instantiated, registered and brought to the CREATE state

    when the BarrierController is deployed. After that, the Barrier is started

    and stopped when matching notifications are received. Thus, other services

    need only depend on the Barrier MBean using the usual

    tag,

    without having to worry about complex lifecycle issues. They will be started

    and stopped in tandem with the Barrier. When the BarrierController is

    undeployed the Barrier is destroyed, too.

     

    The notifications of interest are configured in the BarrierController using

    the SubscriptionList attribute. In order to identify the starting

    and stopping notifications we associate with each subscription a

    handback string object. Handback objects, if specified, are passed back

    along with the delivered notifications at reception time (i.e. when

    handleNotification() is called) to qualify the received notifications,

    so that you can identify quickly from which subscription a notification is

    originating (because your listener can have many active subscriptions).

     

    So we tag the subscriptions that produce the starting/stopping notifications

    of interest using any handback strings, and we configure this same string

    to the StartBarrierHandback (and StopBarrierHandback correspondingly)

    attribute of the BarrierController. Thus we can have more than one notifications

    triggering the starting or stopping of the Barrier.

     

    The Example

     

    The attached example

    (which is displayed here, too) is pretty

    much self describing. It instantiates a BarrierController that creates

    a Barrier called jboss:name=TomcatConnector,type=Barrier.

     

    The Barrier is started when the tomcat connectors are started and stopped

    when the server shutsdown. In fact, this is a very common pattern for

    services that want to hit a servlet inside tomcat.

     

    The service that depends on the Barrier in the example, is a simple

    memory monitor that creates a background thread and monitors the memory

    usage, emitting notifications when thresholds get crossed, but it could

    be anything. We've used this because it prints out to the console

    starting and stopping messages, so we know when the service gets

    activated/deactivated.

     

    If you hot-deploy this on a running server the Barrier will be stopped

    because by the time the BarrierController is deployed the starting

    notification is already seen. (There are ways to overcome this.) However,

    if you re-start the server, the Barrier will be started just after the

    tomcat connectors get activated.

     

    You can also manually start/stop the Barrier by using the startBarrier() and

    stopBarrier() methods on the BarrierController. The attribute

    BarrierStateString indicates the status of the Barrier.

     

    See NotificationsEmittedByJBossMBeans for deployment notifications.

     

    Advanced stuff

     

    • The DynamicSubscriptions attribute can be used to indidicate whether

      to monitor the JMX server for new MBeans registering, and subscribe for

      notifications to them, if they much the subscription list pattern.

      By default it is set to true.

    • The BarrierEnabledOnStartup defines the initial state of the Barrier,

      started or stopped. It is stopped, by default (false).

    • Many BarrierControllers can be deployed to express different

      notification-based dependencies, as long as their names and the specified

      BarrierObjectNames are distinct.

    • Many MBean services can depend on the same Barrier.

    • More than one notifications may start or stop the barrier, as long

      as they specify the same handback string.

    • Getting multiple times in a row a starting or stopping notification has no

      effect on the Barrier.

    • You may extend org.jboss.system.BarrierController in order to override

      the following method, to help the Controller decide about the initial

      state of the Barrier. This is useful when the BarrierController is

      hot deployed and so the starting notification is gone by that time.

       /**
        * Override this method to apply complex logic whether
        * to start the Barrier service upon startup or not.
        * 
        * This method will be only called once and only if
        * setBarrierEnabledOnStartup(Boolean) has not been called.
        * 
        * The default implementation is to return false.
        */
       protected Boolean enableOnStartup()
       {
          return Boolean.FALSE;
       }
    

     

    JBoss AS-5.x

    Some users have mentioned that they had trouble, setting this up in JBoss AS-5.x version. See this thread for more details.

     

     

     

    Related:

     

    BarrierControllerExample

     

    Referenced by: