dcsimg
December 7, 2016
Hot Topics:

Standard MBeans

  • May 23, 2003
  • By O'Reilly & Associates
  • Send Email »
  • More Articles »

How Do Standard MBeans Work?

In this section, we will learn how to instrument a Java class as a standard MBean. We will first look at how to describe the management interface according to the JMX design patterns for standard MBeans. Then we will look at how to implement the MBean interface on the Queue class touched on earlier in this chapter. Many examples will be provided. It is here that we will examine all of the classes that make up the application, showing inheritance patterns and other cool standard MBean miscellany. We will also look at the Controller class's main() routine, which is what drives the application, and we will discuss how to register MBeans with the MBean server, how to register and use the HTML Adaptor server, and how to build and run the example.

Describing the Management Interface

JMX provides us with a set of patterns to follow when instrumenting our application resources as standard MBeans. If we follow these patterns exactly as they are set out in the specification, our standard MBeans are said to be compliant. If we don't correctly follow the patterns, the MBean server (part of the reference implementation; we'll discuss the MBean server later in this chapter) will declare our MBean as non-compliant by throwing a javax.management.NotCompliantMBeanException at the agent that attempts to register the MBean. However, it is possible for us to correctly follow the patterns but still not expose the correct management interface on our standard MBean. We will also look at that case in this section.

There are three patterns you must follow when instrumenting your resources as standard MBeans:

  • The management interface of the resource must have the same name as the resource's Java class, followed by "MBean"; it must be defined as a Java interface; and it must be implemented by the resource to be managed using the implements keyword.
  • The implementing class must contain at least one public constructor.
  • Getters and setters for attributes on the management interface must follow strict naming conventions.

Each of these patterns is discussed in detail in this section.

Pattern #1: Defining, naming, and implementing the MBean interface

The management interface must be defined using the Java interface keyword, it must have public visibility, and it must be strictly named. Earlier in this chapter, we looked at the thought process we might go through to define a management interface for a queue. Suppose the name of this class is Queue. Its standard MBean management interface must be defined as:

public interface QueueMBean {
//management interface goes here. . .
}

The Queue class, in turn, must implement the QueueMBean interface using the Java implements keyword:

public class Queue implements QueueMBean {
//implementation of QueueMBean
//and other stuff here. . .
}

The name of the MBean interface is case-sensitive. For example, QueueMbean is not the same as QueueMBean. Of course, the compiler will help you if you "fat-finger"the spelling of the interface in either the interface definition or the implementation. However, if you use the same misspelling in both, the compiler will chug merrily along and produce perfectly runnable bytecode. Only when you attempt to register your MBean will you receive a NotCompliantMBeanException exception!

The management interface is contained in its own .java file and must have the same name as its corresponding interface. Thus, every standard MBean requires at least two source code files:one for the interface and one for the class that implements the interface.

Another example from the application we use throughout this book is the Worker class. Its management interface is defined as:

public interface WorkerMBean {
//. . .
}

The Worker class, in turn, implements this interface as:

public class Worker implements WorkerMBean {
//. . .
}
The JMX specification states that the class that implements the MBean interface must be declared public and be a concrete (i.e., not abstract) class. However, using the JMX 1.0 RI, I was able to instantiate, register, and manage an MBean with only package-level visibility. This is most likely an oversight in the RI. You should not count on being able to do this in future versions of the RI, or in other JMX implementations, because this behavior is not supported by the specification.

Pattern #2: Provide at least one public constructor

The class that implements the MBean interface must have at least one constructor declared with public visibility. This class may have any number of public constructors, but it must have at least one. If you do not provide a constructor, the compiler will generate a no-argument constructor with public visibility. This will work fine for your MBeans, but I recommend that you explicitly declare a no-argument constructor for these cases, as your code will follow the rule and be more readable as well. Continuing with the code snippets from earlier, then, our Queue class would look like:

public class Queue implements QueueMBean {
  public Queue(){
    //do something here. . .
  }
  //other class methods and management interface
  //implementation. . .
}

However, the Queue class might not have a no-argument constructor at all:

public class Queue implements QueueMBean {
  //no no-arg constructor provided, that's okay. . .
  public Queue(int queueSize){
    //do something custom here. . .
  }
  //other class methods and management interface
  //implementation. . .
}

