Chapter 10. Additional Services

This chapter discusses useful MBean services that are not discussed elsewhere either because they are utility services not necessary for running JBoss, or they don't fit into a current section of the book.

10.1. Memory and Thread Monitoring

The jboss.system:type=ServerInfo MBean provides several attributes that can be used to monitor the thread and memory usage in a JBoss instance. These attributes can be monitored in many ways: through the JMX Console, from a third-party JMX management tool, from shell scripts using the twiddle command, etc... The most interesting attributes are shown below.

FreeMemory

This is the current free memory available in the JVM.

ActiveThreadCount

This is the number of active threads in the JVM.

ActiveThreadGroupCount

This is the number of active thread groups in the JVM.

These are useful metrics for monitoring and alerting, but developers and administrators need a little more insite than this. The Java 5 JVMs from Sun provide more detailed information about the current state of the JVM. Some of these details are exposed by JBoss through operations on the SystemInfo MBean.

listMemoryPools

This operations shows the size and current usage of all JVM memory pools. This operation is only available when using Java 5.

listThreadDump

This operations shows all threads currently running in the JVM. When using Java 5, JBoss will display a complete stack trace for each thread, showing you exactly what code each thread is executing.

listThreadCpuUtilization

This operations shows all threads currently running in the JVM along with the total CPU time each thread has used. The operation is only available in Java 5.

10.2. The Log4j Service

The Log4jService MBean configures the Apache log4j system. JBoss uses the log4j framework as its internal logging API.

  • ConfigurationURL: The URL for the log4j configuration file. This can refer to either a XML document parsed by the org.apache.log4j.xml.DOMConfigurator or a Java properties file parsed by the org.apache.log4j.PropertyConfigurator. The type of the file is determined by the URL content type, or if this is null, the file extension. The default setting of resource:log4j.xml refers to the conf/log4j.xml file of the active server configuration file set.

  • RefreshPeriod: The time in seconds between checks for changes in the log4 configuration specified by the ConfigurationURL attribute. The default value is 60 seconds.

  • CatchSystemErr: This boolean flag if true, indicates if the System.err stream should be redirected onto a log4j category called STDERR. The default is true.

  • CatchSystemOut: This boolean flag if true, indicates if the System.out stream should be redirected onto a log4j category called STDOUT. The default is true.

  • Log4jQuietMode: This boolean flag if true, sets the org.apache.log4j.helpers.LogLog.setQuiteMode. As of log4j1.2.8 this needs to be set to avoid a possible deadlock on exception at the appender level. See bug#696819.

10.3. System Properties Management

The management of system properties can be done using the system properties service. It supports setting of the VM global property values just as java.lang.System.setProperty method and the VM command line arguments do.

Its configurable attributes include:

  • Properties: a specification of multiple property name=value pairs using the java.util.Properites.load(java.io.InputStream) method format. Each property=value statement is given on a separate line within the body of the Properties attribute element.

  • URLList: a comma separated list of URL strings from which to load properties file formatted content. If a component in the list is a relative path rather than a URL it will be treated as a file path relative to the <jboss-dist>/server/<config> directory. For example, a component of conf/local.properties would be treated as a file URL that points to the <jboss-dist>/server/default/conf/local.properties file when running with the default configuration file set.

The following illustrates the usage of the system properties service with an external properties file.

<mbean code="org.jboss.varia.property.SystemPropertiesService"
        name="jboss.util:type=Service,name=SystemProperties">
            
    <!-- Load properties from each of the given comma separated URLs -->
    <attribute name="URLList">
        http://somehost/some-location.properties,
        ./conf/somelocal.properties
    </attribute>
</mbean>

The following illustrates the usage of the system properties service with an embedded properties list.

<mbean code="org.jboss.varia.property.SystemPropertiesService"
        name="jboss.util:type=Service,name=SystemProperties">
    <!-- Set properties using the properties file style. -->
    <attribute name="Properties">
       property1=This is the value of my property
       property2=This is the value of my other property
    </attribute>
            
</mbean>

10.4. Property Editor Management

