BUY THIS BOOK
Add to Cart

Print Book $34.95


Safari Books Online

What is this?

Add to UK Cart

Print Book £24.95

What is this?

Looking to Reprint this content?

Java Management Extensions
Java Management Extensions

By J. Steven Perry
Price: $34.95 USD
£24.95 GBP

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Java Management Extensions Concepts
The growth of large-scale distributed applications in the past decade has been impressive. Mission-critical business applications have evolved from a sequence of programs running on a single computer to business components running on different machines scattered throughout a network. Managing one application running on a single computer is fairly straightforward; you can monitor the health of the application through the use of a single log file, or operator console, and tools provided by the operating system. The difficulty of managing today's distributed systems has increased along with the complexity of those systems. When considering a management solution for today's enterprise applications, some questions arise:
  • Which management solution is best for the application?
  • What standards should a management solution follow?
  • How much effort is required to enable the components of the application to be managed?
Java Management Extensions ( JMX), the result of the Java Community Process ( JCP) Java Specification Request ( JSR) 3, was designed to deal with all of these questions. JMX was designed to address the management needs of applications written for the Java platform and to be compatible with existing management standards, such as the Simple Network Management Protocol (SNMP), which is the standard for management of enterprise networks. It was also designed so that instrumentation of resources to put them under the control of a management application is as easy as possible.
A resource is any entity in the system that needs to be monitored and/or controlled by a management application; resources that can be monitored and controlled are called manageable. A management application is a piece of software that can be used to monitor and control manageable resources (typically remotely). Managing a system of manageable resources is what we call system management. The JMX architecture enables Java applications (or systems) to become manageable.
Three fundamental questions must be addressed by any complete management solution:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Introducing JMX
A resource is any entity in the system that needs to be monitored and/or controlled by a management application; resources that can be monitored and controlled are called manageable. A management application is a piece of software that can be used to monitor and control manageable resources (typically remotely). Managing a system of manageable resources is what we call system management. The JMX architecture enables Java applications (or systems) to become manageable.
Three fundamental questions must be addressed by any complete management solution:
  • How do I make my resources manageable?
  • Once my resources are manageable, how do I make them available (visible) for management?
  • Once my resources are visible for management, how do management applications access them?
