© Copyright O'Reilly & Associates. All rights reserved.
By far the most straightforward type of MBean to create, standard MBeans are a logical starting place for our voyage into the world of JMX. In this chapter, we will begin by defining a management interface, then we will look at the design patterns we must use when building standard MBeans. Next, we will discuss some of the issues involved when using inheritance among standard MBean classes. Then we will look at some common pitfalls of using standard MBeans that might leave you scratching your head, wondering why your MBeans aren't working as expected. Finally, we will discuss some advanced topics and things to consider when creating standard MBeans. This chapter includes several examples from the sample application that is used throughout this book. When you have completed this chapter, you should be able to create standard MBeans and understand the issues involved in doing so.
What Is a Management Interface?
The idea of a management interface revolves around the notion of an application resource, which is any abstraction within an application that provides value. A resource can be, for example, a business component of the application, an infrastructure component such as a cache or queue, or even the application itself. With respect to JMX (and more broadly, system management), only those resources that must be managed are significant. Each resource that is to be managed must provide a management interface, which consists of the attributes and operations it exposes so that it can be monitored and controlled by a management application.
For example, suppose a resource we wish to manage in our application is a queue. A queue is generally used to temporarily store a logical unit of work provided by a supplier until that unit of work is removed from the queue by a consumer for further processing. This is typically done asynchronously, via a multithreaded design, so the queue must also be thread-safe. Let's suppose there is a single supplier thread in the application and a single consumer thread, and that the queue is thread-safe, so that the supplier will wait to add an item to the queue if it is full (and conversely, the consumer will wait on the queue to remove an item if the queue is empty). In monitoring the queue, we want to know two things:
- How long has the supplier waited (i.e., the accumulated wait time)to add an item to the queue because the queue is full?
- How long has the consumer waited to remove an item from the queue because the queue is empty?
Because these two pieces of information are important to us for monitoring the application, it makes sense that we expose them as two attributes on the management interface of the queue. Of course, the queue must be written so that this information is captured, so that it can be exposed in the first place! But that is very straightforward to do and will be handled by our application's Queue class.
I won't spend a lot of time explaining all of the attributes and operations exposed on the management interface of the queue, because the goal of this chapter is to illustrate the mechanics and theory of standard MBeans, not how to design queues.
One other thing to consider is whether the values of these attributes are in milliseconds (the clock tick count, on most systems). If so, and if our application is long-running, we should probably use a long as the data type for these attributes to allow them to contain very large values.
Now that we have decided to expose these two attributes, we must decide whether to make them read-only, write-only, or read/write when we expose them on the management interface. It doesn't make much sense for these attributes to be write-only (because then we could only set them and not look at their values at any particular point in time), so we rule that option out right away. Making these attributes readable makes sense, but should we allow the management application to set their values? We could allow the management application to reset both of these values to zero by exposing an operation to handle this action, thus preventing a user of the management application from setting these values to something unreasonable.
The management interface for our queue now has the following:
- A read-only attribute whose value is the total accumulated time spent by the supplier waiting to add a unit of work to the queue because the queue is full
- A read-only attribute whose value is the total accumulated time spent by the consumer waiting to remove a unit of work from the queue because the queue is empty
- An operation that resets both attributes to zero
We may also want to be able to manage the size of the queue. To allow this, we can define an attribute on the queue and expose that attribute on the management interface as a read/write attribute. This allows us to view the current size of the queue and to modify that value to tweak the queue for maximum performance at runtime. In addition, we might be interested in the total number of workunits processed by the queue, so that we can get an idea of the throughput of the application with respect to any particular instance of our queue. As long as it makes sense and fits in with the design of the queue, the sky's the limit on what we can expose on our queue's management interface. Table 2-1 summarizes the attributes we will expose on our Queue resource.
Table 2-1. Attributes exposed for management on the Queue class
|Add Wait Time||long||Read-only|
|Remove Wait Time||long||Read-only|
|Number of Items Processed||long||Read-only|
|Number of Suppliers||int||Read-only|
|Number of Consumers||int||Read-only|
These attributes will be discussed in detail in the next section, where we will actually implement the queue's management interface as a standard MBean.
Next, let's consider the operations to expose on the management interface of the Queue class. We touched briefly on the reset operation earlier in this chapter. Other operations we may want to include offer the management application the ability to suspend and resume activity in the queue. This allows the management application to halt processing so that, for example, an operator can look at a "snapshot" of what is happening inside the queue. It may also be helpful for the operator to be able to turn on and off tracing. Table 2-2 summarizes the operations on our queue's management interface.
Table 2-2. Operations exposed for management on the Queue class
|Reset||Resets the state of the queue|
|Suspend||Suspends activity in the queue; all suppliers and consumers sleep until Resume is called|
|Resume||Signals to sleeping suppliers and consumers that activity may continue|
|Enable Tracing||Turns on any tracing done by the queue|
|Disable Tracing||Turns off tracing|
Now that we have defined the management interface for our Queue class, it's time to see how to instrument our class as a standard MBean using the design patterns in the JMX specification.
Page 1 of 7