In JBoss, JavaBean property editors are used for reading data types from service files and for editing values in the JMX console. The java.bean.PropertyEditorManager class controls the java.bean.PropertyEditor instances in the system. The property editor manager can be managed in JBoss using the org.jboss.varia.property.PropertyEditorManagerService MBean. The property editor manager service is configured in deploy/properties-service.xml and supports the following attributes:

  • BootstrapEditors: This is a listing of property_editor_class=editor_value_type_class pairs defining the property editor to type mappings that should be preloaded into the property editor manager. The value type of this attribute is a string so that it may be set from a string without requiring a custom property editor.

  • Editors: This serves the same function as the BootstrapEditors attribute, but its type is java.util.Properties. Setting it from a string value in a service file requires a custom property editor for properties objects already be loaded. JBoss provides a suitable property editor.

  • EditorSearchPath: This attribute allows one to set the editor packages search path on the PropertyEditorManager editor packages search path. Since there can be only one search path, setting this value overrides the default search path established by JBoss. If you set this, make sure to add the JBoss search path, org.jboss.util.propertyeditor and org.jboss.mx.util.propertyeditor, to the front of the new search path.

10.5. Services Binding Management

With all of the independently deployed services available in JBoss, running multiple instances on a given machine can be a tedious exercise in configuration file editing to resolve port conflicts. The binding service allows you centrally configure the ports for multiple JBoss instances. After the service is normally loaded by JBoss, the ServiceConfigurator queries the service binding manager to apply any overrides that may exist for the service. The service binding manager is configured in conf/jboss-service.xml. The set of configurable attributes it supports include:

  • ServerName: This is the name of the server configuration this JBoss instance is associated with. The binding manager will apply the overrides defined for the named configuration.

  • StoreFactoryClassName: This is the name of the class that implements the ServicesStoreFactory interface. You may provide your own implementation, or use the default XML based store org.jboss.services.binding.XMLServicesStoreFactory. The factory provides a ServicesStore instance responsible for providing the names configuration sets.

  • StoreURL: This is the URL of the configuration store contents, which is passed to the ServicesStore instance to load the server configuration sets from. For the XML store, this is a simple service binding file.

The following is a sample service binding manager configuration that uses the ports-01 configuration from the sample-bindings.xml file provided in the JBoss examples directory.

<mbean code="org.jboss.services.binding.ServiceBindingManager" 
      name="jboss.system:service=ServiceBindingManager">
    <attribute name="ServerName">ports-01</attribute>
    <attribute name="StoreURL">
        ../docs/examples/binding-manager/sample-bindings.xml
    </attribute>
    <attribute name="StoreFactoryClassName">
        org.jboss.services.binding.XMLServicesStoreFactory 
    </attribute>
</mbean>

The structure of the binding file is shown in Figure 10.1, “The binding service file structure”.

The binding service file structure

Figure 10.1. The binding service file structure

The elements are:

  • service-bindings: The root element of the configuration file. It contains one or more server elements.

  • server: This is the base of a JBoss server instance configuration. It has a required name attribute that defines the JBoss instance name to which it applies. This is the name that correlates with the ServiceBindingManager ServerName attribute value. The server element content consists of one or more service-config elements.

  • service-config: This element represents a configuration override for an MBean service. It has a required name attribute that is the JMX ObjectName string of the MBean service the configuration applies to. It also has a required delegateClass name attribute that specifies the class name of the ServicesConfigDelegate implementation that knows how to handle bindings for the target service. Its contents consists of an optional delegate-config element and one or more binding elements.

  • binding: A binding element specifies a named port and address pair. It has an optional name that can be used to provide multiple binding for a service. An example would be multiple virtual hosts for a web container. The port and address are specified via the optional port and host attributes respectively. If the port is not specified it defaults to 0 meaning choose an anonymous port. If the host is not specified it defaults to null meaning any address.

  • delegate-config: The delegate-config element is an arbitrary XML fragment for use by the ServicesConfigDelegate implementation. The hostName and portName attributes only apply to the AttributeMappingDelegate of the example and are there to prevent DTD aware editors from complaining about their existence in the AttributeMappingDelegate configurations. Generally both the attributes and content of the delegate-config are arbitrary, but there is no way to specify and a element can have any number of attributes with a DTD.

The three ServicesConfigDelegate implementations are AttributeMappingDelegate, XSLTConfigDelegate, and XSLTFileDelegate.

10.5.1. AttributeMappingDelegate

The AttributeMappingDelegate class is an implementation of the ServicesConfigDelegate that expects a delegate-config element of the form:

<delegate-config portName="portAttrName" hostName="hostAttrName">
    <attribute name="someAttrName">someHostPortExpr</attribute>
    <!-- ... -->