The JMX architecture is composed of three levels, each of which answers one of these questions.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
JMX Architecture
In this section, we will take a look at the three levels of the JMX architecture. The level closest to the application is called the instrumentation level. This level consists of four approaches for instrumenting application and system resources to be manageable (i.e., making them managed beans, or MBeans), as well as a model for sending and receiving notifications. JMX notifications are analogous to SNMP traps.
The middle level of the JMX architecture is called the agent level. This level contains a registry for handling manageable resources (the MBean server) as well as several agent services, which themselves are MBeans and thus are manageable. The combination of an instance of the MBean server, its registered MBeans, and any agent services in use within a single Java Virtual Machine ( JVM) is typically referred to as a JMX agent.
The third level of the JMX architecture is called the distributed services level. This level contains the middleware that connects JMX agents to applications that manage them (management applications). This middleware is broken into two categories: protocol adaptors and connectors. Through a protocol adaptor, an application such as a web browser can connect to one or more JMX agents and manage the MBeans that are registered within it (for example, via HTTP). As long as the management application can understand the objects contained in the protocol stream, it can manage the MBeans they represent; thus, protocol adaptors do not need to be written in Java. A connector follows the familiar proxy pattern and is made up of a client and server pair. The server half of the connector pair is normally collocated with the JMX agent it represents (although this is not required), while the client half runs in the JVM of the management application. Issues such as security and Java serialization are understood by both the client and server components of the connector.
The JMX architecture is depicted graphically in Figure 1-1.
Figure 1-1: The JMX architecture (note: protocol adaptors and connectors are not currently standardized)
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Sample Producer/Consumer Application
In the remainder of this chapter, we will build and run a sample application that demonstrates each MBean instrumentation approach. The sections that follow look at the design of the application, where to obtain the source code, how to actually build and run the application, and how to monitor the application via a web browser.
In this section, we will take a look at how the sample application is designed, so that you can better understand what is going on when you see it run. First, we will look at the pattern that is fundamental to the application's design. Then we will see how the pattern is implemented and what classes constitute the source code for the application.
The design pattern used in the application is a monitor. A monitor is a construct that coordinates activity between multiple threads in the system. In this pattern, the monitor coordinates activities between two categories of threads: producer threads and consumer threads. As you might imagine, a producer thread provides something that the consumer uses. That "something" is generically defined as a unit of work. This can be physically realized as anything relevant to a problem that is solved by this pattern.
For example, the unit of work might be an email message that is sent to the email system (the monitor) by the producer (an email client) and removed by the consumer (some agent on the incoming email server side). The producer might perform additional processing on the message before sending it to the email system, such as checking the spelling. By the same token, the consumer may perform additional processing of the message after removing it from the queue, such as applying an anti-virus check. For this reason, we will refer to the pattern as "value-added producer/consumer." This pattern is shown in UML notation in Figure 1-9.
Figure 1-9: UML diagram showing the "value-added producer/consumer" pattern
As you can see in Figure 1-9, the producer and consumer are separated (decoupled) by the monitor. This pattern is best applied to systems that are inherently asynchronous in nature, where the producer and consumer are decoupled by varying degrees. This decoupling can be a separation of location as well as of synchronicity.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Standard MBeans
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.
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:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
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.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
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.
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 noncompliant 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.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Downloading and Installing the JMX Reference Implementation
Before you can build and run the application, you must first obtain the JMX RI. The easiest way to do this is to download it from Sun Microsystems at http://java.sun.com/products/JavaManagement/. Select either the source code or binary RI under "JMX Deliverables" and follow the instructions.
Once you've downloaded the RI, you should unzip the downloaded file directly into your c:\ drive for Windows or your home directory for Unix.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Dynamic MBeans
Standard MBeans are well suited for management interfaces that are relatively static. However, if a management interface must be defined for an existing resource, is likely to evolve over time, or for some other reason needs to be exposed at runtime, JMX provides an interface that allows you to do just that. In this chapter, we will start by looking at the reasons for instrumenting application code as dynamic MBeans. Then we will look at the metadata classes that are used to define the management interface of a dynamic MBean. Next, we will explore ways to implement the DynamicMBean interface and show how the MBeanInfo metadata class is critical in making dynamic MBeans work. At the end of the chapter, we will examine the management interface inheritance patterns that are used with dynamic MBeans.
This chapter assumes that you either are already familiar with standard MBeans or have read Chapter 2.
The main reason to use dynamic MBeans is to more easily instrument existing code that is written in a manner that conflicts with the standard MBean design patterns we discussed in Chapter 2. The dynamic MBean interface is determined not through introspection, but rather through a method call on the dynamic MBean itself. This method, called getMBeanInfo( ) , returns information about the management interface and is defined on the DynamicMBean interface; it is the portal through which a management application views what has been exposed on the management interface of a resource that has been instrumented as a dynamic MBean.
Another reason to use dynamic MBeans is so that you can provide descriptions of the MBean features that are visible to the management application. An MBean feature is an attribute, constructor, operation, parameter, or notification of an MBean. The feature description is a brief explanation of what a particular feature means when viewed from a management application. The feature's name usually indicates what it means, but this isn't always the case. Feature descriptions are not available to standard MBeans.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Why Use Dynamic MBeans?
The main reason to use dynamic MBeans is to more easily instrument existing code that is written in a manner that conflicts with the standard MBean design patterns we discussed in Chapter 2. The dynamic MBean interface is determined not through introspection, but rather through a method call on the dynamic MBean itself. This method, called getMBeanInfo( ) , returns information about the management interface and is defined on the DynamicMBean interface; it is the portal through which a management application views what has been exposed on the management interface of a resource that has been instrumented as a dynamic MBean.
Another reason to use dynamic MBeans is so that you can provide descriptions of the MBean features that are visible to the management application. An MBean feature is an attribute, constructor, operation, parameter, or notification of an MBean. The feature description is a brief explanation of what a particular feature means when viewed from a management application. The feature's name usually indicates what it means, but this isn't always the case. Feature descriptions are not available to standard MBeans.
Because the dynamic MBean interface is exposed at runtime, rather than at compile time (as a standard MBean is), the management interface is exposed through metadata classes. If the management interface is likely to change over time, dynamic MBeans offer a more flexible way to instrument a resource. The management interface is not statically bound to a dynamic MBean, as it is for a standard MBean. Rather, the management interface is exposed dynamically. As such, it is conceivable that a dynamic MBean could—without code changes—expose a different interface from one instance to the next by reading which attributes and operations to expose from a configuration file.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
How Do Dynamic MBeans Work?
Like standard MBeans, dynamic MBeans must be created and registered with the MBean server. When the MBean server is asked to register a dynamic MBean, however, no introspection is performed. Recall that it is the strict application of the standard MBean design patterns (discussed in Chapter 2)—enforced through introspection—that tells the MBean server what management interface is exposed on an MBean. So, how does a dynamic MBean expose its management interface?
Instead of using a Java interface with the name "MBean" on it, dynamic MBeans use metadata classes to expose their management interfaces. They make that metadata available through an interface called DynamicMBean , which must be implemented by all dynamic MBeans. This interface is shown in Example 3-1.
Example 3-1. The DynamicMBean interface
package javax.management;
  
