10 Essentials of the JMX API
This chapter introduces managed beans (MBeans) which are a core component of the Java Management Extensions (JMX) API.
An MBean is a managed Java object, similar to a JavaBean, that follows the design patterns set forth in the instrumentation level of the JMX Specification. An MBean can represent a device, an application, or any resource that is managed. MBeans expose a management interface, which is a set of readable and/or writable attributes and a set of invokable operations, along with a self-description. The management interface does not change throughout the life of an MBean instance. MBeans can also emit notifications when certain defined events occur.
The JMX Specification defines four types of MBean: standard MBeans, dynamic MBeans, open MBeans and model MBeans. The examples in this tutorial demonstrate the simplest type of MBean, namely standard MBeans.
Standard MBeans
You can define a standard MBean by writing a Java interface called SomethingMBean
and a Java class called Something
that implements that interface. Every method in the interface defines either an attribute or an operation in the MBean. By default every method defines an operation. Attributes and operations are simply methods which follow certain design patterns. A standard MBean is composed of the MBean interface which lists the methods for all exposed attributes and operations, and the class which implements this interface and provides the functionality of the instrumented resource.
The following sections describe an example standard MBean, and a simple JMX agent that manages the MBean. The code samples are provided in JMX Essentials. You can run the examples from the directory work_dir/jmx_examples/Essential/com/example/mbeans.
MBean Interface
An example of a basic MBean interface, named HelloMBean
, is shown
in the following code example.
CODE EXAMPLE 10-1 MBean Interface, HelloMBean
package com.example.mbeans;
public interface HelloMBean {
public void sayHello();
public int add(int x, int y);
public String getName();
public int getCacheSize();
public void setCacheSize(int size);
}
An MBean interface takes the name of the Java class that implements it, with the suffix MBean added. The interface is called HelloMBean
. The Hello
class that implements this interface is described in MBean Implementation.
According to the JMX Specification, an MBean interface consists of named and typed
attributes that are readable and possibly writable, and named and typed operations
that can be invoked by the applications that are managed by the MBean. The
HelloMBean
interface shown in CODE EXAMPLE 10-1 MBean
Interface, HelloMBean, declares two operations: the Java methods
add()
and sayHello()
.
Of the two attributes that are declared by HelloMbean
, Name
is a read-only string, and CacheSize
is an integer that can be both read and written. Getter and setter methods are declared, to allow the managed application to access and possibly change the attribute values. As defined by the JMX Specification, a getter is any public method whose name begins with get and which does not return void. A getter enables a manager to read the value of the attribute, whose type is that of the returned object. A setter is any public method whose name begins with set and which takes a single parameter. A setter enables a manager to write a new value in the attribute, whose type is the same as that of the parameter.
The implementation of these operations and attributes is shown in the following section.
MBean Implementation
The Hello
class shown in the following code example implements
HelloMBean
.
CODE EXAMPLE 10-2 MBean Implementation Class, Hello
package com.example.mbeans;
public class Hello implements HelloMBean {
public void sayHello() {
System.out.println("hello, world");
}
public int add(int x, int y) {
return x + y;
}
public String getName() {
return this.name;
}
public int getCacheSize() {
return this.cacheSize;
}
public synchronized void setCacheSize(int size) {
this.cacheSize = size;
System.out.println("Cache size now " + this.cacheSize);
}
private final String name = "Reginald";
private int cacheSize = DEFAULT_CACHE_SIZE;
private static final int DEFAULT_CACHE_SIZE = 200;
}
In Example 10-2, the Java class Hello
provides the definitions of
the operations and attributes declared by HelloMBean
. As you can
see, the example sayHello()
and add()
operations
are extremely simple, but real-life operations can be as simple or as sophisticated
as you like.
Methods to get the Name
attribute and to get and set the cacheSize
attribute are also defined. In this example, the Name
attribute value never changes, but in a real scenario it might change as the managed resource runs. For example, the attribute might represent statistics such as uptime or memory usage. Here, it is merely the name “Reginald”.
Calling the setCacheSize
method allows you to alter the cacheSize
attribute from its declared default value of 200. In reality, changing the cacheSize
attribute could require other operations to be performed, such as discarding entries or allocating new ones. This example merely prints a message to confirm that the cache size is changed, but you can define more sophisticated operations in the place of the call to println()
.
With the Hello
MBean and its interface defined, they can be used to manage the resource they represent, as shown in the following section.
Managing a Resource
As described in the Java Management Extensions Technology User’s Guide, after a resource is instrumented by MBeans, the management of that resource is performed by a JMX agent.
The core component of a JMX agent is the MBean server, a managed object
server in which MBeans are registered. See the API documentation for the
MBeanServer
interface for details of the MBean server implementation. A
JMX agent also includes a set of services to manage MBeans. The following code example
presents a basic JMX agent, named Main
.
CODE EXAMPLE 10-3 Creating a JMX Agent
package com.example.mbeans;
import java.lang.management.*;
import javax.management.*;
public class Main {
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example.mbeans:type=Hello");
Hello mbean = new Hello();
mbs.registerMBean(mbean, name);
System.out.println("Waiting forever...");
Thread.sleep(Long.MAX_VALUE);
}
}
In Example 10-3, the JMX agent Main
begins by obtaining any MBean
server that is running on the platform, by calling the
getPlatformMBeanServer()
method of the
java.lang.management.ManagementFactory
class. If no MBean server is
already running on the platform, then getPlatformMBeanServer()
creates
one automatically by calling the JMX method
MBeanServerFactory.createMBeanServer()
. The
MBeanServer
instance obtained by Main
is named
mbs
.
Next, Main
defines an object name for the MBean instance it will create. Every JMX MBean must have an object name. The object name is an instance of the JMX class ObjectName
, and must conform to the syntax defined by the JMX Specification, namely it must comprise a domain, and a list of key-properties. See the API documentation for the ObjectName
class for details of this syntax. In the object name defined by Main
, name
, the domain is com.example.mbeans
(the package in which the example MBeans are contained) and the key-property declares that this object is of the type Hello
.
An instance of a Hello
object is created, named mbean
. This Hello
object is an instance of the MBean Hello
that was defined in MBean Implementation.
The Hello
object named mbean
is registered as an MBean in the MBean server mbs
with the object name name
, by passing the object and the object name into a call to the JMX method MBeanServer.registerMBean()
.
With the Hello
MBean registered in the MBean server, Main
will simply wait for management operations to be performed on Hello
. In the scope of this example, these management operations are invoking sayHello()
, and add()
, and getting and setting the attribute values.
Running the Standard MBean Example
Having examined the example classes, you can run the example. The Java Platform, Standard Edition includes a management and monitoring console, named JConsole, that is used to interact with the MBean in this example. JConsole is located in JavaSE_HOME/bin/jconsole
, in which JavaSE_HOME
is the installation directory of the Java Platform, Standard Edition (Java SE platform).
To run the example:
-
Copy the source code contained in the JMX Essentials section and create corresponding files in the
work_dir/jmx_examples/Essential
directory. - Compile the example Java classes.
$ javac com/example/mbeans/*.java
- Start the
Main
application.$ java com.example.mbeans.Main
You will see a confirmation that
Main
is waiting for something to happen. - Start JConsole in a different terminal window on the same machine.
$ jconsole
You will see the JConsole tool open, presenting a list of running JMX agents that you can connect to.
- Select
com.example.mbeans.Main
from the list in the “New Connection” window, and click on Connect.You will see a summary of your platform’s current activity.
- Click on the MBeans tab.
This panel shows you all the MBeans currently registered in the MBean server.
- In the left-hand frame, expand the
com.example.mbeans
node in the MBean tree.You will see the example MBean
Hello
, that was created and registered byMain
. If you clickHello
, you will see its associated Attributes and Operations nodes in the MBean tree. - Click on the
Hello
MBean node in the MBean tree to display theHello
MBean’s metadata and its associated Descriptor. - Click the
Attributes
node of theHello
MBean in the MBean tree.This displays the MBean attributes that were defined by the
Hello
class. - Change the value of the
CacheSize
attribute to 150.In the terminal window in which you started
Main
, you will see confirmation of this change of attribute. - Click the
Operations
node of the Hello MBean in the MBean tree.Here you will see the two operations declared by the
Hello
MBean,sayHello()
andadd()
. - Invoke the
sayHello()
operation, by clicking on thesayHello
button.A JConsole dialogue box will inform you that the method was invoked successfully, and you will see the message “hello, world” in the terminal window in which
Main
is running. - Provide two integers for the
add()
operation to add , and click theadd
button.You will be informed of the answer in a JConsole dialogue box.
- Click Connection and then Exit, to exit JConsole.
Sending Notifications
MBeans can generate notifications, for example to signal a state change, a detected event, or a problem.
For an MBean to generate notifications, it must implement the interface NotificationBroadcaster
, or its subinterface NotificationEmitter
. All you need to do to send a notification is to construct an instance of the class javax.management.Notification
or a subclass (such as AttributeChangedNotification
), and pass it to NotificationBroadcasterSupport.sendNotification
.
Every notification has a source. The source is the object name of the MBean that emitted the notification.
Every notification has a sequence number. This number can be used to order notifications coming from the same source when order matters and there is a danger of the notifications being handled in the wrong order. It is all right for the sequence number to be zero, but it is better for it to increment for each notification from a given MBean.
There is an example of a standard MBean that emits notifications in the directory work_dir/jmx_examples/Notification/com/example/mbeans
. This example is essentially the same as the example in Standard MBeans, except that the Hello
MBean implements the NotificationBroadcaster
interface.
NotificationBroadcaster Interface
As previously stated, the only difference between this example and the one presented
in Standard MBeans is that the MBean implementation allows sending
notifications. Notifications are activated by implementing the
NotificationBroadcaster
interface, as shown in the following code
example.
CODE EXAMPLE 10-4 Implementing MBean Notifications
package com.example.mbeans;
import javax.management.*;
public class Hello
extends NotificationBroadcasterSupport implements HelloMBean {
public void sayHello() {
System.out.println("hello, world");
}
public int add(int x, int y) {
return x + y;
}
public String getName() {
return this.name;
}
public int getCacheSize() {
return this.cacheSize;
}
public synchronized void setCacheSize(int size) {
int oldSize = this.cacheSize;
this.cacheSize = size;
System.out.println("Cache size now " + this.cacheSize);
Notification n =
new AttributeChangeNotification(this,
sequenceNumber++,
System.currentTimeMillis(),
"CacheSize changed",
"CacheSize",
"int",
oldSize,
this.cacheSize);
sendNotification(n);
}
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
String[] types = new String[] {
AttributeChangeNotification.ATTRIBUTE_CHANGE
};
String name = AttributeChangeNotification.class.getName();
String description = "An attribute of this MBean has changed";
MBeanNotificationInfo info =
new MBeanNotificationInfo(types, name, description);
return new MBeanNotificationInfo[] {info};
}
private final String name = "Reginald";
private int cacheSize = DEFAULT_CACHE_SIZE;
private static final int DEFAULT_CACHE_SIZE = 200;
private long sequenceNumber = 1;
}
As you can see in CODE EXAMPLE 10-4 Implementing MBean Notifications, this
Hello
MBean implementation extends the
NotificationBroadcasterSupport
class, that itself implements
the NotificationEmitter
interface.
The operations and attributes are set in the same way as before, with the only exception that the cacheSize
attribute’s setter method now defines a new value oldSize
, which records the cacheSize
attribute’s value prior to the set operation.
The notification is constructed from an instance, n
, of the JMX class AttributeChangeNotification
, which extends javax.management.Notification
. The notification is constructed within the definition of the setCacheSize()
method, from the following information, that is passed to AttributeChangeNotification
as parameters:
- The object name of the source of the notification, namely the
Hello
MBean, represented simply bythis
- A sequence number, which in this example is a long named
sequenceNumber
, that is set at 1 and that increases incrementally - A timestamp
- The content of the notification message
- The name of the attribute that has changed, in this case
cacheSize
- The type of attribute that has changed
- The old attribute value, in this case
oldSize
- The new attribute value, in this case
this.cacheSize
The notification n is then passed to the NotificationBroadcasterSupport.sendNotification()
method.
Finally, the MBeanNotification
is defined to describe the characteristics of the different notification instances emitted by the MBean for a given Java class of notification, which in this case is AttributeChangeNotification
notifications.
The MBean interface, HelloMBean
, and the JMX agent Main
are identical to those used in the previous example.
Running the MBean Notification Example
Having examined the example classes, you can now run the example. This example uses JConsole to interact with the Hello
MBean.To run the example:
-
Copy the source code examples contained in the JMX MBean Notifications section to
work_dir/jmx_examples/Notification
. -
Compile the example Java classes.
$ javac com/example/mbeans/*.java
-
Start the
Main
application.$ java com.example.mbeans.Main
You will see confirmation that
Main
is waiting for something to happen. -
Start JConsole in a different terminal window on the same machine.
$ jconsole
You will see the JConsole tool open, presenting a list of running JMX agents that you can connect to.
-
Select
com.example.mbeans.Main
from the list in the New Connection window, and click on Connect.You will see a summary of your platform’s current activity.
-
Click on the MBeans tab.
This panel shows you all the MBeans currently registered in the MBean server.
-
In the left-hand frame, expand the
com.example.mbeans
node in the MBean tree.You will see the example MBean
Hello
, that was created and registered byMain
. If you click onHello
, you will see its associatedAttributes
,Operations
andNotifications
nodes in the MBean tree. -
Click on the
Hello
MBean node in the MBean tree.This displays the MBean’s metadata and its associated Descriptor.
-
Click on the
Notifications
node of the Hello MBean in the MBean tree.You will see that the panel is blank.
-
Click on the “Subscribe” button.
The current number of notifications received (0), will be displayed in the Notifications node label.
-
Click on the
Attributes
node of theHello
MBean in the MBean tree, and change the value of theCacheSize
attribute to 150.In the terminal window in which you started
Main
, you will see confirmation of this change of attribute. You will also see that the number of notifications received displayed in the Notifications node has changed to 1. -
Click on the
Notifications
node of theHello
MBean in the MBean tree again.You will see the details of the notification that was sent.
- Click on Connection and then Exit, to exit JConsole.
Introducing MXBeans
An MXBean is a type of MBean that provides a simple way to code an MBean that only references a pre-defined set of types. In this way, you can be sure that your MBean will be usable by any client, including remote clients, without any requirement that the client have access to model-specific classes representing the types of your MBeans. MXBeans provide a convenient way to bundle related values together without requiring clients to be specially configured to handle the bundles.
In the same way as for standard MBeans, an MXBean is defined by writing a Java interface called SomethingMXBean
and a Java class that implements that interface. However, unlike standard MBeans, MXBeans do not require the Java class to be called Something
. Every method in the interface defines either an attribute or an operation in the MXBean. The annotation @MXBean
can be also used to annotate the Java interface instead of requiring the interface’s name to be followed by the MXBean suffix.
MXBeans provide a convenient way to bundle related values together in an MBean
without requiring clients to be specially configured to handle the bundles when
interacting with that MBean. MXBeans exist in the Java 2 Platform, Standard Edition
(J2SE) 5.0, in the package java.lang.management
. With the Java SE 6
platform, users can now define their own MXBeans, in addition to the standard set
defined in java.lang.management
.
The key idea behind MXBeans is that types such as java.lang.management.MemoryUsage
that are referenced in the MXBean interface, java.lang.management.MemoryMXBean
in this case, are mapped into a standard set of types, the so-called Open Types that are defined in the package javax.management.openmbean
. The exact mapping rules appear in the MXBean specification, but to oversimplify we could say that simple types like int
or String
are unchanged, while complex types like MemoryUsage
get mapped to the standard type CompositeDataSupport
.
The operation of MXBeans is demonstrated by example programs in MXBeans. The MXBean example contains the following files:
QueueSamplerMXBean
interface.QueueSampler
class that implements the MXBean interface.QueueSample
Java type returned by thegetQueueSample()
method in the MXBean interface.Main
, the program that sets up and runs the example.
The MXBean example performs the following actions.
- Defines a simple MXBean that manages a resource of
type Queue<String>
. - Declares a getter,
getQueueSample
, in the MXBean that takes a snapshot of the queue when invoked and returns a Java classQueueSample
that bundles the following values together:- The time the snapshot was taken.
- The queue size.
- The head of the queue at that given time.
- Registers the MXBean in an MBean server.
QueueSamplerMXBean Interface
The following code example shows the source code for the sample
QueueSamplerMXBean
interface.
CODE EXAMPLE 10-5 QueueSamplerMXBean interface
package com.example.mxbeans;
public interface QueueSamplerMXBean {
public QueueSample getQueueSample();
public void clearQueue();
}
As you can see, you declare an MXBean interface in exactly the same way as you declare a standard MBean. The QueueSamplerMXBean
interface declares two operations, getQueueSample
and clearQueue
.
QueueSampler Class
The QueueSampler
class implements the
QueueSamplerMXBean
interface shown in the following code
example.
CODE EXAMPLE 10-6 QueueSampler Class
package com.example.mxbeans;
import java.util.Date;
import java.util.Queue;
public class QueueSampler implements QueueSamplerMXBean {
private Queue<String> queue;
public QueueSampler(Queue<String> queue) {
this.queue = queue;
}
public QueueSample getQueueSample() {
synchronized (queue) {
return new QueueSample(new Date(), queue.size(), queue.peek());
}
}
public void clearQueue() {
synchronized (queue) {
queue.clear();
}
}
}
The MXBean operations getQueueSample()
and clearQueue()
declared by the MXBean interface are defined in QueueSampler
. The getQueueSample()
operation simply returns an instance of the QueueSample
Java type, created with the values returned by the java.util
.Queue
methods peek()
and size()
and an instance of java.util.Date
.
QueueSample Class
The QueueSample
instance returned by QueueSampler
is defined in the QueueSample
class shown in the following code
example.
CODE EXAMPLE 10-7 QueueSample Class
package com.example.mxbeans;
import java.beans.ConstructorProperties;
import java.util.Date;
public class QueueSample {
private final Date date;
private final int size;
private final String head;
@ConstructorProperties({"date", "size", "head"})
public QueueSample(Date date, int size, String head) {
this.date = date;
this.size = size;
this.head = head;
}
public Date getDate() {
return date;
}
public int getSize() {
return size;
}
public String getHead() {
return head;
}
}
In QueueSample
class, the MXBean framework calls all the getters in QueueSample
to convert the given instance into a CompositeData
and uses the @ConstructorProperties
annotation to reconstruct a QueueSample
instance from a CompositeData
.
Creating and Registering the MXBean in the MBean Server
Having defined an MXBean interface and the class that implements it, as well as the
Java type that is returned, the MXBean must now be created and registered in an MBean
server. These actions are performed by the following code example class
Main
.
CODE EXAMPLE 10-8 MXBean example Main class
package com.example.mxbeans;
import java.lang.management.ManagementFactory;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import javax.management.MBeanServer;
import javax.management.ObjectName;
public class Main {
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name =
new ObjectName("com.example.mxbeans:type=QueueSampler");
Queue<String> queue = new ArrayBlockingQueue<String>(10);
queue.add("Request-1");
queue.add("Request-2");
queue.add("Request-3");
QueueSampler mxbean = new QueueSampler(queue);
mbs.registerMBean(mxbean, name);
System.out.println("Waiting...");
Thread.sleep(Long.MAX_VALUE);
}
}
The Main
class gets the platform MBean server, creates an object name for the MXBean QueueSampler
, creates a Queue
instance for the QueueSampler
MXBean to process, and feeds this Queue instance to a newly created QueueSampler
MXBean. The MXBean is then registered in the MBean server in exactly the same way as a standard MBean.
Running the MXBean Example
To run the MXBean example:
-
Copy the source code contained in the MXBeans section to
work_dir/jmx_examples/MXBean
. -
Compile the example Java classes.
$ javac com/example/mxbeans/*.java
-
Start the
Main
application.$ java com.example.mxbeans.Main
You will see confirmation that
Main
is waiting for something to happen. -
Start JConsole in a different terminal window on the same machine.
$ jconsole
You will see the JConsole tool open, presenting a list of running JMX agents that you can connect to.
-
Select
com.example.mxbeans.Main
from the list in the New Connection window, and click on Connect.You will see a summary of your platform’s current activity.
-
Click on the MBeans tab.
This panel shows you all the MBeans currently registered in the MBean server.
-
In the left-hand frame, expand the
com.example.mxbeans
node in the MBean tree.You will see the example MBean
QueueSampler
, that was created and registered by Main. If you click onQueueSampler
, then you will see its associated Attributes and Operations nodes in the MBean tree. -
Select the
Attributes
node.You will see the
QueueSample
attribute appear in the right-hand pane, with its value ofjavax.management.openmbean.CompositeDataSupport
. -
Double-click on the
CompositeDataSupport
value.You can see the
QueueSample
valuesdate
,head
andsize
because the MXBean framework has converted theQueueSample
instance intoCompositeData
. If you had definedQueueSampler
as a Standard MBean rather than as an MXBean, JConsole would not have found theQueueSample
class because it would not be in its class path. IfQueueSampler
had been a standard MBean, you would have received aClassNotFoundException
when retrieving theQueueSample
attribute value. This demonstrates the usefulness of using MXBeans when connecting to JMX agents through generic JMX clients, like JConsole. -
Select the Operations node.
You will see a button to invoke the
clearQueue
operation. -
Click on the clearQueue button.
You will be informed that the method was invoked successfully.
-
Select the Attributes node again and double click on the
CompositeDataSupport
value.The queue has been reset now.
-
Click on Connection and then Exit, to exit JConsole.
In this example JConsole has been used as the JMX client but if you were to access your MXBean programmatically in a JMX client you write yourself, then you could do so in one of two ways:
-
Generically, using the following code:
MBeanServer mbs = ...whatever...; ObjectName name = new ObjectName("com.example.mxbeans:type=QueueSampler"); CompositeData queueSample = (CompositeData) mbs.getAttribute(name, "QueueSample"); int size = (Integer) queueSample.get("size");
-
Via a proxy, using the following code:
MBeanServer mbs = ...whatever...; ObjectName name = new ObjectName("com.example.mxbeans:type=QueueSampler"); QueueSamplerMXBean proxy = JMX.newMXBeanProxy(mbs, name, QueueSamplerMXBean.class); QueueSample queueSample = proxy.getQueueSample(); int size = queueSample.getSize();
This code uses the newMXBeanProxy method to create the MXBean proxy. An equivalent method,
newMBeanProxy
, exists to create proxies for other types of MBeans. ThenewMBeanProxy
andnewMXBeanProxy
methods are used in exactly the same way.
MBean Descriptors
Descriptors allow you to give additional information about MBeans to management clients. For example, a Descriptor on an MBean attribute might say what units it is measured in, or what its minimum and maximum possible values are. As of Java SE 6, Descriptors are an integrated part of the JMX API and are available in all types of MBeans.
Descriptors give you a convenient way to attach arbitrary extra metadata to your MBeans. Descriptors have always existed in the JMX API, but until Java SE 6 they were only available in conjunction with Model MBeans.
For most constructors in the classes MBean*Info
(MBeanInfo
, MBeanAttributeInfo
, and so on), a parallel constructor exists with the same parameters plus an additional javax.management.Descriptor
parameter. The same is true for OpenMBean*InfoSupport
. The MBean*Info
and OpenMBean*InfoSupport
classes contain a getDescriptor()
method.
Open MBeans return information about default and legal values from the getDefaultValue()
, getLegalValues()
, getMaxValue()
, getMinValue()
methods of OpenMBeanParameterInfo
and OpenMBeanAttributeInfo
. This information is now also present in the corresponding Descriptors, and other types of MBean can also return the information in their Descriptors.
MBean Descriptors are demonstrated in the example classes you will find in the directory work_dir/jmx_examples/Descriptors/com/example/mxbeans
after you have downloaded and unzipped the jmx_examples.zip
file. The MBean Descriptor example contains the following files.
Author
, an annotation the supplies the name of the author of the MBean interface.DisplayName
, an annotation that supplies a display name for methods in the MBean interface.Main
, the program that sets up and runs the example.QueueSamplerMXBean
interface.QueueSampler
class that implements the MXBean interface.QueueSample
Java type returned by thegetQueueSample()
method in the MXBean interface.Version
, an annotation that supplies the current version of the MBean interface.
The QueueSampler
MXBean in this example basically performs the same actions as the MXBean example presented in Introducing MXBeans , except with the addition of MBean Descriptors. This example shows how the DescriptorKey
meta-annotation can be used to add new descriptor items to the Descriptors for a standard MBean (or an MXBean) via annotations in the standard MBean (or MXBean) interface.
DescriptorKey Annotations
The DescriptorKey
annotation can be used to add information to the
Descriptors for a standard MBean or a MXBean through annotations in the Standard MBean
or MXBean interface. This makes it possible for a tool that generates standard MBeans
from an existing management model to include information from the model in the generated
MBean interfaces, rather than in separate files. The following code example demonstrates
the definition of the annotation Author
.
CODE EXAMPLE 10-9 Author Annotation
package com.example.mxbeans;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.management.DescriptorKey;
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
@DescriptorKey("author")
String value();
}
This annotation supplies the name of the creator of the MBean interface. A new field author
will be added to the MBeanInfo
Descriptor with the value defined by the @Author
annotation. The files Version
and DisplayName
define annotations of those names in exactly the same way as for Author
above. In each of Version
and DisplayName
, the @DescriptorKey
value is “version”
and “displayname”
respectively.
In the case of Version, a new field version
will be added to the MBeanInfo
Descriptor with the value defined by the @Version
annotation.
For DisplayName
, new field displayName
will be added to the MBeanAttributeInfo
Descriptor or the MBeanOperationInfo
Descriptor with the value defined by the @DisplayName
annotation depending on whether the annotated method is a getter/setter or an operation, respectively.
Using MBean Descriptors
The QueueSamplerMXBean
interface used in the following code example
is slightly different from the one used in the MXBeans example. It implements MBean
Descriptors to publish some of its information.
CODE EXAMPLE 10-10 QueueSamplerMXBean with Descriptors
package com.example.mxbeans;
@Author("Mr Bean")
@Version("1.0")
public interface QueueSamplerMXBean {
@DisplayName("GETTER: QueueSample")
public QueueSample getQueueSample();
@DisplayName("OPERATION: clearQueue")
public void clearQueue();
}
Here, the @Author
annotation is set to Mr. Bean
, the @Version
annotation is set to 1.0
, and the @DisplayName
is set to the names either of the attribute QueueSample
or the operation clearQueue
.
Running the MBean Descriptors Example
To run the example:
-
Copy the source code contained in the MBean Descriptors section to
work_dir/jmx_examples/Descriptors
. -
Compile the example Java classes.
$ javac com/example/mxbeans/*.java
-
Start the
Main
application.$ java com.example.mxbeans.Main
You will see confirmation that
Main
is waiting for something to happen. -
Start JConsole in a different terminal window on the same machine.
$ jconsole
You will see the JConsole tool open, presenting a list of running JMX agents that you can connect to.
-
Select
com.example.mxbeans.Main
from the list in the New Connection window, and click on Connect.You will see a summary of your platform’s current activity.
-
Click on the MBeans tab.
This panel shows you all the MBeans currently registered in the MBean server.
-
In the left-hand frame, expand the
com.example.mxbeans
node in the MBean tree.You will see the example MBean
QueueSampler
, that was created and registered by Main. If you click onQueueSampler
, you will see its associated Attributes and Operations nodes in the MBean tree. You will also see the fieldsauthor
andversion
in theMBeanInfo
Descriptor table. -
Expand the
Attributes
andOperations
nodes under theQueueSampler
MBean node.You will see the individual Attributes and Operations.
-
Select the
QueueSample
node.You will see the field
displayName
in theMBeanAttributeInfo
Descriptor table. -
Select the
clearQueue
node.You will see the field
displayName
in theMBeanOperationInfo
Descriptor table. -
Click on Connection and then Exit , to exit JConsole.