Adding Java Management Extensions (JMX) Instrumentation to a Java Application
Last Updated: December 2007
By
and
,
JMX Engineering Team.
Expected duration: 60 minutes
The NetBeans JMX Wizard Module integrates JMX technology right into your workflow
in the NetBeans IDE. This module allows you to quickly develop management applications,
add management to exisiting applications, develop manager applications, and
monitor the state of the Virtual Machine.
This tutorial has been updated for the JMX Wizard module version 3.0, available for NetBeans
IDE version 6.0 and higher.
This tutorial shows you how to add management to an existing application (the
NetBeans sample Anagrams Game application). You will first create a non-manageable
Anagram Java Project. You will then use JMX Wizards to generate 90% of the management.
Then you will implement the management behavior specific to the application.
You will finally use the Run/Debug project with JConsole to visualize the Anagram
MBeans.
To install the JMX plugin, choose Tools > Plugins and download the module from the NetBeans Update Center.
IMPORTANT NOTE: If you are using NetBeans 6.1 or higher, you also need to download and install the JConsole module.
This tutorial requires the JDK 5 or higher version of the Java Platform.
The steps detailed below have been performed with JDK 6.
Resources
NetBeans help contents (Help > Help Contents > JMX). This help is
also available from Wizards.
You can see a full size view of the reduced screen captures by clicking on them.
Exercise 1: Creating the NetBeans sample Anagram Game project
The goal of this exercise is to create a runnable Java Project. The Anagram
game is a Swing Application. It displays a mixed-up word to the user and waits
for the user to solve the anagram.
Choose File > New Project (Ctrl-Shift-N).
Select the Samples > General category.
Select the Anagram Game project.
Click Next. The Project Name and Location panel is displayed.
Set your project location, or keep the default value if it suits you.
Keep the "Set as Main Project" checkbox selected, it will make subsequent
actions easier.
Click Finish. A new anagrams project is created.
Make sure the Source/Binary format is at least JDK 5:
Right click on the AnagramGame project and select Properties.
In categories: Sources, select JDK 5 or JDK 6 in Source/Binary Format drop down selection
and click OK. If NetBEans proposes to regenerate the build-impl.xml,
accept by clicking Regenerate.
Note that to be able to select JDK 5 or JDK 6 Source/Binary format, the Java Platform
for the AnagramGame project must be ast least JDK 5 or JDK 6 respectively.
You can change the Java Platform for the AnagramGame in the project Properties,
categories: Libraries.
At this point you have a working anagram game:
you can check by building and running the AnagramGame project.
Exercise 2: Creating the AnagramsStats JMX Standard MBean and its Management interface
The goal of this exercise is to create a skeleton JMX Standard MBean,
which is composed of its implementation class and its management interface.
Steps to Follow
Be sure to have selected the anagrams project and to have set it as your main
project.
Choose File > New File (Ctrl-N).
From the JMX category, select Standard MBean:
Click Next to go to the New Standard MBean Name and Location panel.
Enter the following information:
Class Name: AnagramsStats
Location: Source Packages (default)
Package: com.toy.anagrams.mbeans
Description: Monitoring and Management of the Anagrams Game
Then click Finish:
the AnagramsStats MBean class and AnagramsStatsMBean
MBean interface are generated in the com.toy.anagrams.mbeans
package of the AnagramGame project. These are empty skeletons for now,
we are going to populate them in the next exercise.
Exercise 3: Adding attributes, operation and notification to the AnagramsStats JMX Standard MBean
The goal of this exercise is to populate the previously generated MBean skeleton,
so that we can use it to monitor the time spent by the user to solve a new anagram.
Each time an anagram is solved, we also want a JMX notification to be sent.
The MBean will contain:
Two Attributes named LastThinkingTime and NumResolvedAnagrams
An Operation named resetAll.
A notification of type AttributeChangeNotification. This notification
is emitted when LastThinkingTime is updated.
Steps to Follow
Open the just generated AnagramsStats.java MBean implementation file
in the NetBeans editor.
We are going to add the LastThinkingTime attribute:
Right-click in the NetBeans editor window where the AnagramsStats.java
file is opened, select the JMX submenu and then the
"Add MBean Attributes..." action.
In the panel that shows up, click the Add Attribute button and then
specify the following information, but do not click OK yet:
Attribute Name: LastThinkingTime
Type: int
Access: ReadOnly
Description: Elapsed time to solve last anagram
We are going to add the NumSolvedAnagrams attribute:
in the same panel, click again the Add Attribute button and then
specify the following information:
Attribute Name: NumSolvedAnagrams
Type: int
Access: ReadOnly
Description: Number of solved anagrams
Then click OK. The necessary code to expose the read only LastThinkingTime
and NumSolvedAnagrams attributes have been generated in both the
AnagramsStats MBean class and its interface.
Look at the code: you will see the private fields declaration and the public
getter methods.
More precisely, looking at the members view and at the generated code, you will notice
that the getLastThinkingTime and getNumSolvedAnagrams methods
are generated both in the AnagramsStats class and in its
AnagramsStatsMBean interface. Private fields named lastThinkingTime
and numSolvedAnagrams of type int are also generated. They are used to
store the actual attribute values.
Click the NetBeans Save button to save your changes.
Now, we realize we also would like to keep track via the management interface
of the minimum and maximum thinking time the user took, and of the current
anagram being proposed to the user. We need to add three more attributes:
Right-click in the NetBeans editor window where the AnagramsStats.java
file is opened, select the JMX submenu and then the
"Add MBean Attributes..." action.
Notice the previously created attributes are already listed.
Using the Add Attribute button add the following attributes:
Attribute Name
Type
Access
Description
MinThinkingTime
int
ReadOnly
Minimum elapsed time to solve an anagram
MaxThinkingTime
int
ReadOnly
Maximum elapsed time to solve an anagram
CurrentAnagram
String
ReadOnly
Current anagram to solve
Here is what you should see before you click OK:
Click OK and save your changes.
We are going to add the resetAll() operation:
Right-click in the NetBeans editor window where the AnagramsStats.java
file is opened, select the JMX submenu and then the
"Add MBeans Operations..." action.
In the panel that shows up, click the Add Operation button and then
specify the following information:
Operation Name: resetAll
Return Type: void
Parameters: (leave empty)
Exceptions: (leave empty)
Description: Reset MBean state
Then click OK. The necessary code to expose the resetAll
operation has been generated in both the AnagramsStats MBean class and
its interface, you can have a look.
Click the NetBeans Save button to save your changes.
We are now going to add notification emission:
Right-click in the NetBeans editor window where the AnagramsStats.java
file is opened, select the JMX submenu and then the
"Implement NotificationEmitter interface..." action.
In the panel that shows up:
Check the Generate Delegation to Broadcaster checkbox. All methods
declared by the NotificationEmitter interface will be implemented
by delegating to a notification broadcaster. A notification broadcaster
simplifies the way the MBean will send notifications.
Check the Generate Private Seq Number and Accessor. Some code will be
generated to handle the unique sequence number value that must be added
to each notification that is sent.
Click the Add Notification button and then
specify the following information:
Notification Type: (it is automatically set to ATTRIBUTE_CHANGE)
Description: Anagram is Solved
Then click OK. The necessary code to implement the NotificationEmitter
interface has been generated in the AnagramsStats MBean class. Have a look...
Notice how the generated implementation delegates the handling of notifications
to the NotificationBroadcasterSupport class.
Click the NetBeans Save button to save your changes.
Summary
In this exercise, you have learned how to add attributes, operations and
notifications emission to an MBean using the JMX Wizard module.
The steps needed to populate your MBean with the necessary infrastructure
to expose the management information you want are now finished.
We now need to add internal logic to the AnagramsStats MBean
class implementation, then build the bridge between the MBean and the
Anagram Game application.
Exercise 4: Adding implementation code to the AnagramsStats JMX Standard MBean
In this exercise, we will add some internal logic to the AnagramsStats
MBean class implementation.
Steps to Follow
The attributes
already have their private fields declared, and nothing needs to be added
to their getter methods.
The resetAll() method needs to be implemented. The generated body
is empty. When resetAll() is called, we simply set all counters
to 0. Add the following lines of code in the resetAll() method body:
We also need to add some implementation code in order to:
calculate the thinking time the user took to solve the last anagram,
calculate the minimum and maximum thinking times,
increment the counter of solved anagrams,
know wich is the current anagram,
create and send a notification when an anagram is solved.
For that purpose we will add a private field startTime to store at
which time the last anagram was presented to the user, two methods
startThinking() and stopThinking() to perform the operations
listed above, and a setCurrentAnagram() method.
To add this code, copy and paste into the AnagramsStats.java
file, e.g. at the end of the class implementation, the following Java code:
/*
* Methods exposed to Anagrams application to feed management with data.
*/
//Stores the time at which a new anagram is proposed to the user.
private long startTime;
/**
* A new Anagram is proposed to the user: store current time.
*/
public void startThinking() {
startTime = System.currentTimeMillis();
}
/**
* An Anagram has been resolved.
*/
public void stopThinking() {
//Update the number of resolved anagrams
numSolvedAnagrams++;
// Compute last, min and max thinking times
lastThinkingTime = (int) (System.currentTimeMillis() - startTime) / 1000 ;
minThinkingTime = (lastThinkingTime < minThinkingTime || minThinkingTime == 0) ?
lastThinkingTime :
minThinkingTime;
maxThinkingTime = (lastThinkingTime > maxThinkingTime) ?
lastThinkingTime :
maxThinkingTime;
//Create a JMX Notification
Notification notification = new Notification(AttributeChangeNotification.ATTRIBUTE_CHANGE,
this,
getNextSeqNumber(),
"Anagram solved: " + currentAnagram);
// Send a JMX notification.
broadcaster.sendNotification(notification);
}
/**
* Set latest anagram which has been computed by the Anagram application
*/
public void setCurrentAnagram(String currentAnagram) {
this.currentAnagram = currentAnagram;
}
Note that the three methods startThinking(), stopThinking() and
setCurrentAnagram() are not part of the MBean management interface, because they
are not declared in the AnagramsStatsMBean interface, but still they are
public because they will be called by the Anagram Game application to tell the MBean
everytime a new anagram is presented to the user and when it is solved, and
which is the current anagram. So, they
are a necessary part of the bridge between the application and our MBean.
Notice also how a JMX notification of type ATTRIBUTE_CHANGE is sent
each time an anagram is solved.
Summary
In this chapter you simply added code and methods to allow:
internal MBean state updates
calls from the application
sending of JMX notifications
You are done with the MBean implementation.
Exercise 5: Connecting Management and the Application Together
In this exercise, we will add code to the Anagram Game application so that it
can access the MBean to pass management information.
Steps to Follow:
The main class of the Anagram Game application is the Anagrams
class in the com.toy.anagrams.ui package. Double-click the
Anagrams.java file. As the Anagrams class is also the User
Interface class, the file opens in the Editor's Design view, so click the Source
button at the top of the Editor window to edit the class
in the Source view, not in the design view.
We add an empty (for now) initManagement() private mehod to the
Anagrams class:
Copy and paste the following lines of code right after the Anagrams
constructor:
/**
* JMX initialization:
* Create and register Anagrams MBean in Platform MBeanServer.
* Initialize thinking time and current anagram.
*/
private void initManagement() throws Exception {
}
We add a call to the initManagement() method at the end of
the Anagrams class constructor:
Copy and paste the following lines of code right before the enclosing
curly brace marking the end of the Anagrams
constructor:
//JMX Management initialization
initManagement();
You also need to add a throws Exception clause to the
Anagrams() constructor and to the Main() method declarations
for your code to compile.
Here is what you should see at this stage [click to view larger image]:
We now add the MBean registration code to the initManagement()
method, using the JMX Module MBean registration wizard:
In the Anagrams.java source editor window, right-click
inside the initManagement() method body,
select the JMX submenu and then the
"Generate MBean Registration..." action.
In the "Instantiate and Register MBean" panel that shows up,
keep the "Register Existing MBean" radio-button selected,
click the Browse button, choose the AnagramsStats MBean class and
click OK in the Browse panel. You should now see:
No need to change the automatically specified MBean Object Name and Constructor.
Click OK, and you will see the generated MBean registration code
in the initManagement() method body.
Best practice for naming your MBeans
When naming your MBean, use the "type=" key in the Object Name. The value
of this key should be the MBean class (in our case AnagramsStats).
In the case of a singleton MBean (an MBean that has a single instance within
your application), having this unique key is sufficient for naming purposes.
Avoid creating too many domain names. Use your application Java package names.
You can also use
the default domain name: not specifying a domain before the ObjectName
":" separator implicitly references the default domain.
Applying best practices will make the way you name your MBeans more formalized.
So, the ObjectName created by default in our case above is:
com.toy.anagrams.mbeans:type=AnagramsStats
In the context of this tutorial, an extra step is required. We want the
application to have access to the class implementing the management interface
(AnagramsStats). This is not a general rule but it can be useful
when your application needs to push data to an MBean. In our case, the
startThinking(),
stopThinking() and setCurrentAnagram()
methods are not management methods but are used
by the Anagrams Game application to notify the
MBean that some events have occured. In turn, the MBean updates its state.
In order to make AnagramsStats accessible from the Anagrams
UI class, we need the Anagrams class to keep a direct reference to the
instance of the AnagramsStats MBean.
Therefore, we need to modify the code of the Anagrams.java
file as follows:
Add a private field to the Anagrams class. Copy and paste from below:
// Reference to the AnagramsStats MBean
private AnagramsStats mbean;
Initialize the reference to the AnagramsStats MBean in the
initManagement() method, by modifying the generated MBean Registration
code so that it reads:
try { // Register MBean in Platform MBeanServer
mbean = new AnagramsStats();
ManagementFactory.getPlatformMBeanServer().
registerMBean(mbean,
new ObjectName("com.toy.anagrams.mbeans:type=AnagramsStats"));
} catch (JMException ex) {
ex.printStackTrace();
}
Initialize the AnagramsStats MBean state:
when the Anagrams Game application starts up, an anagram is immediately displayed,
so we need to pass to the MBean the anagram string value and to start
computing thinking time. Copy and paste the lines below at the end of the
initManagement() method:
// When the Anagrams game is first displayed, a word is proposed to the user.
// We must start time computing and set the current anagram
mbean.startThinking();
mbean.setCurrentAnagram(WordLibrary.getScrambledWord(wordIdx));
Here is what you should see at this stage [click to view larger image]:
We now need to add code to track the user's anagram solving experience.
Add code in two places:
In the nextTrialActionPerformed() method:
each time a new anagram is proposed to the user, we must tell the MBean
which is the new anagram and to start counting the user thinking time.
So, copy and paste the lines of code below at the end of the
nextTrialActionPerformed() method:
Here is what you should see at this stage [click to view larger image]:
You have now finished linking the JMX management layer to the
application layer.
We are now going to build and run the Anagrams Game application and
look at the exposed management information through the JConsole GUI.
In this exercise, you will learn how to build and run your project, and connect
JConsole to visualize the JVM state, as well as the application MBeans.
Steps to Follow
A single step performs these three tasks: simply click the
"Run Main Project with Monitoring and Management" icon
in the toolbar.
This action is also available in NetBeans Run menu.
A dialog box warns you that the build.xml files will be updated.
Just click OK.
You can follow the execution in the output console.
The Anagram game should start and its GUI displayed:
In the JConsole window, select the MBeans tab and in the tree layout
on the left open down all nodes under com.toy.anagrams.mbeans
as shown below:
Select the Notifications node and click on the Subscribe button at the
bottom so that JConsole will receive a new notification each
time an anagram is solved:
Now go to the Anagrams Game window, and solve the first three or four anagrams
(The answers are in the WordLibrary class, but here they are:
abstraction, ambiguous, arithmetic, backslash, ...)
Go back to JConsole, and notice that it received the four notifications
[JConsole window width has been enlarged below]:
Click on the Attributes node and notice the attributes values are updated:
Now, you can just play with the JConsole interface and the Anagrams Game.
For example, you can invoke the management operation resetAll().
Notice that the MBean attribute values are indeed reset to 0.
And now, you are done! You did a really good job, congratulations!