public interface DynamicMBean {
  
  public Object getAttribute(String attribute) 
    throws AttributeNotFoundException, MBeanException, ReflectionException; 
  
  public void setAttribute(Attribute attribute) 
    throws AttributeNotFoundException, InvalidAttributeValueException,
           MBeanException, ReflectionException; 
  
  public AttributeList getAttributes(String[] attributes);
  
  public AttributeList setAttributes(AttributeList attributes);
  
  public Object invoke(String actionName, Object params[], String signature[])
    throws MBeanException, ReflectionException;    
  
  public MBeanInfo getMBeanInfo(  );
    
}
Essentially, the DynamicMBean interface provides a way for a management interface to do four things:
  • Dynamically discover the management interface exposed by the MBean (getMBeanInfo( )).
  • Retrieve the value of one or more attributes on the management interface (getAttribute( ) and getAttributes( ), respectively).
  • Set the value of one or more attributes on the management interface (setAttribute( ) and setAttributes( ), respectively).
  • Invoke an operation on the management interface (invoke( )).
Instances of the appropriate metadata classes are created by the MBean (usually in the constructor) and added to the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Dynamic MBean Inheritance Patterns
In this section, we will look at how the introspection process performed by the MBean server causes the inheritance patterns available to dynamic MBeans to differ from those available to standard MBeans.
Suppose that our application has the inheritance graph shown in Figure 3-2.
Figure 3-2: UML diagram showing a possible inheritance scenario for the sample application
In this scenario, each class (with the exception of Supplier and Consumer) explicitly implements the DynamicMBean interface. Based on the information in the figure, what would you expect the management interface of, say, Controller to be? If you said that it would be the union of the management interface of Basic and Controller, you would be mistaken. You may recall from the previous chapter that using inheritance pattern #4 would allow a child class to augment its management interface with that of its parent class. However, no such inheritance patterns are available for dynamic MBeans.
What do you suppose the management interface of Supplier is? In fact, it may be a better question to ask whether Supplier is an MBean at all. The answer is yes, Supplier is indeed an MBean (in fact, a dynamic MBean), because it may inherit the dynamic MBean interface from its parent class. How is this possible? When Supplier is registered with the MBean server, the MBean server performs its introspection and looks to see whether Supplier exposes a management interface. Because it does not, the MBean server next looks to its parent class, Worker. The MBean server notices that Worker does implement an MBean interface, declares Supplier to be an MBean, and delegates all MBean functionality to Worker (where the management interface is actually implemented).
Let's look at another example. Suppose that we have the inheritance scenario shown in Figure 3-3, again using the classes from the application.
Figure 3-3: Another possible inheritance scenario, shown in UML notation
Notice that Worker does not implement
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: Model MBeans
Model MBeans are the most powerful type of MBean. Instrumenting your application resources as model MBeans provides you with the most features and flexibility of any of the MBean types that are fully specified by the current JMX specification. Furthermore, this power comes without a commensurate level of complexity! In this chapter, we will examine the features provided by model MBeans and why you might choose this instrumentation strategy over the others we have discussed so far. Then we will look at how model MBeans work, including a detailed look at the Descriptor class and the metadata classes that are used by resources instrumented as model MBeans. We will also take a look at RequiredModelMBean, a model MBean class that is required to be present in every JMX implementation. Finally, we will develop a working example that uses the same design as the examples of the previous chapters, so you can compare and contrast model MBeans with standard and dynamic MBeans.
An entire book could be devoted to model MBeans, as they are by far the most complex type of MBean. The objective of this chapter is simply to familiarize you sufficiently with the major issues involved in instrumenting your resources as model MBeans that you can do so.
This chapter assumes that you have read the previous chapter, or are familiar with dynamic MBeans. You should be familiar with the DynamicMBean interface and how to use metadata classes to describe an MBean's management interface.
In this chapter, we will refer to MBean features, or simply features. A feature is a constituent of the management interface: an attribute, operation, constructor, parameter, or notification.
Model MBeans are dynamic MBeans and so use metadata to describe the features of the MBean. However, there is one significant difference: model MBeans offer the instrumentation developer a metadata class called Descriptor, which is a collection of name/value pairs in which the name is a String and the value is an Object. This allows for a much richer set of metadata to be exchanged with the agent level, other MBeans, and management applications. Model MBeans offer some significant benefits over other JMX instrumentation strategies, as described in this section.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Why Use Model MBeans?
Model MBeans are dynamic MBeans and so use metadata to describe the features of the MBean. However, there is one significant difference: model MBeans offer the instrumentation developer a metadata class called Descriptor, which is a collection of name/value pairs in which the name is a String and the value is an Object. This allows for a much richer set of metadata to be exchanged with the agent level, other MBeans, and management applications. Model MBeans offer some significant benefits over other JMX instrumentation strategies, as described in this section.
First, instrumenting your application resources as model MBeans allows you to more quickly perform the instrumentation. You can instrument a resource as a model MBean in just a few lines of code. When a resource's attributes are accessed or changed, or when an operation is invoked, the mechanism used by model MBeans is a callback. In other words, when the metadata for an MBean feature (such as an attribute or operation) is created, a reference to the instance of the resource is stored with the metadata, along with the name of the attribute getter/setter or operation. When a management application manages the MBean, it simply uses this information to call back into the resource.
A second benefit of model MBeans is the feature set that comes along with them. Model MBeans have a rich set of features, including support for:
  • Automatic attribute-change notifications
  • Persistence of the MBean's state at predefined intervals
  • Logging of certain significant events in state changes of the MBean
  • Accessing MBean state from a cache to improve performance for attributes whose values have a relatively long freshness
