Cover | Table of Contents | Colophon
Queue class.
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.
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.
implements keyword.
http://java.sun.com/products/JavaManagement/.
Select either the source code or binary RI under
"JMX Deliverables" and follow the
instructions.
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.
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.
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.
DynamicMBean
, which must be implemented by all
dynamic MBeans. This interface is shown in Example 3-1.
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( );
}DynamicMBean interface provides a
way for a
management interface to do four things:
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.
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).
Worker does not implement
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.
DynamicMBean interface and how to use metadata
classes to describe an MBean's management interface.
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.
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.
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.
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.
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;
}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.
RequiredModelMBean.ModelMBeanInfo object).
RequiredModelMBean to the
metadata for the resource (from Step 3) and the resource to be
managed through the ModelMBean interface.
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.
Queue) and to create the
RequiredModelMBean instance:
// . . . Queue queue = new Queue( ); RequiredModelMBean queueModelMBean = new RequiredModelMBean( ); // . . .
// 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,
);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.
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.
CompositeData and
TabularData and discusses their type definition
classes (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.
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.
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.
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:
OpenType instance represents (e.g.,
java.lang.Integer is the class name for integer
data types).
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.
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.
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.
OpenMBeanInfoSupport completely
describes an MBean. The relationship between
OpenMBeanInfoSupport and the other open MBean
interfaces is shown in Figure 5-2.
OpenMBeanParameterInfo.
Description
MBeanServer instance.
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.
MBeanServer interface. We will discuss the
MBeanServer interface in more detail later in this
chapter.
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.
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.
MBeanServerImpl, in the JMX 1.0 RI) should never
be instantiated directly! You should always use the static methods of
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.
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) {
// . . .
}
// . . .
}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.
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.
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.
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;
}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( );
}null, the MBean will generate its own
object name. Otherwise, name is returned
unchanged.
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.