and still be a compliant MBean, because it provides a public constructor.

Pattern #3: Attributes and how to name their getters and setters

When defining an attribute on the management interface, you must follow strict naming standards. If the attribute is readable, it must be declared on the interface (and subsequently implemented) as getAttributeName(), where AttributeName is the name of the attribute you want to expose, and take no parameters. This method is called a getter. Table 2-1 showed some of the attributes we plan to expose on the Queue class. As an example, we would define the Add Wait Time attribute on the management interface as:

public interface QueueMBean {
  public long getAddWaitTime();
  //. . .
}
Notice the use of "camel case" in the naming of our attribute. If an attribute's name consists of multiple words, the words are placed together and the first letter of each word is capitalized. This is a fairly common practice and will be used throughout this book.

For boolean values, preceding the attribute name with "is"is a common idiom and one that is acceptable according to the JMX standard MBean design patterns. From Table 2-1, notice that we have a boolean attribute called Suspended. We would define this attribute on the management interface as:

public interface QueueMBean {
  public long getAddWaitTime();
  //. . .
  public boolean isSuspended();
  //. . .
}

If an attribute is writable, the naming pattern is similar to that for readable attributes, only the word "get"is replaced with "set," and the attribute takes a single parameter whose type is that of the attribute to be set. This method is called a setter. For example, Table 2-1 shows a readable and writable attribute called QueueSize. We would define this attribute on the management interface as:

public interface QueueMBean {
  public long getAddWaitTime();
  //. . .
  public boolean isSuspended();
  //. . .
  public int getQueueSize();
  public void setQueueSize(int value);
  //. . .
}

There are two rules about setters:

  • The setter can take only a single parameter. If you unintentionally provide a second parameter to what you thought you were coding as a setter, the MBean server will expose your "setter" as an operation.
  • The parameter types must be the same for read/write attributes, or your management interface will not be what you expect. In fact, if you have a read/write attribute where the getter returns a different data type than the setter takes as a parameter, the setter controls. For example, suppose that I mistakenly coded the setter for QueueSize to take a short data type. My management interface would then look like:

    public interface QueueMBean {
      public long getAddWaitTime();
      //. . .
      public boolean isSuspended();
      //. . .
      public int getQueueSize();
      public void setQueueSize(short value);
      //. . .
    }
    
    Strangely enough, what I have actually exposed is a single write-only attribute called QueueSize, of type short! Clearly, that is not what I intended. Of course, remember that with standard MBeans, the Java compiler can catch some of these mistakes for you. Let's say that I made this particular mistake on the interface definition, but on the implementing class I used the proper int type on my setter. The compiler would tell me that I should declare the implementing class abstract, because it doesn't define the setter that takes the short! That is one advantage of standard MBeans over other MBean types—the compiler can help you find mistakes before they turn into nasty bugs.

Using the information from Tables 2-1 and 2-2, the management interface is shown in Example 2-1.

Example 2-1. The QueueMBean interface

public interface QueueMBean {
  //attributes
  public long getAddWaitTime();
  public long getRemoveWaitTime();
  public int getQueueSize();
  public void setQueueSize(int value);
  public long getNumberOfItemsProcessed();
  public boolean isQueueFull();
  public boolean isQueueEmpty();
  public boolean isSuspended();
  public int getNumberOfSuppliers();
  public int getNumberOfConsumers();
  //operations
  public void reset();
  public void suspend();
  public void resume();
  public void enableTracing();
  public void disableTracing();
}

A word about introspection

Introspection literally means to "look inside" and is performed by the MBean server to ensure compliance on the part of your MBeans when they are registered. Because it is possible to write Java code that cleanly compiles and executes but does not follow the standard MBean design patterns we discussed earlier, the MBean server looks inside your MBean to make sure you followed the patterns correctly.

When your MBean is registered by the agent, the MBean server uses Java's reflection API to crawl around inside the MBean and make sure that the three design patterns we discussed earlier were followed. If they were, your MBean is compliant and its registration proceeds. If not, the MBean server throws an exception at the agent.

Introspection takes place only when your MBean is registered by the agent. Depending on the code paths your application takes when instantiating your MBean classes, the notification (via an exception) that one of your MBeans is not compliant will appear only when the MBean is registered.





Page 2 of 7



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date
Rocket Fuel