A third benefit of model MBeans is that the resource you are instrumenting does not require any code changes. This is a significant advantage when instrumenting existing application or third-party resources that provide a well-defined API. Unlike standard or dynamic MBeans, the resource itself does not have to implement anything to be a perfectly compliant JMX resource. All that is required is that somewhere in the code execution stream there must be code that creates the necessary
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
How Do Model MBeans Work?
Like all other MBean types, model MBeans must be created and registered with the MBean server, and, as with dynamic MBeans, the management interface of your resource is exposed through metadata classes. The similarities end there.
Every compliant JMX implementation must ship a class called RequiredModelMBean. This class is instantiated and registered with the MBean server, and it implements several interfaces (including DynamicMBean) that make the life of the instrumentation developer easier. But what is it that makes a model MBean tick? What makes a model MBean work and live up to its reputation (which we discussed in the previous section)? The rest of this section is devoted to answering those questions.
The key difference between instrumenting a resource as a model MBean versus as a dynamic MBean is the Descriptor interface. A class implementing this interface describes certain properties of the MBean to the agent level of the JMX architecture, other MBeans, and management applications. Each descriptor contains one or more fields, which have corresponding Object values. Think of a field as a property of the MBean that gives some other party in the system (usually a management application) a little "nugget" of information about the MBean or one of its features (such as an attribute or operation). Of course, in order to exploit the full power of a descriptor, the management application must know about model MBeans. If the management application knows nothing of model MBeans, it simply treats the MBean as it would any other. Unfortunately, it is then unable to exploit the additional metadata contained in the descriptor. Example 4-1 shows the Descriptor interface.
Example 4-1. The Descriptor interface
public interface Descriptor extends java.io.Serializable {
  
  public Object getFieldValue(String fieldName)
    throws RuntimeOperationsException;
  
  public void setField(String fieldName, Object fieldValue)
    throws RuntimeOperationsException;
  
  public String[] getFields(  );
  
  public String[] getFieldNames(  );
  
  public Object[] getFieldValues(String[] fieldNames); 
  
  public void removeField(String fieldName);
  
  public void setFields(String[] fieldNames, Object[] fieldValues)
     throws RuntimeOperationsException;
  
  public Object clone(  ) throws RuntimeOperationsException;
  