</delegate-config>

The portAttrName is the attribute name of the MBean service to which the binding port value should be applied, and the hostAttrName is the attribute name of the MBean service to which the binding host value should be applied. If the portName attribute is not specified then the binding port is not applied. Likewise, if the hostName attribute is not specified then the binding host is not applied. The optional attribute element(s) specify arbitrary MBean attribute names whose values are a function of the host and/or port settings. Any reference to ${host} in the attribute content is replaced with the host binding and any ${port} reference is replaced with the port binding. The portName, hostName attribute values and attribute element content may reference system properties using the ${x} syntax that is supported by the JBoss services descriptor.

The sample listing illustrates the usage of AttributeMappingDelegate.

<service-config name="jboss:service=Naming"
                 delegateClass="org.jboss.services.binding.AttributeMappingDelegate">
     <delegate-config portName="Port"/>
     <binding port="1099" />
</service-config>

Here the jboss:service=Naming MBean service has its Port attribute value overridden to 1099. The corresponding setting from the jboss1 server configuration overrides the port to 1199.

10.5.2. XSLTConfigDelegate

The XSLTConfigDelegate class is an implementation of the ServicesConfigDelegate that expects a delegate-config element of the form:

<delegate-config>
    <xslt-config configName="ConfigurationElement"><![CDATA[
        Any XSL document contents...
        ]]>
     </xslt-config>
     <xslt-param name="param-name">param-value</xslt-param>
     <!-- ... -->
</delegate-config>

The xslt-config child element content specifies an arbitrary XSL script fragment that is to be applied to the MBean service attribute named by the configName attribute. The named attribute must be of type org.w3c.dom.Element. The optional xslt-param elements specify XSL script parameter values for parameters used in the script. There are two XSL parameters defined by default called host and port, and their values are set to the configuration host and port bindings.

The XSLTConfigDelegate is used to transform services whose port/interface configuration is specified using a nested XML fragment. The following example maps the port number on hypersonic datasource:

   
<service-config name="jboss.jca:service=ManagedConnectionFactory,name=DefaultDS" 
                delegateClass="org.jboss.services.binding.XSLTConfigDelegate">
    <delegate-config>
        <xslt-config configName="ManagedConnectionFactoryProperties"><![CDATA[
<xsl:stylesheet
      xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>

  <xsl:output method="xml" />
  <xsl:param name="host"/>
  <xsl:param name="port"/>

  <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="config-property[@name='ConnectionURL']">
    <config-property type="java.lang.String" name="ConnectionURL">
       jdbc:hsqldb:hsql://<xsl:value-of select='$host'/>:<xsl:value-of select='$port'/>
    </config-property>
  </xsl:template>

  <xsl:template match="*|@*">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
]]>
        </xslt-config>
     </delegate-config>
     <binding host="localhost" port="1901"/>
</service-config>  

10.5.3. XSLTFileDelegate

The XSLTFileDelegate class works similarly to the XSLTConfigDelegate except that instead of transforming an embedded XML fragment, the XSLT script transforms a file read in from the file system. The delegate-config takes exactly the same form:

<delegate-config>
    <xslt-config configName="ConfigurationElement"><![CDATA[
        Any XSL document contents...
        ]]>
     </xslt-config>
     <xslt-param name="param-name">param-value</xslt-param>
     <!-- ... -->
</delegate-config>

The xslt-config child element content specifies an arbitrary XSL script fragment that is to be applied to the MBean service attribute named by the configName attribute. The named attribute must be a String value corresponding to an XML file that will be transformed. The optional xslt-param elements specify XSL script parameter values for parameters used in the script. There are two XSL parameters defined by default called host and port, and their values are set to the configuration host and port bindings.

