blob: d0ed077fd73cc9e7e67c0aad7017566c42e705e3 [file] [log] [blame]
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
= Adding Java Management Extensions (JMX) Instrumentation to a Java Application
:jbake-type: tutorial
:jbake-tags: tutorials
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: Adding Java Management Extensions (JMX) Instrumentation to a Java Application - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, Adding Java Management Extensions (JMX) Instrumentation to a Java Application
*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 existing applications, develop manager applications, and monitor the state of the Virtual Machine.
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
image::images/netbeans-stamp-80-74-73.png[title="Content on this page applies to the NetBeans IDE 7.2, 7.3, 7.4 and 8.0"]
* <<Exercise_1,Exercise 1: Creating the NetBeans sample Anagram Game project>>
* <<Exercise_2,Exercise 2: Creating the AnagramsStats JMX Standard MBean and its Management interface>>
* <<Exercise_3,Exercise 3: Adding attributes, operation and notification to the AnagramsStats JMX Standard MBean>>
* <<Exercise_4,Exercise 4: Adding implementation code to the AnagramsStats JMX Standard MBean>>
* <<Exercise_5,Exercise 5: Connecting the management and the application together>>
* <<Exercise_6,Exercise 6: Running the Anagram Game with JConsole>>
=== Prerequisites
This tutorial assumes you have some basic knowledge of, or programming experience with, the following technologies.
* JMX technology: link:http://download.oracle.com/javase/6/docs/technotes/guides/jmx/index.html[+ JMX online documentation+]
* Java technology: link:http://www.oracle.com/technetwork/java/javase/tech/index.html[+ Java SE Technologies at a Glance+]
* NetBeans IDE
You will also benefit from having some knowledge on link:http://download.oracle.com/javase/6/docs/technotes/guides/management/index.html[+ 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
|link:https://netbeans.org/downloads/index.html[+NetBeans IDE+] |7.2, 7.3, 7.4, 8.0, Java version
|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Java Development Kit (JDK)+] |version 7 or 8
|JMX plugin |Available from NetBeans Update Center
|JConsole plugin |Available from NetBeans Update Center
|===
To install the *JMX* and *JConsole* plugins, choose Tools > Plugins and download the module from the NetBeans Update Center.
=== Resources
* NetBeans help contents (Help > Help Contents > JMX). This help is also available from Wizards.
== 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 that displays a scrambled 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 > Java category.
3. Select the Anagram Game project. Click Next.
4. In the Project Name and Location panel, set the project location or keep the default value if it suits you. Select "Set as Main Project" checkbox if not selected because it will make subsequent actions easier. Click Finish.
When you click Finish the IDE creates the Anagram Game project and displays the project in the Projects window.
. Right-click the AnagramGame project and select Properties.
. Select the Sources category and confirm that the Source/Binary format is set to JDK 7 or JDK 8. Click OK.
*Note.* To select JDK 7 or JDK 8, the Java Platform for the AnagramGame project must also be at least JDK 7 or JDK 8, respectively. You can change the Java Platform for the AnagramGame in the Libraries category in the Properties window.
. Right-click the Anagram Game project node and choose Run.
When you choose Run, the IDE builds and launches the Anagram Game application.
== 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.
Perform the following steps to create the JMX Standard MBean.
1. Confirm that the Anagram Game project is set as the main project.
2. Choose File > New File (Ctrl-N).
3. From the JMX category, select Standard MBean. Click Next.
image::images/jmx-newfile.png[title="Standard MBean file type in New File Wizard"]
. Enter the following information Name and Location panel:
* Class Name: ``AnagramsStats``
* Location: Source Packages (default)
* Package: ``com.toy.anagrams.mbeans``
* Description: ``Monitoring and Management of the Anagrams Game``
image::images/jmx-newmbean.png[]
. Click Finish.
When you 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 now several empty skeletons that you will populate 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 generated MBean skeleton, so that it monitors the time spent by the user to solve a new anagram and a JMX notification is sent each time an anagram is solved.
The MBean will contain the following:
* Two Attributes named ``LastThinkingTime`` and ``NumResolvedAnagrams``
* An Operation named ``resetAll`` .
* A notification of type ``AttributeChangeNotification`` . This notification is emitted when ``LastThinkingTime`` is updated.
Perform the following steps to populate the MBean skeleton.
1. Open the ``AnagramsStats.java`` MBean implementation file in the NetBeans editor.
2. Right-click in the source editor and select *JMX > Add MBean Attributes* in the popup menu.
3. Add the ``LastThinkingTime`` attribute by clicking the Add Attribute button and supplying the following information.
* Attribute Name: ``LastThinkingTime``
* Type: int
* Access: ReadOnly
* Description: ``Elapsed time to solve last anagram``
*Note.* Do not click OK yet!
. Click Add Attribute again and add the following ``NumSolvedAnagrams`` attribute. Click OK.
* Attribute Name: ``NumSolvedAnagrams``
* Type: int
* Access: ReadOnly
* Description: ``Number of solved anagrams``
image::images/jmx-addattribute.png[]
The necessary code to expose the read only ``LastThinkingTime`` and ``NumSolvedAnagrams`` attributes is generated in both the ``AnagramsStats`` MBean class and its interface.
You can 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. The private fields ``lastThinkingTime`` and ``numSolvedAnagrams`` of type ``int`` were also generated and will be used to store the actual attribute values.
Next you will add three more attributes to keep track of the minimum and maximum thinking time the user took, and of the current anagram being proposed to the user.
. Right-click in the source editor and select *JMX > Add MBean Attributes* in the popup menu.
. Click the Add Attribute button and 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
|===
The dialog box should be similar to the following image.
image::images/jmx-addattribute2.png[title="Add Attribute dialog after adding 3 more attributes"]
*Note.* Notice that the attributes that you already created are listed in the dialog box.
. Click OK and save your changes.
. Right-click in the source editor and select *JMX > Add MBeans Operations* in the popup menu.
. Click Add Operation and add the ``resetAll()`` operation and specify the following details. Click OK.
* Operation Name: ``resetAll``
* Return Type: ``void``
* Parameters: (leave empty)
* Exceptions: (leave empty)
* Description: ``Reset MBean state``
image::images/jmx-addoperation.png[title="Adding resetAll operation in Add Operation dialog"]
After you click OK you can see that the necessary code to expose the ``resetAll`` operation was generated in both the ``AnagramsStats`` MBean class and its interface.
. Right-click in the source editor and select the *JMX > Implement NotificationEmitter interface* in the popup menu.
. Specify the following details in the Implement NotificationEmitter interface dialog box.
* *Select Generate Delegation to Broadcaster.* 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.
* *Select 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 Add Notification.* Specify the following details in the Notifications table.
* Notification Class: ``javax.management.AttributeChangeNotification``
* Notification Type: (it is automatically set to ``ATTRIBUTE_CHANGE`` )
* Description: ``Anagram is Solved``
image::images/jmx-changenotification.png[title="Adding change notification in Implement NotificationEmitter dialog"]
Click OK.
You can see that the necessary code to implement the ``NotificationEmitter`` interface was generated in the ``AnagramsStats`` MBean class. You can see how the generated implementation delegates the handling of notifications to the ``NotificationBroadcasterSupport`` class.
. Save your changes.
In this exercise you 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. You 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 you will add some internal logic to the ``AnagramsStats`` MBean class implementation.
Perform the following steps to add the implementation code.
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 bold) in the ``resetAll()`` method body:
[source,java]
----
public void resetAll() {
*minThinkingTime = 0;
maxThinkingTime = 0;
lastThinkingTime = 0;
numSolvedAnagrams = 0;*
}
----
. You also need to add some implementation code that will do the following:
* 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 you will add a private field ``startTime`` to store the time at which the last anagram was presented to the user, two methods ``startThinking()`` and ``stopThinking()`` to perform the operations listed above, and a ``setCurrentAnagram()`` method.
Add the following code to ``AnagramsStats.java`` , e.g. at the end of the class implementation.
[source,java]
----
/*
* 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 they are public because they will be called by the Anagram Game application to tell the MBean each time that 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.
You are now done with the MBean implementation. In this section you added code and methods to allow the following:
* internal MBean state updates
* calls from the application
* sending of JMX notifications
== 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.
Perform the following steps to
1. Open ``Anagrams.java`` in the editor.
The ``Anagrams`` class in the ``com.toy.anagrams.ui`` package is the ``main`` class of the Anagram Game application. The file opens in the Editor's Design view because the ``Anagrams`` class is also the User Interface class.
. Click the Source button at the top of the Editor window to edit the class in the Source view.
. Add the following empty ``initManagement()`` private method to the ``Anagrams`` class: after the ``Anagrams`` constructor.
[source,java]
----
/**
* JMX initialization:
* Create and register Anagrams MBean in Platform MBeanServer.
* Initialize thinking time and current anagram.
*/
private void initManagement() throws Exception {
}
----
. Add the following call to the ``initManagement()`` method at the end of the ``Anagrams`` class constructor before the enclosing curly brace marking the end of the constructor.
[source,java]
----
//JMX Management initialization
initManagement();
----
You also need to add a ``throws Exception`` clause to the ``Anagrams()`` constructor and surround the statement ``new Anagrams().setVisible(true);`` with a try-catch in the ``Main()`` method to compile. You can see the suggestion glyph in the left margin of the editor. You can place your insert cursor in the line in the code and type Alt-Enter to invoke the code hint in the source editor.
image::images/jmx-initmanagement-try.png[title="Code hint to add try-catch"]
Here is what you should see at this stage [click to view larger image]:
[.feature]
--
image:images/jmx-initmanagement-sm.png[role="left", link="images/jmx-initmanagement.png"]
--
. 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:
image::images/jmx-registermbeandialog.png[]
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. You 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 this 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, you need to make the following changes to the code of the ``Anagrams.java`` file.
. Add the following private field to the ``Anagrams`` class.
[source,java]
----
// 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:
[source,java]
----
private void initManagement() throws Exception {
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:
[source,java]
----
// 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]:
[.feature]
--
image:images/jmx-initmanagement2-sm.png[role="left", link="images/jmx-initmanagement2.png"]
--
You now need to add code to track the user's anagram solving experience.
. Locate the ``nextTrialActionPerformed()`` method and paste the following code at the end of the ``nextTrialActionPerformed()`` method.
[source,java]
----
//Update management statistics and values
try {
mbean.setCurrentAnagram(wordLibrary.getScrambledWord(wordIdx));
mbean.startThinking();
} catch (Exception e) {e.printStackTrace();}
----
Each time that a new anagram is proposed to the user, the code tells the MBean which anagram it is and to start counting the user thinking time.
. Locate the ``guessedWordActionPerformed()`` method and add the following lines to the code. Save your changes.
[source,java]
----
//Update management stats
try {
mbean.stopThinking();
} catch(Exception e) {e.printStackTrace();}
----
The ``stopThinking()`` method in the MBean is called each time that an anagram is guessed correctly.
You should now see the following in the editor [click to view larger image]:
[.feature]
--
image:images/jmx-stopthinking-sm.png[role="left", link="images/jmx-stopthinking.png"]
--
You have now finished linking the JMX management layer to the application layer. In the next section you will 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.
Perform the following steps to run the application and view the management information.
1. A single step performs these three tasks: simply click the "Run Main Project with Monitoring and Management" button in the toolbar (  image::images/run-project24.png[title="Run Main Project with Monitoring and Management button"])
You can also invoke the action from the Run menu in the main menu.
*Note.* The first time that you build and run the application the IDE displays a warning dialog that informs you that the ``build.xml`` files will be updated. You can click OK in the dialog.
image::images/jmx-firsttime.png[title="Warning dialog when monitoring application for the first time"]
You can follow the execution in the Output window.
image::images/jmx-compiling.png[title="Output window displaying process"]
The IDE will build and launch the Anagram game and will automatically open the JConsole window.
image::images/jmx-anagram.png[title="Anagram Game"]
*Notes.* You might see a Connection Failed warning in the Java Monitoring &amp; Management Console when the console attempts to connect to the Anagram Game process. For this tutorial you can click Insecure when you are prompted to authorize the connection.
. Select the MBeans tab in the JConsole window.
. In the tree layout in the left pane, expand all the nodes under ``com.toy.anagrams.mbeans`` .
image::images/jmx-jconsole-mbeans1.png[title="MBeans tab showing AnagramsStats node"]
. 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.
. In the Anagrams Game window, and solve the first three or four anagrams.
The solutions to the anagrams (abstraction, ambiguous, arithmetic, backslash,...) are contained in the ``WordLibrary`` class.
. In the JConsole window, and notice that it received notifications for each of the solutions.
[.feature]
--
image::images/jmx-jconsole-mbeans2-sm.png[role="left", link="images/jmx-jconsole-mbeans2.png"]
--
. Click on the Attributes node and notice the attributes values are updated:
image::images/jmx-jconsole-mbeans3.png[title="MBeans tab showing AnagramsStats node"]
You can experiment with the JConsole interface and the Anagrams Game. For example, if you invoke the management operation ``resetAll()`` you will see that the MBean attribute values are reset to 0.
*And now, you are done! You did a really good job, congratulations! *
link:/about/contact_form.html?to=3&subject=Feedback:%20Adding%20Java%20Management%20Extensions%20(JMX)%20Instrumentation[+Send Feedback on This Tutorial+]
== See Also
For more information, see the following:
* link:jmx-getstart.html[+Getting Started with JMX Monitoring in NetBeans IDE+]