In this section we will walk through the development of standard and dynamic MBeans for a simple web server.

A Simple Web Server

The UML diagram below illustrates the static structure of a simple HTTP daemon:

HTTP UML

Disclaimer: this code provides none of the usual web server security features and will happily retrieve any file on your computer.

The daemon uses a simple pipeline to handle HTTP GET requests. The listener encapsulates a server socket upon which it waits for HTTP requests. As requests come in they get placed in the request queue. Handlers from the HandlerPool pick up requests from the queue, log the request in a LogFile, and return the requested file to the client.

Suppose that we want to make the following elements of this design JMX manageable:

Listener, HandlerPool, and LogFile are all classes we've written so we will turn them into standard MBeans. The RequestQueue is implemented via a java.util.SortedSet. Since we don't have the source for java.util.SortedSet RequestQueue will be a dynamic MBean.

An Instrumented Web Server

To turn Listener, HandlerPool, and LogFile into standard MBeans we must define a management interface for each class. The management interface is specified by a Java interface that follows the JMX standard MBean naming convention: the management interface of a given class, say Foo, is specified by an interface named FooMBean. Dynamic MBeans are created by implementing the DynamicMBean interface.

Applying these conventions to our design yields the following structure:

Managed HTTP Daemon

A management interface should expose the resource attributes that will be monitored and the methods that will be used to control the resource. Keep in mind that the management interface may be exposed to administrators on remote consoles. In general, simpler is better.

Standard MBeans

The listener's management interface exposes three attributes: Port, Requests, and Listening. The first attribute is the IP port upon which the listener listens, the second is the number of requests the daemon has handled, and the third indicates whether or not the daemon is listening for requests. The port is a read/write attribute; the interface contains both a getPort() and a setPort() method. The requests and listening attributes are read-only; the interface includes only a getRequests() method and an isListening()method - the latter form is permissable for boolean attributes. Note that, as with JavaBean properties, an attribute is exposed via methods in an interface not by direct access to a data member. The listener exposes two control methods: startListening() and stopListening(). Their meaning should be obvious.

The handler pool's management interface exposes one attribute and one method. The Size attribute determines the number of handlers in the handler pool. The refill() method allows an administrator to reinitialize the handler pool at runtime.

The log file's management interface exposes two read-only attributes: Size and LastModified, and a method: rollOver. The size attributes indicates the logfile's size in bytes. The lastModified attribute indicates when the log file was last updated. The rollOver method renames the current log file: Httpd.log.backup, and creates a new Httpd.log.

Naturally having defined their management interfaces both the Listener and HandlerPool classes must be altered to appropriately implement those interfaces. No changes are necessary to the LogFile class since it already provides support for its management interface.

A Dynamic MBean

The request queue's dynamic MBean management interface exposes two attributes: Capacity and Length. The former is the space available for requests, the latter is the number of requests currently in the queue. Only one method: clear(), is supported. Note that unlike standard MBeans which must use reflection to discover and use the resource's management interface no reflection is necessary with dynamic MBeans. This makes them a better choice for platforms where java.lang.reflect is not supported, e.g,. J2ME and IBM's VisualAge MicroEdition.

Because the MBeanServer does no introspection of a dynamic MBean we have to create its meta data, the MBeanInfo structure, manually in our implementation of the getMBeanInfo() method. This is the most tedious part of creating a dynamic MBean.