The following example maps the host and port values for the Tomcat connectors:

   
<service-config name="jboss.web:service=WebServer"
                delegateClass="org.jboss.services.binding.XSLTFileDelegate">
    <delegate-config>
        <xslt-config configName="ConfigFile"><![CDATA[
   <xsl:stylesheet
         xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>

     <xsl:output method="xml" />
     <xsl:param name="port"/>

     <xsl:variable name="portAJP" select="$port - 71"/>
     <xsl:variable name="portHttps" select="$port + 363"/>

     <xsl:template match="/">
       <xsl:apply-templates/>
     </xsl:template>

      <xsl:template match = "Connector">
         <Connector>
            <xsl:for-each select="@*">
            <xsl:choose>
               <xsl:when test="(name() = 'port' and . = '8080')">
                  <xsl:attribute name="port">
                      <xsl:value-of select="$port" />
                  </xsl:attribute>
               </xsl:when>
               <xsl:when test="(name() = 'port' and . = '8009')">
                  <xsl:attribute name="port">
                      <xsl:value-of select="$portAJP" />
                  </xsl:attribute>
               </xsl:when>
               <xsl:when test="(name() = 'redirectPort')">
                  <xsl:attribute name="redirectPort">
                      <xsl:value-of select="$portHttps" />
                  </xsl:attribute>
               </xsl:when>
               <xsl:when test="(name() = 'port' and . = '8443')">
                  <xsl:attribute name="port">
                      <xsl:value-of select="$portHttps" />
                  </xsl:attribute>
               </xsl:when>
               <xsl:otherwise>
                  <xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>
               </xsl:otherwise>
            </xsl:choose>
            </xsl:for-each>
            <xsl:apply-templates/>
         </Connector>
      </xsl:template>

     <xsl:template match="*|@*">
       <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
       </xsl:copy>
     </xsl:template>
   </xsl:stylesheet>
   ]]>
        </xslt-config>
    </delegate-config>
    <binding port="8280"/>
</service-config> 

10.5.4. The Sample Bindings File

JBoss ships with service binding configuration file for starting up to three separate JBoss instances on one host. Here we will walk through the steps to bring up the two instances and look at the sample configuration. Start by making two server configuration file sets called jboss0 and jboss1 by running the following command from the book examples directory:

[examples]$ ant -Dchap=chap10 -Dex=1 run-example

This creates duplicates of the server/default configuration file sets as server/jboss0 and server/jboss1, and then replaces the conf/jboss-service.xml descriptor with one that has the ServiceBindingManager configuration enabled as follows:

<mbean code="org.jboss.services.binding.ServiceBindingManager"
       name="jboss.system:service=ServiceBindingManager">
    <attribute name="ServerName">${jboss.server.name}</attribute>
    <attribute name="StoreURL">${jboss.server.base.dir}/chap10ex1-bindings.xml</attribute>
    <attribute name="StoreFactoryClassName">
        org.jboss.services.binding.XMLServicesStoreFactory
    </attribute>
</mbean>

Here the configuration name is ${jboss.server.name}. JBoss will replace that with name of the actual JBoss server configuration that we pass to the run script with the -c option. That will be either jboss0 or jboss1, depending on which configuration is being run. The binding manager will find the corresponding server configuration section from the chap10ex1-bindings.xml and apply the configured overrides. The jboss0 configuration uses the default settings for the ports, while the jboss1 configuration adds 100 to each port number.

To test the sample configuration, start two JBoss instances using the jboss0 and jboss1 configuration file sets created previously. You can observe that the port numbers in the console log are different for the jboss1 server. To test out that both instances work correctly, try accessing the web server of the first JBoss on port 8080 and then try the second JBoss instance on port 8180.

10.6. RMI Dynamic Class Loading

The WebService MBean provides dynamic class loading for RMI access to the server EJBs. The configurable attributes for the service are as follows:

  • Port: the WebService listening port number. A port of 0 will use any available port.

  • Host: Set the name of the public interface to use for the host portion of the RMI codebase URL.

  • BindAddress: the specific address the WebService listens on. This can be used on a multi-homed host for a java.net.ServerSocket that will only accept connect requests to one of its addresses.

  • Backlog: The maximum queue length for incoming connection indications (a request to connect) is set to the backlog parameter. If a connection indication arrives when the queue is full, the connection is refused.

  • DownloadServerClasses: A flag indicating if the server should attempt to download classes from thread context class loader when a request arrives that does not have a class loader key prefix.

  • DownloadResources: A flag indicating whether the server should attempt to download non-class file resources using the thread context class loader. Note that allowing this is generally a security risk as it allows access to server configuration files which may contain security settings.

  • ThreadPool: The org.jboss.util.threadpool.BasicThreadPoolMBean instance thread pool used for the class loading.

10.7. Scheduling Tasks

Java includes a simple timer based capability through the java.util.Timer and java.util.TimerTask utility classes. JMX also includes a mechanism for scheduling JMX notifications at a given time with an optional repeat interval as the javax.management.timer.TimerMBean agent service.