  public boolean isValid(  ) throws RuntimeOperationsException;
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Instrumenting Resources as Model MBeans
In this chapter, we have seen how to create Descriptor objects and the necessary metadata classes for a model MBean, and we have looked at RequiredModelMBean and the interfaces that it must implement. In this section, we will see how to tie all of this information together to instrument resources as model MBeans.
The steps you must go through to instrument each of your resources as model MBeans are:
  1. Create an instance of the resource to be managed.
  2. Create an instance of RequiredModelMBean.
  3. Create the necessary metadata classes and optional descriptors for the features of the management interface.
  4. Create the metadata for the resource (i.e., the ModelMBeanInfo object).
  5. Set the metadata of RequiredModelMBean to the metadata for the resource (from Step 3) and the resource to be managed through the ModelMBean interface.
As in the previous chapters, we will use the sample application for all of our examples. This will allow you to compare and contrast the other MBean types with model MBeans.
In the examples presented here we will look at the application class Controller, which acts as the JMX agent. For the example code in this chapter, the Controller class is responsible for creating the resources to be managed, instrumenting them as model MBeans, and registering them with the MBean server.
The first two steps are to create an instance of the managed resource (in this example, the Queue) and to create the RequiredModelMBean instance:
// . . .
Queue queue = new Queue(  );
RequiredModelMBean queueModelMBean = new RequiredModelMBean(  );
// . . .
Next, we must create the necessary model MBean metadata classes (only some of the attributes and operations are shown, as the examples can be quite lengthy). First we'll create the attributes:
// There are 10 attributes . . .
ModelMBeanAttributeInfo[] attributeInfo = new ModelMBeanAttributeInfo[10];
attributeInfo[0] = new ModelMBeanAttributeInfo(
  "QueueSize",
  "java.lang.Integer",
  "The maximum size of the queue.",
  true,
  true,
  false,
);
DescriptorSupport desc = attributeInfo[0].getDescriptor(  );
desc.setField("getMethod", "getQueueSize");
desc.setField("setMethod", "setQueueSize");
desc = new DescriptorSupport(
  new String[] {
    "name=NumberOfItemsProcessed",
    "descriptorType=attribute",
    "getMethod=getNumberOfItemsProcessed",
  }
);
attributeInfo[1] = new ModelMBeanAttributeInfo(
  "NumberOfItemsProcessed",
  "java.lang.Long",
  "The number of work units processed.",
  true,
  false,
  false,
);
// . . . other attributes . . .
desc = new DescriptorSupport(
  new String[] {
    "name=NumberOfConsumers",
    "descriptorType=attribute",
    "getMethod=getNumberOfConsumers",
  }
);
attributeInfo[9] = new ModelMBeanAttributeInfo(
  "NumberOfConsumers",
  "java.lang.Integer",
  "No. of consumer threads currently feeding the queue.",
  true,
  false,
  false,
);
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 5: Open MBeans
So far, we have looked at three ways to instrument resources to be manageable. Now we will look at a way to instrument resources so that they are the most open to management applications. In this chapter, we will discuss how to instrument resources whose attributes are more complex than the fundamental types and whose operations take complex parameters. The key to this more open means of instrumentation lies in the set of data types defined by the JMX specification called open MBeans. By using open MBeans, we can instrument application resources of any type and make them available to any agent or management application that does not have access to the bytecode for either the resource, attribute, or operation parameter. The agent or management application can even be a non-Java program!
We will first look at the various open MBean types. Those types include the fundamental types, such as int, long, and char, as well as new types, such as structural and tabular data. All of the open MBean types are classes that derive from a single open MBean type, OpenType.
Next, we will examine the various open MBean metadata classes that allow us to instrument our resources as open MBeans. At the time of this writing, open MBeans are newly finalized (they were not part of the JMX 1.0 specification), so some of the information in this chapter may be subject to change.
The open MBean types are at the heart of what makes open MBeans "open." The JMX RI defines a base class, OpenType, from which all open MBean types are derived. This ensures consistency among all of the subsequent types. In this section, we will look at the basic types, most of which are fundamental and correspond to their JDK wrapper types. We will first look at OpenType, then we will take a look at SimpleType, an RI class that provides static methods to obtain references to the various fundamental open types. Then we will look briefly at the basic types that allow us to describe complex data.
This section also describes how to represent complex data using the JMX classes CompositeData and TabularData and discusses their type definition classes (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Open MBean Types
The open MBean types are at the heart of what makes open MBeans "open." The JMX RI defines a base class, OpenType, from which all open MBean types are derived. This ensures consistency among all of the subsequent types. In this section, we will look at the basic types, most of which are fundamental and correspond to their JDK wrapper types. We will first look at OpenType, then we will take a look at SimpleType, an RI class that provides static methods to obtain references to the various fundamental open types. Then we will look briefly at the basic types that allow us to describe complex data.
This section also describes how to represent complex data using the JMX classes CompositeData and TabularData and discusses their type definition classes (CompositeType and TabularType, respectively). Finally, we will look at the JMX support classes that implement these complex type enablers.
All of the open MBean types are one of the basic types. There are two categories of basic types: those types that are fundamental and those that may be used to describe arbitrarily complex types. In this section, we will look at all of the open MBean basic types. We will start with the base class for all open MBean types, OpenType. Then we will look at SimpleType, a subclass of OpenType, which is used to obtain instances of the fundamental open MBean types. Finally, we will take a quick look at the open MBean types that are used to represent complex data, saving the bulk of the discussion for the next section, Section 5.1.2.

Section 5.1.1.1: OpenType

This class is the base class for all open MBean types. OpenType is abstract, so it cannot be instantiated. However, the essential characteristics for all open MBean types are defined in the protected constructor for OpenType, to which subclasses must delegate:
Class name
The fully qualified name of the Java class that the OpenType instance represents (e.g., java.lang.Integer is the class name for integer data types).
Type name
The name that has been assigned to the data type represented by this
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Open MBean Metadata Classes
Now that we've seen how open MBean types work and how they are defined, let's take a look at creating the metadata classes that describe resources that are instrumented as open MBeans. We will start by seeing how to describe parameters, attributes, constructors, operations, notifications, and finally OpenMBeanInfo. Each of these is described by an interface and implemented by a support class. This is similar to model MBeans—the focus of the previous chapter—and the open MBean types we looked at earlier in this chapter.
As with the open MBean type classes, when we talk about an object that implements the interface (e.g., an OpenMBeanParameterInfo object) we have presupposed the creation of the object using a support class. This is because we generally work with a particular open MBean metadata type through its interface and use the corresponding support class only to create instances of those objects.
A common theme for all of the OpenMBean*Info objects (where * is Parameter, Attribute, etc.) is that the support classes provided extend their javax.management.MBean*Info counterparts—for example, OpenMBeanParameterInfoSupport extends MBeanParameterInfo. The relationships between the open MBean classes are shown in Figure 5-1.
Figure 5-1: Relationships between the open MBean metadata classes
As we saw with dynamic MBeans in Figure 3-1, a single instance of OpenMBeanInfoSupport completely describes an MBean. The relationship between OpenMBeanInfoSupport and the other open MBean interfaces is shown in Figure 5-2.
Figure 5-2: Relationships between OpenMBeanInfoSupport and the other open MBean metadata interfaces
In the rest of this section we will look at each of the open MBean metadata interfaces and classes, starting with OpenMBeanParameterInfo.
This interface deals with open MBean parameter information. There are several read-only attributes of an open MBean parameter:
Description
A human-readable description of the parameter described by this
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 6: The MBean Server
So far, we have talked only about the instrumentation level of the JMX architecture. In this chapter, we will take a close look at the core of the JMX architecture, the agent level. This chapter is for those developers who want a deeper understanding of the JMX agent level, are responsible for developing protocol adaptors and connectors, or need to interact with a local MBeanServer instance.
First, we will take a quick look at the MBean server's role in the JMX agent level, how it is implemented in the RI, how to get a reference to it, and what you can do with that reference once you have it. Next, we will take a closer look at the MBeanServerFactory class and its various methods for obtaining references to the MBean server. Then we will look at the MBeanServer interface, which is how MBeans, JMX agents, and management applications interact with the MBean server. In this section, we will also explore how to register and unregister MBeans, how to use the MBean server to interact with an MBean through its ObjectName, how to register interest in notifications, and how to query the MBean server to return a subset of registered MBeans. This section will be followed by a discussion of the MBeanRegistration interface, which gives the instrumentation developer a means of control over an MBean's ObjectName, as well as exit points for additional processing before and after the MBean is registered and deregistered. The chapter will conclude with a look at MBeanServerDelegate, a class required by all JMX-compliant implementations to provide metadata about that particular JMX implementation.
The MBean server is at the heart of the agent level of the JMX architecture. The primary function of the MBean server is to act as a registry for MBeans. It is through the MBean server that MBeans, other parts of the JMX agent, and management applications gain access to the MBeans that are registered with the MBean server. Every MBean must be registered with the MBean server in order to be managed. This is achieved by first obtaining a reference to the MBean server (we'll see how to do that later in this chapter) and then invoking the appropriate method of the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What Is the MBean Server?
The MBean server is at the heart of the agent level of the JMX architecture. The primary function of the MBean server is to act as a registry for MBeans. It is through the MBean server that MBeans, other parts of the JMX agent, and management applications gain access to the MBeans that are registered with the MBean server. Every MBean must be registered with the MBean server in order to be managed. This is achieved by first obtaining a reference to the MBean server (we'll see how to do that later in this chapter) and then invoking the appropriate method of the MBeanServer interface. We will discuss the MBeanServer interface in more detail later in this chapter.
A secondary function of the MBean server is to act as an intermediary to allow other JMX agents, management applications, and MBeans to monitor and manage MBeans without having a reference to the MBean object. As long as the object name of the MBean is known and the MBean is registered, an MBean can be indirectly manipulated through the MBean server in which the MBean is registered.
In the RI provided with the final release of the JMX 1.0 specification, the MBeanServer interface is fully implemented in a class called MBeanServerImpl , located in the com.sun.management.jmx package. If you are using the RI and are curious about the internals of the MBean server implementation, I encourage you to look at the source code for this class.
As mentioned earlier, before an MBean can be registered with the MBean server, a reference to the MBean server must be obtained. This is achieved through MBeanServerFactory , a class located in the javax.management package that must be shipped with every compliant JMX implementation. This class contains static methods that allow you to create an instance of an MBean server and find an instance of an MBean server that has already been created. Each of the methods of the MBeanServerFactory class will be discussed later in this chapter.
The MBean server implementation class (MBeanServerImpl, in the JMX 1.0 RI) should never be instantiated directly! You should always use the static methods of
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Obtaining a Reference to the MBean Server
The under-the-hood implementation of the MBean server in the RI is com.sun.management.jmx.MBeanServerImpl, but this class should never be instantiated directly. Instead, the RI provides a factory class called MBeanServerFactory that contains various static methods that allow you to obtain a reference to the MBean server. In this section, we will describe each of those static methods and give examples of how to use them. Example 6-1 is an abbreviated version of the MBeanServerFactory class.
Example 6-1. The static methods of MBeanServerFactory
package javax.management;
// . . .
public class MBeanServerFactory { 
// . . .
  public static MBeanServer createMBeanServer (  ) {
    // . . .
  }
  
  public static MBeanServer createMBeanServer (String domain)  {
    // . . .
  }
  
  public static MBeanServer newMBeanServer (  ) {
    // . . .
  }
  
  public static MBeanServer newMBeanServer (String domain)  {
    // . . .
  }
 
  public synchronized static ArrayList findMBeanServer (String AgentId) {
    // . . .
  }
  
  public static void releaseMBeanServer (MBeanServer mbeanServer) {
    // . . .
  }
  
// . . .
}
There are six static methods on MBeanServerFactory, as shown in Example 6-1. These methods allow you to create an instance, find one or more instances, and release a reference to an instance of an MBean server.
If no MBean server instance exists (we'll discuss how to find that out later), there are four static methods that allow you to create one. The first two, overloads of createMBeanServer( ), allow you to create an instance of the MBean server with the default domain name and a specific domain name, respectively. When you create an instance of the MBean server, MBeanServerFactory maintains a reference to the MBean server that was just created, ensuring that it will not be garbage-collected. The second two methods, overloads of newMBeanServer( ), do the same thing, but MBeanServerFactory does not maintain a reference to the newly created MBean server—it is up to the caller to maintain the reference.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The MBeanServer Interface
In this section, we will take a close look at the MBeanServer interface, which is used to communicate with the MBeanServer implementation. First we will present the interface in its entirety, then we will proceed to dissect the interface method by method, providing examples along the way. We will also take another look at the ObjectName class, which is critical in manipulating MBeans indirectly through the MBeanServer interface (the preferred means of doing so). We have already covered what you can do through a reference to the MBeanServer interface. Let's now look more closely at this important interface. Example 6-2 shows the MBeanServer interface.
Example 6-2. The MBeanServer interface
package javax.management;
  
public interface MBeanServer { 
  
  public Object instantiate(String className) 
    throws ReflectionException, MBeanException;
  
  public Object instantiate(String className, ObjectName loaderName) 
    throws ReflectionException, MBeanException, InstanceNotFoundException;
  
  public Object instantiate(String className, Object params[], String signature[])
    throws ReflectionException, MBeanException; 
  
  public Object instantiate(String className, ObjectName loaderName,
                            Object params[], String signature[]) 
    throws ReflectionException, MBeanException, InstanceNotFoundException;
  
  public ObjectInstance registerMBean(Object object, ObjectName name)
    throws InstanceAlreadyExistsException, MBeanRegistrationException,
           NotCompliantMBeanException;
  
  public ObjectInstance createMBean(String className, ObjectName name)
    throws ReflectionException, InstanceAlreadyExistsException,
           MBeanRegistrationException, MBeanException, NotCompliantMBeanException;
  
  public ObjectInstance createMBean(String className, ObjectName name,
                                    ObjectName loaderName) 
    throws ReflectionException, InstanceAlreadyExistsException,
           MBeanRegistrationException, MBeanException,
           NotCompliantMBeanException, InstanceNotFoundException;
  
  public ObjectInstance createMBean(String className, ObjectName name,
                                    Object params[], String signature[]) 
    throws ReflectionException, InstanceAlreadyExistsException,
           MBeanRegistrationException, MBeanException, NotCompliantMBeanException;
  
  public ObjectInstance createMBean(String className, ObjectName name,
                                    ObjectName loaderName, Object params[],
                                    String signature[]) 
    throws ReflectionException, InstanceAlreadyExistsException,
           MBeanRegistrationException, MBeanException,
           NotCompliantMBeanException, InstanceNotFoundException;
  
  public void unregisterMBean(ObjectName name)
    throws InstanceNotFoundException, MBeanRegistrationException; 
  
  public Object getAttribute(ObjectName name, String attribute)
    throws MBeanException, AttributeNotFoundException,
           InstanceNotFoundException, ReflectionException;
  
  public AttributeList getAttributes(ObjectName name, String[] attributes)
    throws InstanceNotFoundException, ReflectionException;
  
  public void setAttribute(ObjectName name, Attribute attribute)
    throws InstanceNotFoundException, AttributeNotFoundException,
           InvalidAttributeValueException, MBeanException, ReflectionException;
  
  public AttributeList setAttributes(ObjectName name, AttributeList attributes)
    throws InstanceNotFoundException, ReflectionException;
  
  public Object invoke(ObjectName name, String operationName,
                       Object params[], String signature[])
    throws InstanceNotFoundException, MBeanException, ReflectionException;
  
  public MBeanInfo getMBeanInfo(ObjectName name)
    throws InstanceNotFoundException, IntrospectionException, ReflectionException;
  
  public void addNotificationListener(ObjectName name, NotificationListener listener,
                                      NotificationFilter filter, Object handback)
    throws InstanceNotFoundException;
  
  public void addNotificationListener(ObjectName name, ObjectName listener, 
                                      NotificationFilter filter, Object handback)
    throws InstanceNotFoundException;
  
  public void removeNotificationListener(ObjectName name, NotificationListener listener)
    throws InstanceNotFoundException, ListenerNotFoundException;
  
  public void removeNotificationListener(ObjectName name, ObjectName listener) 
    throws InstanceNotFoundException, ListenerNotFoundException;
  
  public Set queryMBeans(ObjectName name, QueryExp query);
  
  public Set queryNames(ObjectName name, QueryExp query);
  
  public ObjectInstance getObjectInstance(ObjectName name)
    throws InstanceNotFoundException;
  
  public boolean isRegistered(ObjectName name);
  
  public Integer getMBeanCount(  );
  
  public boolean isInstanceOf(ObjectName name, String className)
    throws InstanceNotFoundException;
  
  public String getDefaultDomain(  );
  
  public ObjectInputStream deserialize(ObjectName name, byte[] data)
    throws InstanceNotFoundException, OperationsException;
  
  public ObjectInputStream deserialize(String className, byte[] data)
    throws OperationsException, ReflectionException;
  
  public ObjectInputStream deserialize(String className, ObjectName loaderName,
                                       byte[] data)
    throws InstanceNotFoundException, OperationsException, ReflectionException;
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Controlling MBean Registration
There are times when it is necessary to perform certain activities before and after an MBean is registered and deregistered. Implementing the MBeanRegistration interface provides an MBean with four opportunities (i.e., callbacks) to perform additional processing. The MBeanRegistration interface is defined as:
public interface MBeanRegistration {
  
  public ObjectName preRegister(MBeanServer server, ObjectName name)
    throws java.lang.Exception;
  
  public void postRegister(Boolean registrationDone);
  
  public void preDeregister(  )
    throws java.lang.Exception;
  
  public void postDeregister(  );
}
Another advantage of implementing this interface is that the MBean itself can generate its own object name in preRegister( ) , which is invoked prior to registering the MBean. The first opportunity an MBean has to perform any additional processing is in preRegister( ), which takes two parameters. The first parameter, server , is a reference to the MBean server in which the MBean will be registered, allowing an MBean to maintain a reference to its MBean server. The second parameter, name , is the object name of the MBean. The specification does not mention anything about the behavior of this method, other than that it is invoked prior to an MBean being registered. However, looking through the RI, it is clear that the designers of JMX intended that if the name parameter is null, the MBean will generate its own object name. Otherwise, name is returned unchanged.
Once the MBean has been registered, postRegister( ) is invoked with a boolean parameter, registrationDone , that indicates whether the registration was successful. If a problem occurred during registration, registrationDone will be false. Note that if an exception is thrown during the preRegister( ) callback, this method is never invoked.
If the agent that registered the MBean explicitly calls unregister( ) to deregister the MBean, the preDeregister( ) callback is invoked just prior to the MBean's deregistration. This gives the MBean the opportunity to perform any necessary cleanup, such as releasing the reference to its MBean server. This callback method can
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
MBeanServerDelegate
Content preview·Buy PDF of this chapter|