FeaturesPluginsDocs & SupportCommunityPartners

Adding Java Management Extensions (JMX) Instrumentation to a Java Application

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.

Tutorial exercises

Content on this page applies to NetBeans IDE 6.0 and 6.1

Prerequisites

This tutorial assumes you have some basic knowledge of, or programming experience with, the following technologies.

You will also benefit from having some knowledge on Monitoring and Management for the Java Platform

Software Needed for the Tutorial

For this tutorial you need to have the following software installed on your computer:

Software or Resource Version Required
NetBeans IDE version 6.1 or
version 6.0
Java Developer Kit (JDK) version 6 or
version 5
JMX plugin Available from NetBeans Update Center

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.

  1. Choose File > New Project (Ctrl-Shift-N).
  2. Select the Samples > General category.
  3. Select the Anagram Game project.
    create_anagram: create Anagram Game project, step 1
  4. 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.
    create_anagram2: create Anagram Game project, step 2
  5. Click Finish. A new anagrams project is created.
  6. 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.
  7. 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.

  1. Choose File > New File (Ctrl-N).
  2. From the JMX category, select Standard MBean:
    create_mbean1: create new Standard MBean, step 1
  3. 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
  4. create_mbean2: create new Standard MBean, step 2

  5. 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

  1. Open the just generated AnagramsStats.java MBean implementation file in the NetBeans editor.
  2. 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

    create_mbean7: Add LastThinkingTime attribute
  3. 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
  4. create_mbean7bis: Add NumSolvedAnagrams attribute

  5. 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.

  6. 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:

  7. create_mbean7ter: Add 3 more attributes

    Click OK and save your changes.

  8. 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

  9. create_mbean8: Add resetAll operation

  10. 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.

  11. 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 Class: javax.management.AttributeChangeNotification
      • Notification Type: (it is automatically set to ATTRIBUTE_CHANGE)
      • Description: Anagram is Solved

    create_mbean9: Implement NotificationEmitter interface

  12. 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

  1. The attributes already have their private fields declared, and nothing needs to be added to their getter methods.

  2. 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:
  3.         minThinkingTime = 0;
            maxThinkingTime = 0;
            lastThinkingTime = 0;
            numSolvedAnagrams = 0;
      
  4. 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;
        }
          
  5. 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.

  6. 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:

  1. 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.

  2. 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 {
    
        }
              

  3. 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]:

    instrument_anagram1: adding initManagement()


  4. 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:

    create_mbean_registration: Generate MBean Registration code

    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.



  5. 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:

  6. Add a private field to the Anagrams class. Copy and paste from below:
        // Reference to the AnagramsStats MBean
        private AnagramsStats mbean;
        
  7. 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();
            }
        
  8. 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));
          
  9. Here is what you should see at this stage [click to view larger image]:

    instrument_anagram2: initialize MBean Reference and State


  10. 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:

              //Update management statistics and values
              try {
                  mbean.setCurrentAnagram(WordLibrary.getScrambledWord(wordIdx));
                  mbean.startThinking();
                  } catch (Exception e) {e.printStackTrace();}
       
    • In the guessedWordActionPerformed() method: each time an anagram is guessed correctly, we must tell so to the MBean by a call to stopThinking().

      So, in the guessedWordActionPerformed() method, copy and paste the lines below in the block of code to execute if the guessed word is correct:

                  //Update management stats
                  try {
                      mbean.stopThinking();
                  } catch(Exception e) {e.printStackTrace();}
          
  11. Here is what you should see at this stage [click to view larger image]:

    instrument_anagram3: call MBean methods


    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.


 

Exercise 6: Running the Application with JConsole

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

  1. A single step performs these three tasks: simply click the "Run Main Project with Monitoring and Management" icon JConsole Button in the toolbar. This action is also available in NetBeans Run menu.

  2. A dialog box warns you that the build.xml files will be updated. Just click OK.
  3. Run 1 - click for fullsize


    You can follow the execution in the output console.

    Run 2 - click for fullsize


  4. The Anagram game should start and its GUI displayed:
  5. Run 3 - click for fullsize


  6. 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:
  7. Run 4 - click for fullsize


  8. 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:
  9. Run 5 - click for fullsize


  10. 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, ...)

  11. Go back to JConsole, and notice that it received the four notifications [JConsole window width has been enlarged below]:
  12. Run 6 - click for fullsize


  13. Click on the Attributes node and notice the attributes values are updated:
  14. Run 7 - click for fullsize


  15. 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!


See Also

For more information, see the following:

Bookmark this page

del.icio.us furl simpy slashdot technorati digg
Companion
Projects:
MySQL Database Server   Open JDK: an Open SourceJDK   GlassFish Community: an Open Source Application Server    Mobile & Embedded Community    Open Solaris   java.net - The Source for Java Technology Collaboration   Open ESB - The Open Enterprise Service Bus Powered by