JBoss includes two variations of the JMX timer service in the org.jboss.varia.scheduler.Scheduler and org.jboss.varia.scheduler.ScheduleManager MBeans. Both MBeans rely on the JMX timer service for the basic scheduling. They extend the behavior of the timer service as described in the following sections.

10.7.1. org.jboss.varia.scheduler.Scheduler

The Scheduler differs from the TimerMBean in that the Scheduler directly invokes a callback on an instance of a user defined class, or an operation of a user specified MBean.

  • InitialStartDate: Date when the initial call is scheduled. It can be either:

    • NOW: date will be the current time plus 1 seconds

    • A number representing the milliseconds since 1/1/1970

    • Date as String able to be parsed by SimpleDateFormat with default format pattern "M/d/yy h:mm a". If the date is in the past the Scheduler will search a start date in the future with respect to the initial repetitions and the period between calls. This means that when you restart the MBean (restarting JBoss etc.) it will start at the next scheduled time. When no start date is available in the future the Scheduler will not start.

    For example, if you start your Schedulable everyday at Noon and you restart your JBoss server then it will start at the next Noon (the same if started before Noon or the next day if start after Noon).

  • InitialRepetitions: The number of times the scheduler will invoke the target's callback. If -1 then the callback will be repeated until the server is stopped.

  • StartAtStartup: A flag that determines if the Scheduler will start when it receives its startService life cycle notification. If true the Scheduler starts on its startup. If false, an explicit startSchedule operation must be invoked on the Scheduler to begin.

  • SchedulePeriod: The interval between scheduled calls in milliseconds. This value must be bigger than 0.

  • SchedulableClass: The fully qualified class name of the org.jboss.varia.scheduler.Schedulable interface implementation that is to be used by the Scheduler . The SchedulableArguments and SchedulableArgumentTypes must be populated to correspond to the constructor of the Schedulable implementation.

  • SchedulableArguments: A comma separated list of arguments for the Schedulable implementation class constructor. Only primitive data types, String and classes with a constructor that accepts a String as its sole argument are supported.

  • SchedulableArgumentTypes: A comma separated list of argument types for the Schedulable implementation class constructor. This will be used to find the correct constructor via reflection. Only primitive data types, String and classes with a constructor that accepts a String as its sole argument are supported.

  • SchedulableMBean: Specifies the fully qualified JMX ObjectName name of the schedulable MBean to be called. If the MBean is not available it will not be called but the remaining repetitions will be decremented. When using SchedulableMBean the SchedulableMBeanMethod must also be specified.

  • SchedulableMBeanMethod: Specifies the operation name to be called on the schedulable MBean. It can optionally be followed by an opening bracket, a comma separated list of parameter keywords, and a closing bracket. The supported parameter keywords include:

    • NOTIFICATION which will be replaced by the timers notification instance (javax.management.Notification)

    • DATE which will be replaced by the date of the notification call (java.util.Date)

    • REPETITIONS which will be replaced by the number of remaining repetitions (long)

    • SCHEDULER_NAME which will be replaced by the ObjectName of the Scheduler

    • Any fully qualified class name which the Scheduler will set to null.

A given Scheduler instance only support a single schedulable instance. If you need to configure multiple scheduled events you would use multiple Scheduler instances, each with a unique ObjectName. The following is an example of configuring a Scheduler to call a Schedulable implementation as well as a configuration for calling a MBean.

<server>
                 
    <mbean code="org.jboss.varia.scheduler.Scheduler"
           name="jboss.docs.chap10:service=Scheduler">
        <attribute name="StartAtStartup">true</attribute>
        <attribute name="SchedulableClass">org.jboss.chap10.ex2.ExSchedulable</attribute>
        <attribute name="SchedulableArguments">TheName,123456789</attribute>
        <attribute name="SchedulableArgumentTypes">java.lang.String,long</attribute>
                 
        <attribute name="InitialStartDate">NOW</attribute>
        <attribute name="SchedulePeriod">60000</attribute>
        <attribute name="InitialRepetitions">-1</attribute>
    </mbean>
                 
</server> 

The SchedulableClass org.jboss.chap10.ex2.ExSchedulable example class is given below.

package org.jboss.chap10.ex2;

import java.util.Date;
import org.jboss.varia.scheduler.Schedulable;

import org.apache.log4j.Logger;

/**
 * A simple Schedulable example.
 * @author Scott.Stark@jboss.org
 * @version $Revision: 1.14 $
 */
public class ExSchedulable implements Schedulable
{
    private static final Logger log = Logger.getLogger(ExSchedulable.class);

    private String name;
    private long value;

    public ExSchedulable(String name, long value)
    {
        this.name = name;
        this.value = value;
        log.info("ctor, name: " + name + ", value: " + value);
    }

    public void perform(Date now, long remainingRepetitions)
    {
        log.info("perform, now: " + now +
                 ", remainingRepetitions: " + remainingRepetitions +
                 ", name: " + name + ", value: " + value);
    }
}

Deploy the timer SAR by running:

[examples]$ ant -Dchap=chap10 -Dex=2 run-example

The server console shows the following which includes the first two timer invocations, separated by 60 seconds:

21:09:27,716 INFO  [ExSchedulable] ctor, name: TheName, value: 123456789
21:09:28,925 INFO  [ExSchedulable] perform, now: Mon Dec 20 21:09:28 CST 2004, 
  remainingRepetitions: -1, name: TheName, value: 123456789
21:10:28,899 INFO  [ExSchedulable] perform, now: Mon Dec 20 21:10:28 CST 2004, 
  remainingRepetitions: -1, name: TheName, value: 123456789
21:11:28,897 INFO  [ExSchedulable] perform, now: Mon Dec 20 21:11:28 CST 2004, 
  remainingRepetitions: -1, name: TheName, value: 123456789

10.8. The Timer Service

The JMX standard defines a timer MBean (javax.management.timer.Timer) which can send notifications at predetermined times. The a timer MBean can be instantiated within JBoss as any other MBean.

<mbean code="javax.management.timer.Timer" name="jboss.monitor:name=Heartbeat,type=Timer"/>

A standard JMX timer doesn't produce any timer events unless it is asked to. To aid in the configuration of the timer MBean, JBoss provides a complementary TimerService MBean. It interacts with the timer MBean to configure timer events at regular intervals and to transform them into JMX notifications more suitable for other services. The TimerService MBean takes the following attributes:

  • NotificationType: This is the type of the notification to be generated.

  • NotificationMessage: This is the message that should be associated with the generated notification.

  • TimerPeriod: This is the time period between notification. The time period is in milliseconds, unless otherwise specified with a unit like "30min" or "4h". Valid time suffixes are msec, sec, min and h.

  • Repeatitions: This is the number of times the alert should be generated. A value of 0 indicates the alert should repeat indefinitely.

  • TimerMbean: This is the ObjectName of the time MBean that this TimerService instance should configure notifications for.

The following sample illustrates the the use of the TimerService MBean.

<mbean code="org.jboss.monitor.services.TimerService" 
       name="jboss.monitor:name=Heartbeat,type=TimerService">
    <attribute name="NotificationType">jboss.monitor.heartbeat</attribute>
    <attribute name="NotificationMessage">JBoss is alive!</attribute>
    <attribute name="TimerPeriod">60sec</attribute>
    <depends optional-attribute-name="TimerMBean">
        jboss.monitor:name=Heartbeat,type=Timer
    </depends>
</mbean>

This MBean configuration configures the jboss.monitor:name=Heartbeat,type=Timer timer to generate a jboss.monitor.heartbeat notification every 60 seconds. Any service that that wants to receive this periodic notifications can subscribe to the notification.

As an example, JBoss provides a simple NotificationListener MBean that can listen for a particular notifcation and log a log message when an event is generated. This MBean is very useful for debugging or manually observing notifications. The following MBean definition listens for any events generated by the heartbeat timer used in the previous examples.

<mbean code="org.jboss.monitor.services.NotificationListener" 
       name="jboss.monitor:service=NotificationListener">
    <attribute name="SubscriptionList">
        <subscription-list>
            <mbean name="jboss.monitor:name=Heartbeat,type=Timer" />
        </subscription-list>
    </attribute>
</mbean>

The subscription-list element lists which MBeans the listener should listen to. Notice that the MBean we are listening to is the name of the actual timer MBean and not the TimerService MBean. Because the timer might generate multiple events, configured by multiple TimerService instances, you may need to filter by notification type. The filter element can be used to create notification filters that select only the notification types desired. The following listing shows how we can limit notifications to only the jboss.monitor.heartbeat type the timer service configured.

<mbean code="org.jboss.monitor.services.NotificationListener"
      name="jboss.monitor:service=NotificationListener">
    <attribute name="SubscriptionList">
        <subscription-list>
            <mbean name="jboss.monitor:name=Heartbeat,type=Timer">
                <filter factory="NotificationFilterSupportFactory">
                    <enable type="jboss.monitor.heartbeat"/>                        
                </filter>
            </mbean>
        </subscription-list>
    </attribute>
</mbean>

As an example of a slightly more interesting listener, we'll look at the ScriptingListener. This listener listens for particular events and then executes a specified script when events are received. The script can be writen in any bean shell scripting language. The ScriptingListener accepts has the following parameters.

  • ScriptLanguage: This is the language the script is written in. This should be beanshell, unless you have loaded libraries for another beanshell compatible language.

  • Script: This is the text of the script to evaluate. It is good practice to enclose the script in a CDATA section to minimize conflicts between scripting language syntax and XML syntax.

  • SubscriptionList: This is the list of MBeans that this MBean will listen to for events that will trigger the script.

The following example illustrates the use of the ScriptingListener. When the previously configured timer generates a heartbeat notification, the beanshell script will execute, printing the current memory values to STDOUT. (This output will be redirected to the log files) Notice that the beanshell script has a reference to the MBean server and can execute operations against other MBeans.

<mbean code="org.jboss.monitor.services.ScriptingListener" 
       name="jboss.monitor:service=ScriptingListener"> 
    <attribute name="SubscriptionList">
        <subscription-list>
            <mbean name="jboss.monitor:name=Heartbeat,type=Timer"/>
        </subscription-list>
    </attribute>
    <attribute name="ScriptLanguage">beanshell</attribute>
    <attribute name="Script">
                <![CDATA[
   import javax.management.ObjectName;

   /* poll free memory and thread count */   
   ObjectName target = new ObjectName("jboss.system:type=ServerInfo");

   long freeMemory = server.getAttribute(target, "FreeMemory");
   long threadCount = server.getAttribute(target, "ActiveThreadCount");

   log.info("freeMemory" + freeMemory + ", threadCount" + threadCount);
]]>
    </attribute>
</mbean>

Of course, you are not limited to these JBoss-provided notification listeners. Other services such as the barrier service (see Section 10.9, “The BarrierController Service”) receive and act on notifications that could be generated from a timer. Additionally, any MBean can be coded to listen for timer-generated notifications.

10.9. The BarrierController Service

Expressing dependencies between services using the <depends> tag is a convenient way to make the lifecycle of one service depend on the lifecycle of another. For example, when serviceA depends on serviceB JBoss will ensure the serviceB.create() is called before serviceA.create() and serviceB.start() is called before serviceA.start().

However, there are cases where services do not conform to the JBoss lifecycle model, i.e. they don't expose create/start/stop/destroy lifesycle methods). This is the case for jboss.system:type=Server MBean, which represents the JBoss server itself. No lifecycle operations are exposed so you cannot simply express a dependcy like: 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 sufficient to describe a dependency. For example the jboss.web:service=WebServer MBean that wraps the embedded Tomcat server in JBoss does not start the Tomcat connectors until after the 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 shuts down. Similarly, jboss.web:service=WebServer emits a notification of type jboss.tomcat.connectors.started when it starts up. Services can subscribe to those notifications in order to implement more complex dependencies. This technique has been generalized with the barrier controller service.

The barrier controller is a relatively simple MBean service that extends ListenerServiceMBeanSupport and thus can subscribe to 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 barrier controller 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 <depends> tag, without having to worry about complex lifecycle issues. They will be started and stopped in tandem with the Barrier. When the barrier controller is undeployed the barrier is destroyed.

The notifications of interest are configured in the barrier controller 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 barrier controller. Thus we can have more than one notifications triggering the starting or stopping of the barrier.

The following example shows a service that depends on the Tomcat connectors. 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.

<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: chap10.xml,v 1.14 2006/04/27 01:19:12 nrichards Exp $ -->

<server>
  <!--
    In this example we have the BarrierController controlling a Barrier
    that is started when we receive the "jboss.tomcat.connectors.started"
    notification from the Tomcat mbean, and stopped when we receive the
    "org.jboss.system.server.stopped" notification from the server mbean.
    
    The dependent services need only define a dependency on the Barrier mbean!
  -->
  <mbean code="org.jboss.system.BarrierController"
         name="jboss:service=BarrierController">
    
    <!-- Whether to have the Barrier initially started or not -->
    <attribute name="BarrierEnabledOnStartup">false</attribute>
    
    <!-- Whether to subscribe for notifications after startup -->
    <attribute name="DynamicSubscriptions">true</attribute>
    
    <!-- Dependent services will depend on this mbean -->
    <attribute name="BarrierObjectName">jboss:name=TomcatConnector,type=Barrier</attribute>
    
    <!-- The notification subscription handback that starts the barrier -->
    <attribute name="StartBarrierHandback">start</attribute>
    
    <!-- The notification subscription handback that stops the barrier -->
    <attribute name="StopBarrierHandback">stop</attribute>
    
    <!-- The notifications to subscribe for, along with their handbacks -->
    <attribute name="SubscriptionList">
      <subscription-list>
        <mbean name="jboss.web:service=WebServer" handback="start">
          <filter factory="NotificationFilterSupportFactory">
            <enable type="jboss.tomcat.connectors.started"/>
          </filter>
        </mbean>
        <mbean name="jboss.system:type=Server" handback="stop">
          <filter factory="NotificationFilterSupportFactory">
            <enable type="org.jboss.system.server.stopped"/>
          </filter>
        </mbean>        
      </subscription-list>
    </attribute>
  </mbean>

  <!--
    An example service that depends on the Barrier we declared above.
    This services creates a background thread and monitors the memory
    usage. When it exceeds the defined thresholds it emits notifications
  -->
  <mbean code="org.jboss.monitor.services.MemoryMonitor"
         name="jboss.monitor:service=MemoryMonitor">

    <attribute name="FreeMemoryWarningThreshold">20m</attribute>
    <attribute name="FreeMemoryCriticalThreshold">15m</attribute>
    
    <!-- The BarrierObjectName configured in the BarrierController -->
    <depends>jboss:name=TomcatConnector,type=Barrier</depends>
  </mbean>
  
</server>

If you hot-deploy this on a running server the Barrier will be stopped because by the time the barrier controller 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 or stop the barrier by using the startBarrier() and stopBarrier() operations on the barrier controller. The attribute BarrierStateString indicates the status of the barrier.

10.10.  Exposing MBean Events via SNMP

JBoss has an SNMP adaptor service that can be used to intercept JMX notifications emitted by MBeans, convert them to traps and send them to SNMP managers. In this respect the snmp-adaptor acts as a SNMP agent. Future versions may offer support for full agent get/set functionality that maps onto MBean attributes or operations.

This service can be used to integrate JBoss with higher order system/network management platforms (HP OpenView, for example), making the MBeans visible to those systems. The MBean developer can instrument the MBeans by producing notifications for any significant event (e.g. server coldstart), and adaptor can then be configured to intercept the notification and map it onto an SNMP traps. The adaptor uses the JoeSNMP package from OpenNMS as the SNMP engine.

The SNMP service is configured in snmp-adaptor.sar. This service is only available in the all configuration, so you'll need to copy it to your configuration if you want to use it. Inside the snmp-adaptor.sar directory, there are two configuration files that control the SNMP service.

The SNMPAgentService MBean is configured in snmp-adaptor.sar/META-INF/jboss-service.xml. The configurable parameters are:

  • HeartBeatPeriod: The period in seconds at which heartbeat notifications are generated.

  • ManagersResName: Specifies the resource name of the managers.xml file.

  • NotificationMapResName: Specifies the resource name of the notications.xml file.

  • TrapFactoryClassName: The org.jboss.jmx.adaptor.snmp.agent.TrapFactory implementation class that takes care of translation of JMX Notifications into SNMP V1 and V2 traps.

  • TimerName: Specifies the JMX ObjectName of the JMX timer service to use for heartbeat notifications.

  • SubscriptionList: Specifies which MBeans and notifications to listen for.

The schema for the SNMP managers file

Figure 10.2. The schema for the SNMP managers file

The schema for the notification to trap mapping file

Figure 10.3. The schema for the notification to trap mapping file

TrapdService is a simple MBean that acts as an SNMP Manager. It listens to a configurable port for incoming traps and logs them as DEBUG messages using the system logger. You can modify the log4j configuration to redirect the log output to a file. SnmpAgentService and TrapdService are not dependent on each other.