1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 2 3 <html> 4 <head> 5 <!-- 6 Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. 7 8 Redistribution and use in source and binary forms, with or without 9 modification, are permitted provided that the following conditions 10 are met: 11 12 - Redistributions of source code must retain the above copyright 13 notice, this list of conditions and the following disclaimer. 14 15 - Redistributions in binary form must reproduce the above copyright 16 notice, this list of conditions and the following disclaimer in the 17 documentation and/or other materials provided with the distribution. 18 19 - Neither the name of Oracle nor the names of its 20 contributors may be used to endorse or promote products derived 21 from this software without specific prior written permission. 22 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 --> 35 36 <title>JMX(TM) "scandir" Example</title> 37 </head> 38 <body> 39 40 <h1><center>Java<font size="-1"><sup>TM</sup></font> Management Extensions (JMX<font size="-1"><sup>TM</sup></font>) <i>scandir</i> Example</center></h1> 41 42 <h2><a name="h2-Introduction">Introduction</a></h2> 43 <ul> 44 <p>The JMX <i>scandir</i> example is an application that 45 scans parts of a filesystem - e.g. a set of directories 46 used by a number of lab machines when running tests - in 47 order to clean up and optimize disk space by removing 48 obsolete files - e.g. files that are leaked by the test 49 suites running on those machines, like coredump files, or 50 temporary files that might remain after a test crash. 51 It could also serve as a basis for an application that 52 would monitor disk usage and suggest removal of old big 53 long-unaccessed files. 54 </p> 55 <p>The JMX <i>scandir</i> example does not however implement 56 the full fledged logic that such an application might 57 have. It implements a subset of this logic which is 58 sufficient to demonstrate common patterns and 59 solutions used when implementing a monitoring and 60 management interface for an application with JMX 61 Technology.</p> 62 <p>This example is an advanced JMX example, which presents 63 advanced JMX concepts. It is assumed that the reader is already 64 familiar with the JMX API. Newcomers to JMX Technology are 65 invited to have a look at the <a 66 href="http://java.sun.com/javase/6/docs/technotes/guides/jmx/" 67 >JMX API Overview, Tutorial and Examples</a> before going any further. 68 </p> 69 <p></p> 70 <hr> 71 <blockquote> 72 <u>Note:</u> This example was developed using <a 73 href="http://www.netbeans.org">NetBeans 5.0 IDE</a>. The instructions 74 given in this document to build, run, and test the example assume that 75 you have at your disposal: 76 <ul><li>either <a href="http://www.netbeans.org">NetBeans 5.0 IDE</a>,</li> 77 <li>or <a href="http://ant.apache.org/">Apache Ant 1.6.5</a> and 78 <a href="http://sourceforge.net/projects/junit/">JUnit 3.8.1 or 79 3.8.2</a><br> 80 (JUnit is only needed to run the example's unit tests). 81 </li> 82 </ul> 83 <p><a name="setup">In order to build the example</a>, 84 <u>you may need to copy the jmx-scandir</u> 85 directory to somewhere where you have write permissions. 86 <br>In that case, you will need to update the <i>nbjdk.home</i> variable 87 in the copied <i><a href="build.properties">build.properties</a></i> 88 file located at the root of the copied project directory. 89 Please make sure that this variable points to the JDK 6 home directory. 90 </p> 91 <p>If you wish to run the testsuite from within the <a 92 href="http://www.netbeans.org">NetBeans IDE</a> you will also have 93 to set the <i>libs.junit.classpath</i> variable in 94 <a href="build.properties">build.properties</a>. 95 The <i>libs.junit.classpath</i> variable should point to your 96 <a href="http://sourceforge.net/projects/junit/">junit.jar</a>, 97 version 3.8.1 or 3.8.2. 98 </p> 99 </blockquote> 100 <hr> 101 <p></p> 102 <p><u>Table Of Contents:</u></p> 103 <p><center>[<a href="#h2-Generating">Generating the Java Documentation</a>] 104 [<a href="#h2-Overview">Overview of the <i>scandir</i> Example</a>] 105 [<a href="#h2-API-Doc">API Documentation and Sources</a>] 106 [<a href="#h2-Patterns">Patterns, Best Practices, and Common Pitfalls</a>] 107 [<a href="#h2-Testing">Testing the <i>scandir</i> Example</a>] 108 [<a href="#h2-Running">Running the <i>scandir</i> Example</a>] 109 [<a href="#h2-Playing">Playing with JConsole</a>] 110 [<a href="#h2-Turning">Turning the example into a Secure JMX Application</a>] 111 [<a href="#h2-Connecting">Connecting to the Secure JMX Application</a>] 112 [<a href="#h2-Conclusion">Conclusion</a>] 113 [<a href="#h2-References">References</a>]</center></p> 114 115 </ul> 116 <h2><a name="h2-Generating">Generating the Java Documentation</a></h2> 117 118 <ul> 119 <p>Before reading further, you will need to generate the 120 Java Documentation for the example's sources.</p> 121 <p>In the example root directory (where the <code>build.xml</code> 122 file is located) run the following command: 123 <pre>ant javadoc</pre> 124 </p> 125 <p>Alternatively you can open the jmx-scandir project with the 126 NetBeans IDE and generate the Javadoc from its <code>Build</code> 127 menu. 128 </p> 129 <p>If building the documentation fails, please make sure to read the 130 <a href="#setup">note</a> at the beginning of this document.</p> 131 </ul> 132 133 <h2><a name="h2-Overview">Overview of the <i>scandir</i> Example</a></h2> 134 135 <ul> 136 <p>The JMX <i>scandir</i> example is built around the 137 following MBeans:</p> 138 <ul> 139 <li>The first MBean we will present here is the 140 <a 141 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 142 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 143 >DirectoryScannerMXBean</a>. <br>A 144 <code>DirectoryScannerMXBean</code> is an MBean that scans a 145 file system starting at a given root directory, and then looks 146 for files that match the given criteria. When such a file is 147 found, the <code>DirectoryScannerMXBean</code> takes the 148 action for which it was configured: emit a notification, 149 <i>and/or</i> log a <code>record</code> for this file, 150 <i>and/or</i> delete that file. The code that would actually 151 delete the file is commented out - so that nothing valuable is 152 lost if the example is run by mistake on the wrong set of 153 directories.<br> <code>DirectoryScannerMXBeans</code> are 154 created by the <a 155 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 156 title="The ScanManagerMXBean is the main MBean of the scandir application" 157 >ScanManagerMXBean</a> - see next item on the list, from its 158 configuration. 159 </li> 160 <li> 161 The <a 162 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 163 title="The ScanManagerMXBean is the main MBean of the scandir application" 164 >ScanManagerMXBean</a> is the actual entry point of the 165 application. It reads the application's 166 configuration, and from that configuration, 167 will create a <a 168 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManager.html" 169 title="The ResultLogManager is in charge of managing result logs" 170 >ResultLogManager</a> and some <a 171 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 172 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 173 >DirectoryScannerMXBeans</a>. 174 <br>The <code>ScanManagerMXBean</code> lets you start, stop, and 175 schedule directory scans. The 176 <code>ScanManagerMXBean</code> is a singleton 177 MBean: there can be at most one instance of such 178 an MBean registered in a given MBeanServer. 179 </li> 180 <li>The <a 181 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 182 title="The ScanDirConfigMXBean is in charge of the configuration" 183 >ScanDirConfigMXBean</a> is an MBean which is able to 184 load/save the configuration to/from an XML file. It 185 will also let you modify that configuration - by e.g. 186 creating new directory scanners in there. 187 The corresponding MBeans will be created later, only 188 when you later 189 ask the <code><a 190 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 191 title="The ScanManagerMXBean is the main MBean of the scandir application" 192 >ScanManagerMXBean</a> </code> to apply the 193 configuration again.<br> 194 The <code>ScanDirConfigMXBean</code> is created by the 195 <code>ScanManagerMXBean</code>, when the 196 <code>ScanManagerMXBean</code> is registered. 197 It is also possible to create an alternate 198 <code>ScanDirConfigMXBean</code>, and to switch the 199 <code>ScanDirConfigMXBean</code> to use one or the other 200 configuration. 201 <br>An example of XML configuration file is given 202 <a href="src/etc/testconfig.xml" 203 title="An Example Of Configuration" 204 >here</a>. Although you could edit such a file by 205 hand, it is easier to do it programmatically (or 206 with <a href="#JConsole">JConsole</a>) through 207 the <code>ScanDirConfigMXBean</code> interface. 208 </li> 209 <li>The <a 210 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 211 title="The ResultLogManagerMXBean is in charge of managing result logs" 212 >ResultLogManagerMXBean</a> is in charge of managing result logs. 213 <br>Directory Scanners can be configured to log a 214 <a 215 href="dist/javadoc/com/sun/jmx/examples/scandir/config/ResultRecord.html" 216 title="A ResultRecord contains information about a file matching the criteria of a Directory Scanner" 217 >ResultRecord</a> whenever they take action upon a file that 218 matches their criteria. The <code>ResultLogManagerMXBean</code> is 219 responsible for logging these result records. 220 The <code>ResultLogManagerMXBean</code> can be configured to log 221 such records to a flat file, or into a log held in memory, or 222 both. Both logs (file and memory) can be configured with a 223 maximum capacity. 224 <br>When the maximum capacity of the memory 225 log is reached, its first entry (i.e. its oldest entry) is 226 removed to make place for the latest one. 227 <br>When the maximum 228 capacity of the file log is reached, the file is 229 renamed by appending a tilde '~' to its name and a 230 new result log is created. 231 <br>The <code>ResultLogManagerMXBean</code> 232 will let you interactively clear these result logs, change their 233 capacity, and decide where (memory or file) to log. 234 The memory log is useful in that its content can be interactively 235 returned by the <code>ResultLogManagerMXBean</code>, while 236 the file log doesn't have this facility.<br> 237 The result logs are intended to be used by e.g. an offline 238 program that would take some actions on the files that 239 matched the scan criteria: 240 <br>The <i>scandir</i> application 241 could be configured to only produce logs (i.e. takes no 242 action but logging the matching files), and the real 243 action could be performed by another program or module (e.g. mail the result log to the engineer who 244 maintains the lab, or parse that log and delete all the 245 files listed there, or parse the log and prepare and send 246 a single mail to each owner of matching files, containing 247 the list of files they should consider deleting).<br> 248 The <code>ResultLogManagerMXBean</code> is a singleton 249 MBean created by the <code><a 250 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 251 title="The ScanManagerMXBean is the main MBean of the scandir application" 252 >ScanManagerMXBean</a> </code> 253 which reads and writes its configuration from the 254 <code><a 255 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 256 title="The ScanDirConfigMXBean is in charge of the configuration" 257 >ScanDirConfigMXBean</a></code>. 258 </li> 259 </ul> 260 <p>An application <code>main()</code> method is 261 provided in the <a 262 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html" 263 >ScanDirAgent</a> class. The <code>main()</code> simply registers 264 a <code><a 265 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 266 title="The ScanManagerMXBean is the main MBean of the scandir application" 267 >ScanManagerMXBean</a> </code> in the platform MBeanServer, and 268 then waits for someone to call <code>close()</code> on the 269 <code>ScanManagerMXBean</code>. 270 </p> 271 <p>When the <code>ScanManagerMXBean</code> is registered, it 272 will create a default <code><a 273 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 274 title="The ScanDirConfigMXBean is in charge of the configuration" 275 >ScanDirConfigMXBean</a></code> bound 276 to a default XML config file. 277 </p> 278 <p>The application's default XML config file is determined as 279 follows: 280 <ol> 281 <li>If the property <code>scandir.config.file</code> is 282 defined, the default application file will be the 283 file pointed to by this property. If that file 284 doesn't exist, it will be created when 285 <code>ScanDirConfigMXBean.save()</code> is 286 invoked. 287 </li> 288 <li>Otherwise the application config file is 289 assumed to be a file called <code>jmx-scandir.xml</code>, 290 located in the user's directory (as defined by 291 the System property <code>user.home</code>). 292 If that file doesn't exists, it will be created when 293 <code>ScanDirConfigMXBean.save()</code> is 294 invoked. 295 </li> 296 </ol> 297 <p>It is worth noting that this project is defined to 298 run with the following properties: 299 <pre>-Djava.util.logging.config.file=logging.properties</pre> 300 <pre>-Dscandir.config.file=src/etc/testconfig.xml</pre> 301 With <code>ScanDirAgent</code> defined as the project's 302 main class. Hence when you invoke from the NetBeans IDE 303 <i>Run Project</i> on the <i>jmx-scandir</i> project, 304 or <i>Run file</i> on the <code>ScanDirAgent</code>, the 305 application starts with the test configuration provided in 306 <a href="src/etc/testconfig.xml" 307 title="An Example Of Configuration" 308 >src/etc/testconfig.xml</a> 309 </p> 310 </ul> 311 <h2><a name="h2-API-Doc">API Documentation and Sources</a></h2> 312 <ul> 313 <p>Once generated, the Javadoc of example classes can 314 be found starting from <a href="dist/javadoc/index.html" 315 title="The API Documentation" 316 ><code>dist/javadoc/index.html</code></a>.</p> 317 <p>You can view the sources in the <a 318 href="src" 319 title="The Example Source Tree" 320 ><code>src</code></a> subdirectory.</p> 321 </ul> 322 <h2><a name="h2-Patterns">Patterns, Best Practices, and Common Pitfalls</a></h2> 323 <ul> 324 <p>This section discusses some common patterns and 325 design choices that this example demonstrates, and some pitfalls that 326 it avoids. 327 </ul> 328 <h3>MBeans or MXBeans?</h3> 329 <ul> 330 <p>What is an MXBean? MXBeans made their appearance in 331 J2SE 5.0 (Tiger), with the Management and Monitoring 332 API of the JVM. However, Java SE 6 is the first 333 Java SE release that contains a standard framework which 334 makes it possible to create and register your own MXBeans. 335 </p> 336 <p>MXBeans are a special kind of MBean, which once registered 337 in the MBeanServer, get automatically transformed into 338 OpenMBeans. From a developer point of view, nothing changes: 339 A Wombat MBean can become an MXBean simply by renaming 340 its <code>WombatMBean</code> interface into <code>WombatMXBean</code>.</p> 341 <p>Using MXBeans rather than plain Standard MBean brings its 342 own advantages:</p> 343 <ul> 344 <li> 345 Generic tools, like JConsole, will be able to 346 display and interact with your MXBeans nicely, even 347 if your MXBean interfaces reference custom types 348 - e.g. custom Java enums. This is because all the types 349 exposed by your MXBeans are converted to Open Types. 350 Just look at the <a 351 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 352 title="The ScanDirConfigMXBean is in charge of the configuration" 353 >ScanDirConfigMXBean</a> with JConsole and you will 354 understand the benefits. 355 </li> 356 <li> 357 When writing a programmatic client, you can obtain 358 a proxy that implements the original MXBean interface, 359 and forget about the Open Type conversion. 360 The JUnit unit tests that come with this example 361 use this feature very widely. Have a look at them. 362 </li> 363 <li> 364 The MXBean framework also lets you nicely navigate 365 from one MXBean to another: your MXBeans can 366 have attributes and parameters which are proxies 367 to other MXBeans! We demonstrate this in the 368 <a 369 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 370 title="The ScanManagerMXBean is the main MBean of the scandir application" 371 >ScanManagerMXBean</a> which exposes a list 372 of <code><a 373 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 374 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 375 >DirectoryScannerMXBean</a></code> and points 376 towards a <code><a 377 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 378 title="The ScanDirConfigMXBean is in charge of the configuration" 379 >ScanDirConfigMXBean</a></code>. 380 </li> 381 </ul> 382 <p>In short, MXBeans are so much easier to use that 383 this example doesn't even have a single regular 384 Standard MBean. 385 </p> 386 <p>See also <a 387 href="http://weblogs.java.net/blog/emcmanus/archive/2006/02/what_is_an_mxbe.html" 388 title="What is an MXBean?" 389 >What is an MXBean?</a> 390 and <a 391 href="http://weblogs.java.net/blog/emcmanus/archive/2006/06/intermxbean_ref.html" 392 title="Inter-MXBean references" 393 >Inter-MXBean References</a>. 394 </p> 395 <blockquote><u>Hint:</u> In order to simplify the task of coding a 396 JMX programmatic client, we recommend that getters, setters, and 397 operations defined in MBean and MXBean interfaces throw 398 <code>IOException</code>. Proxy objects will then be able 399 to rethrow directly any <code>IOException</code> received from 400 their underlying MBean Server connection, without wrapping 401 them into <code>UndeclaredThrowableExceptions</code>.<br> 402 Since the life cycle of the proxy object is not directly tied to 403 the life cycle of the MBean it proxies, you may also want to 404 have all methods in the MBean or MXBean interface throw 405 <code>InstanceNotFoundException</code> or more generally 406 <code>JMException</code>. 407 </blockquote> 408 </ul> 409 <h3>MBean Names - aka ObjectNames</h3> 410 <ul> 411 <p>As you must know if you've been studying JMX, MBeans are 412 named objects. The names of MBeans are represented by 413 instances of <code>ObjectName</code>. An ObjectName is 414 composed of a <i>domain</i>, followed by a colon ':', 415 followed by a comma-separated list of <i>key=value</i> 416 pairs.<br> 417 The ordering of the <i>key=value</i> pairs is not 418 important, but <code>ObjectNames</code> are case sensitive 419 (both keys and values are case sensitive) and <b>white space 420 is not ignored</b>.<br> 421 A common pitfall for JMX beginners is to inadvertently 422 insert white space after commas into an ObjectName, 423 and expect that two ObjectNames which differ only by such white 424 space will be considered identical. This is not the 425 case.<br> 426 As an example, the ObjectName '<b><code>D:k1=v1, k2=v2, k3=v3</code></b>' has 427 three keys, which are '<b><code>k1</code></b>', '<b><code> k2</code></b>', 428 and '<b><code> k3</code></b>': beware 429 of the space in the name of the second and third 430 keys!<br> 431 It is therefore a different ObjectName from 432 '<b><code>D:k1=v1,k2=v2,k3=v3</code></b>' (the keys are now 433 '<b><code>k1</code></b>', '<b><code>k2</code></b>', and 434 '<b><code>k3</code></b>'), but the same ObjectName as 435 '<b><code>D: k2=v2, k3=v3,k1=v1</code></b>', and yet different 436 from '<b><code>D:k2=v2, k3=v3, k1=v1</code></b>'! 437 <p>In this example, we are following the rules 438 for ObjectName suggested in the <a 439 href="http://java.sun.com/products/JavaManagement/best-practices.html" 440 >JMX Best Practices</a>:</p> 441 <ul> 442 <li>ObjectNames should be <a 443 href="http://java.sun.com/products/JavaManagement/best-practices.html#mozTocId654884" 444 >predictable</a> 445 </li> 446 <li>The domain part of our ObjectNames starts with a Java 447 package name 448 </li> 449 <li>Our ObjectNames contain a <code>type=</code> 450 key property. This property is different for every 451 object type in our domain. 452 </li> 453 <li>For every ObjectName with a given type, we have the same set of key 454 properties with the same syntax and semantics for their values - in 455 fact we only use an additional <code>name=</code> key. 456 </li> 457 <li>When there can only be one instance of a given type 458 there aren't any other key properties than <code>type=</code>. 459 The ObjectNames of the <a 460 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 461 title="The ScanManagerMXBean is the main MBean of the scandir application" 462 >ScanManagerMXBean</a> and <a 463 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 464 title="The ResultLogManagerMXBean is in charge of managing result logs" 465 >ResultLogManagerMXBean</a>, which are both singleton MBeans, are 466 composed in this way. 467 </li> 468 <li>When there can be several instances of a given type, 469 we differentiate them by further key properties. 470 To achieve this, we are using the most usual key property 471 in addition to <code>type=</code>: the <code>name=</code> key. 472 In this example, a key property list of the form 473 <code>type=X,name=Y</code> is always enough to uniquely name 474 an MBean. Tools like jconsole are usually aware 475 of the semantics of the <code>type=</code> key and 476 <code>name=</code> key, and are therefore able to 477 display this form of name in a way that 478 is easier to read than other name forms. 479 </li> 480 </ul> 481 <p>The rules listed above are implemented by a couple 482 of static helper functions in the <a 483 href="src/com/sun/jmx/examples/scandir/ScanManager.java" 484 title="ScanManager.java" 485 >ScanManager</a> class. See the code of the 486 <b><code>makeSingletonName</code></b> and 487 <b><code>makeMBeanName</code></b> methods. 488 </p> 489 </ul> 490 <h3>Inter MBean Navigation</h3> 491 <ul> 492 <p>One of the most common problems that needs to be solved 493 when designing a management interface with JMX is to 494 choose a representation for inter-MBean relationships.<br> 495 Prior to Java 6, there were basically three possible 496 choices:</p> 497 <ul> 498 <li><b>Make the relation appear in the ObjectName</b>. 499 For instance, if MBean B was contained in 500 MBean A, you could choose to name MBean B so 501 that its parent relationship with MBean A 502 appeared in its name. <br> 503 The obvious limitation of this solution is that 504 it only allows to model one such relation (an 505 MBean has only one name) and the relation must 506 be fixed - it cannot change during the life of 507 the MBean since the name of an MBean cannot 508 change.<br> 509 This scheme is therefore mostly used when 510 the application MBeans are modeling objects 511 which are conceptually contained within 512 each other in a tree-like structure. 513 <br>For instance, most MBean names defined by 514 <a href="http://jcp.org/en/jsr/detail?id=77" 515 >J2EE Management (JSR 77)</a> follow 516 this scheme. 517 </li> 518 <li><b>Design getters and setters (or operations) which 519 return <code>ObjectName</code> or 520 <code>ObjectName[]</code> values</b>. The ObjectNames 521 point to the MBeans which are related to that 522 object. For instance , <a 523 href="http://glassfish.dev.java.net/" 524 title="Open Source Java EE 5 Application Server" 525 >GlassFish</a> 526 defines MBeans which also use this pattern. 527 </li> 528 <li><b>Use the JMX RelationService</b>. The JMX RelationService 529 is quite powerful, but simple relationships often 530 do not justify that overhead. 531 </li> 532 </ul> 533 <p>In Java 6, these three possibilities still remain, but 534 the new MXBean framework brings up an interesting 535 alternative. Instead of returning an ObjectName or 536 an ObjectName array, <b>an MXBean can return a proxy</b> 537 to its related MXBeans. This is how we have chosen to 538 implement our inter MBean relationships in this 539 example: 540 <br>For instance the 541 <code>ScanManagerMXBean</code>/<code>DirectoryScannerMXBean</code> 542 relationship and the 543 <code>ScanManagerMXBean</code>/<code>ScanDirConfigMXBean</code> 544 relationships are implemented in this way. 545 <p> 546 The additional benefit, as compared to returning ObjectNames or 547 using the RelationService is that interface type of the MBeans 548 which are pointed to by the relationship becomes directly 549 apparent. The method: 550 <pre> 551 public Map<String,DirectoryScannerMXBean> getDirectoryScanners(); 552 </pre> 553 makes it immediately obvious that the MBeans to which we point are 554 <a 555 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 556 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 557 >DirectoryScannerMXBeans</a>. It would have been much less obvious in prior 558 versions of Java SE, were the returned type would have had to be 559 <code>Map<String,ObjectName></code>, or 560 even worse just <code>Map</code>. 561 </p> 562 <p>However, it must be clear that the behaviour will be 563 quite different when an MXBean is returned as compared 564 to when a simple bean is returned. 565 </p> 566 <p>When an MXBean is returned, the remote client sees either 567 an ObjectName, if it is a generic client like jconsole, or 568 a proxy to a remote MXBean, if the client is working with the 569 MXBean interface. Invoking an operation on one of the 570 proxy returned by a method such as 571 <code>getDirectoryScanners</code> will cause the 572 MBean to be invoked on the remote server side. 573 </p> 574 <p>If <code>getDirectoryScanners</code> were 575 defined as: 576 <pre> 577 public Map<String,DirectoryScannerConfig> getDirectoryScanners(); 578 </pre> 579 then invoking a method on one of the returned objects 580 would have absolutely no effect on the remote 581 server side - because the returned objects in this 582 case would simply be a bunch of serialized data objects. 583 </p> 584 <p>It is worth noting that although an MXBean interface 585 can have getters and operations which return an MXBean 586 interface, a regular standard MBean shouldn't have 587 any getters or methods which return MBean interfaces or 588 MXBean interfaces. 589 </p> 590 <p>For more information see also <a 591 href="http://weblogs.java.net/blog/emcmanus/archive/2006/06/intermxbean_ref.html" 592 title="Inter-MXBean references" 593 >Inter-MXBean References</a>. 594 </p> 595 </ul> 596 <h3>The MBeanRegistration interface, or how an MBean can 597 know or provide its own name</h3> 598 <ul> 599 <p> 600 Sometimes, an MBean needs to have a reference to the 601 MBeanServer in which it is registered, or needs to know 602 with which ObjectName it has been registered. 603 </p> 604 <p> 605 Sometimes also, an MBean may need to perform some 606 checks before being registered, or will need 607 to carry out some actions right after it has been 608 successfully registered in the MBeanServer. 609 </p> 610 <p> 611 Sometimes again, an MBean may need to perform some 612 checks, or some cleaning actions, just before, or 613 just after, it is unregistered. 614 </p> 615 <p> 616 When an MBean has such needs, the easiest solution 617 for it is to implement the <code>MBeanRegistration</code> 618 interface. 619 </p> 620 <p>The <code>MBeanRegistration</code> interface is a callback 621 interface which defines pre and post registration and 622 unregistration callbacks. 623 </p> 624 <p> 625 When an MBean implementing this interface is created 626 (with <code>createMBean</code>) or registered 627 (with <code>registerMBean</code>) in an MBeanServer, 628 the MBeanServer will call the <code>preRegister</code> 629 and <code>postRegister</code> method implemented by 630 the MBean. The <code>preRegister</code> method 631 has an <code>MBeanServer</code> and <code>ObjectName</code> 632 parameter, which are passed by the MBeanServer to the 633 MBean. The MBean can store the reference it is being passed 634 in a private instance variable for later use. 635 </p> 636 <p> 637 Most of the MXBeans we have defined in this example 638 implement the <code>MBeanRegistration</code> interface. The table 639 below show how our MBeans use this interface to control 640 their own names, make sanity checks, perform 641 initialization steps or cleanup actions. 642 </p> 643 <p><br><center> 644 <table border="1" cellpadding="4" cellspacing="2" 645 bgcolor="#eeeeee" width="95%"> 646 <thead> 647 <tr bgcolor="#cecece"> 648 <th width="20%">MBean Requirement</th> 649 <th>callback</th> 650 <th>use case example</th> 651 </tr> 652 </thead> 653 <tbody> 654 <tr> 655 <td bgcolor="#dedede">get a reference to the MBeanServer</td> 656 <td><code>preRegister</code></td> 657 <td bgcolor="#fafafa">The <a 658 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 659 title="The ScanManagerMXBean is the main MBean of the scandir application" 660 >ScanManagerMXBean</a> needs a reference 661 to the MBeanServer in order to create and 662 register other MBeans, such as the 663 <a 664 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 665 title="The ResultLogManagerMXBean is in charge of managing result logs" 666 >ResultLogManagerMXBean</a>, and the 667 <a 668 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 669 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 670 >DirectoryScannerMXBeans</a>. 671 </td> 672 </tr> 673 <tr> 674 <td bgcolor="#dedede">reject registration if conditions are 675 not met. 676 </td> 677 <td><code>preRegister</code></td> 678 <td bgcolor="#fafafa">The <a 679 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 680 title="The ScanManagerMXBean is the main MBean of the scandir application" 681 >ScanManagerMXBean</a> will throw 682 an IllegalArgumentException in <code>preRegister</code> 683 if the ObjectName it is being passed is 684 illegal. Throwing an exception in 685 <code>preRegister</code> makes the registration fail. 686 </td> 687 </tr> 688 <tr> 689 <td bgcolor="#dedede">get my client-assigned MBean name</td> 690 <td><code>preRegister</code></td> 691 <td bgcolor="#fafafa">The <a 692 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 693 title="The ScanDirConfigMXBean is in charge of the configuration" 694 >ScanDirConfigMXBean</a> propagates the 695 value of the <code>name=</code> property of 696 the ObjectName it is given into its 697 ScanManagerConfig bean. 698 </td> 699 </tr> 700 <tr> 701 <td bgcolor="#dedede">provide my own default ObjectName if none 702 was given to the MBeanServer 703 </td> 704 <td><code>preRegister</code></td> 705 <td bgcolor="#fafafa">The name that is returned by <code>preRegister</code> 706 is the ObjectName with which the MBean will be 707 eventually registered. 708 The <a 709 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 710 title="The ScanDirConfigMXBean is in charge of the configuration" 711 >ScanDirConfigMXBean</a> is able to suggest 712 a value for its own ObjectName if none was 713 provided. Similarly, the <a 714 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 715 title="The ScanManagerMXBean is the main MBean of the scandir application" 716 >ScanManagerMXBean</a> 717 always returns its singleton ObjectName 718 defined by <a 719 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html#SCAN_MANAGER_NAME" 720 title="The ScanManagerMXBean is the main MBean of the scandir application" 721 >ScanManagerMXBean.SCAN_MANAGER_NAME</a>. 722 </td> 723 </tr> 724 <tr> 725 <td bgcolor="#dedede">perform initialization steps</td> 726 <td><code>preRegister</code></td> 727 <td bgcolor="#fafafa">The <a 728 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 729 title="The ScanDirConfigMXBean is in charge of the configuration" 730 >ScanDirConfigMXBean</a> uses <code>preRegister</code> 731 to initialize its internal ScanManagerConfig bean. 732 </td> 733 </tr> 734 <tr> 735 <td bgcolor="#dedede">perform initialization steps, once it is 736 known that the registration was successful. 737 </td> 738 <td><code>postRegister</code></td> 739 <td bgcolor="#fafafa">The <code>postRegister</code> method 740 can be used to implement 741 initialization steps that need to be done once it 742 is known that the registration was successful, or to 743 undo any action performed by <code>preRegister</code> once it 744 is known that registration was not successful. 745 The <code>postRegister</code> method has a Boolean parameter 746 which tells the MBean whether it was or wasn't 747 successfully registered in the MBeanServer. 748 The <a 749 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 750 title="The ScanManagerMXBean is the main MBean of the scandir application" 751 >ScanManagerMXBean</a> uses <code>postRegister</code> to create 752 and register other MBeans, such as the 753 <a 754 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 755 title="The ResultLogManagerMXBean is in charge of managing result logs" 756 >ResultLogManagerMXBean</a> and the default 757 <a 758 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 759 title="The ScanDirConfigMXBean is in charge of the configuration" 760 >ScanDirConfigMXBean</a>. 761 Note that <code>postRegister</code> is not expected to throw any 762 exception. If an exception needs to be thrown, it should 763 be thrown in <code>preRegister</code>. 764 </td> 765 </tr> 766 <tr> 767 <td bgcolor="#dedede">check whether the MBean can be deregistered</td> 768 <td><code>preDeregister</code></td> 769 <td bgcolor="#fafafa">The <a 770 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 771 title="The ScanManagerMXBean is the main MBean of the scandir application" 772 >ScanManagerMXBean</a> uses this method to verify 773 that its state allows it to be deregistered. 774 In particular, it will refuse to be deregistered 775 if it is in the RUNNING or SCHEDULED state. 776 If <code>preDeregister</code> throws an exception, the unregisterMBean 777 call will fail and the MBean will remain registered in 778 the MBeanServer. 779 Take particular care when implementing business logic 780 in this method: if the logic you implement has an 781 unfortunate bug which makes it always throw an 782 exception, you will never be able to unregister 783 that MBean. 784 </td> 785 </tr> 786 <tr> 787 <td bgcolor="#dedede">clean up resources, refusing to be deregistered if 788 it fails 789 </td> 790 <td><code>preDeregister</code></td> 791 <td bgcolor="#fafafa">The <a 792 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 793 title="The ScanManagerMXBean is the main MBean of the scandir application" 794 >ScanManagerMXBean</a> uses this method to unregister 795 all the other MBeans it has created and registered in the 796 MBeanServer. This includes the <a 797 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 798 title="The ResultLogManagerMXBean is in charge of managing result logs" 799 >ResultLogManagerMXBean</a>, the 800 <a 801 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 802 title="The ScanDirConfigMXBean is in charge of the configuration" 803 >ScanDirConfigMXBeans</a> it has created, and the 804 <a 805 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 806 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 807 >DirectoryScannerMXBeans</a> it has created when 808 applying its configuration. 809 </td> 810 </tr> 811 <tr> 812 <td bgcolor="#dedede">clean up resources which need to be released in 813 a best-effort way, when it is known that the MBean is no 814 longer registered. 815 </td> 816 <td><code>postDeregister</code></td> 817 <td bgcolor="#fafafa"><code>postDeregister</code> is only called if the MBean was succesfully 818 unregistered. 819 The <a 820 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 821 title="The ScanManagerMXBean is the main MBean of the scandir application" 822 >ScanManagerMXBean</a> uses this method to cancel 823 its internal java.util.Timer. 824 </td> 825 </tr> 826 </tbody> 827 </table> 828 </center><br></p> 829 </ul> 830 <h3>The Singleton MBean Pattern</h3> 831 <ul> 832 <p> 833 A singleton MBean is an MBean which can only have one 834 instance registered in a given MBeanServer. <br> 835 A singleton MBean usually has a well-known name, 836 which can be defined as a constant. In that case, 837 clients no longer need to call <code>new ObjectName(...)</code> 838 and catch the declared <code>MalformedObjectNameException</code>. 839 </p> 840 <p>There are already quite a few examples of singleton 841 MBeans in the java.lang.management API. The 842 ThreadingMXBean, ClassLoadingMXBean, RuntimeMXBean, etc. 843 are all singleton MBeans. 844 </p> 845 <p>In this example, we have two singleton MBeans: 846 The <code><a 847 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 848 title="The ScanManagerMXBean is the main MBean of the scandir application" 849 >ScanManagerMXBean</a></code> and the 850 <code><a 851 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 852 title="The ResultLogManagerMXBean is in charge of managing result logs" 853 >ResultLogManagerMXBean</a></code>. But in fact, 854 the only real singleton MBean is the 855 <code>ScanManagerMXBean</code>. The 856 <code>ResultLogManagerMXBean</code> just happens to 857 be a singleton MBean because it has a 1-1 relationship 858 with the <code>ScanManagerMXBean</code>. 859 </p> 860 <p>The <code>ScanManagerMXBean</code> implements the 861 singleton MBean pattern in this way: 862 </p> 863 <ul> 864 <li>The <code>ScanManagerMXBean</code> name has a single 865 key property: <code>type=ScanManagerMXBean</code>.</li> 866 <li>Its name is defined by an ObjectName constant called 867 <code>SCAN_MANAGER_NAME</code> in the <code>ScanManager</code> class</li> 868 <li>The <code>ScanManagerMXBean</code> enforces its status of 869 singleton MBean. It will refuse to be registered 870 with a name other than 871 the <code>SCAN_MANAGER_NAME</code>. You can therefore depend on 872 the fact that the <code>ScanManagerMXBean</code> will always 873 be registered with its singleton <code>SCAN_MANAGER_NAME</code> 874 (see <code>preRegister</code>) 875 </li> 876 <li>You are not obliged to provide a name when you 877 register the <code>ScanManagerMXBean</code>: if you pass null, 878 then the <code>ScanManager</code> will be registered with 879 its singleton <code>SCAN_MANAGER_NAME</code> 880 (see <code>preRegister</code>). 881 </li> 882 <li>The <code>ScanManager</code> class has a no-arg static 883 <code>register</code> method that will register 884 the singleton instance in the Platform MBeanServer. 885 This static <code>register</code> method returns 886 a proxy to the registered singleton. 887 </li> 888 <li>The <code>ScanManager</code> class has also a static 889 <code>register</code> method that will create 890 a singleton instance in a (possibly remote) 891 MBeanServerConnection - using 892 <code>createMBean</code>. 893 This static <code>register</code> method 894 also returns a proxy to the registered singleton. 895 </li> 896 <li>Only the MBeanServer has a reference to the 897 singleton instance. The singleton instance is 898 not returned to the caller, and not kept 899 in any other static data structure. 900 </li> 901 </ul> 902 <p> 903 On the other hand, the <code><a 904 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 905 title="The ResultLogManagerMXBean is in charge of managing result logs" 906 >ResultLogManagerMXBean</a></code> 907 has a much more relaxed implementation of the pattern: 908 <br>It simply provides its own singleton name if it is 909 registered with a null ObjectName, but will not enforce 910 the use of that name. 911 </p> 912 <p>Note that all singleton MBean names in this example 913 are created using the <code>ScanManager.makeSingletonName</code> 914 method, which implements the pattern for ObjectNames suggested 915 in the JMX Best Practices. 916 </p> 917 </ul> 918 <h3>Managing the Life Cycle of dependent MBeans</h3> 919 <ul> 920 <p>A common task that many JMX applications have 921 is to manage the life cycle of MBeans registered 922 in the MBeanServer.</p> 923 <p>In this example, we have decided to follow a simple 924 pattern:</p> 925 <ul> 926 <li>The application is initialized simply 927 by registering the singleton 928 <a 929 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 930 title="The ScanManagerMXBean is the main MBean of the scandir application" 931 >ScanManagerMXBean</a> in 932 the MBeanServer. 933 </li> 934 <li>The <code>ScanManagerMXBean</code> will then 935 in turn register any other MBean that the 936 application might need: 937 <ul> 938 <li>It creates and registers the singleton 939 <code><a 940 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 941 title="The ResultLogManagerMXBean is in charge of managing result logs" 942 >ResultLogManagerMXBean</a></code> 943 </li> 944 <li>It creates and registers the default 945 <code><a 946 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 947 title="The ScanDirConfigMXBean is in charge of the configuration" 948 >ScanDirConfigMXBean</a></code> 949 which loads the initial configuration 950 </li> 951 <li>It creates as many 952 <code><a 953 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 954 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 955 >DirectoryScannerMXBeans</a></code> as 956 needed when the configuration is applied 957 </li> 958 <li>It lets you create alternate 959 <code>ScanDirConfigMXBean</code>, to 960 which you can later switch in order 961 to apply a new alternate configuration. 962 </li> 963 </ul> 964 </li> 965 <li>When a new configuration is applied (or if the 966 current configuration is reapplied), the 967 <code>ScanManagerMXBean</code> will unregister 968 any <code>DirectoryScannerMXBeans</code> it has 969 previously registered, and will re-create 970 brand new <code>DirectoryScannerMXBeans</code> 971 from the applied configuration. 972 </li> 973 <li>When you unregister the <code>ScanManagerMXBean</code>, 974 it does all the cleanup for you, by unregistering 975 all the MBeans that it has created during the 976 course of the application. 977 </li> 978 </ul> 979 <p>The <code>ScanManagerMXBean</code> makes use of its 980 <code>MBeanRegistration</code> interface in order 981 to register the other MBeans it needs (see the 982 <code>ScanManager.postRegister</code> method) and to unregister 983 every MBean it has created (see the <code>ScanManager.preDeregister</code> 984 method). 985 </p> 986 <p>You will note that the <code>ScanManagerMXBean</code> 987 will only allow itself to be deregistered if it can be 988 closed - that is if there's no other action in 989 progress. 990 This is to make sure that the deregistration of 991 dependent MBeans will work smoothly. 992 <br> 993 The deregistration of related MBeans will happen 994 in the <code>ScanManager.preDeregister</code> 995 method. 996 <br> 997 If one of these MBeans could not be deregistered, 998 then the <code>ScanManagerMXBean</code> will throw 999 an exception, refusing to be deregistered. 1000 <br>This leaves you a chance to try to deregister it 1001 again later. Since the <code>ScanManagerMXBean</code> 1002 has switched its state to CLOSED before starting 1003 to unregister its dependent MBeans, it will refuse 1004 any further actions, ensuring that e.g. nobody 1005 can try to start it or schedule it while it 1006 is in that partially-deregistered state. 1007 </p> 1008 <p>Handling the LifeCycle of all the application's 1009 MBeans in a single MBean is usually a good design 1010 pattern, especially if the application is a 1011 module which is intended to share a JVM - or 1012 an MBeanServer - with other modules. 1013 </p> 1014 <p>This is specially useful if the application needs to 1015 be loaded and unloaded on demand: in that 1016 case, simply registering or unregistering the top level 1017 MBean (in our example the <code>ScanManagerMXBean</code>) does 1018 the trick. 1019 </p> 1020 </ul> 1021 <h3>Emitting Notifications</h3> 1022 <ul> 1023 <p>In order to emit notifications, an MBean must be 1024 an instance of <code>NotificationEmitter</code>. 1025 The <code>NotificationEmitter</code> interface defines methods 1026 that the MBeanServer will call on the MBean in order 1027 to register <code>NotificationListeners</code> with the MBean. 1028 </p> 1029 <p>It is worth noting that the MBean may not be 1030 invoked each time a JMX client wants to register 1031 a listener. For instance, the RMIConnectorServer 1032 registers <i>only once</i> a single listener with each MBean 1033 which is a <code>NotificationEmitter</code>. 1034 In that specific case, the listener may even be registered 1035 with the MBean before any client has actually subscribed 1036 for notifications from that particular MBean. 1037 </p> 1038 <p>An MBean can therefore make no assumption about 1039 which client or how many clients have registered for 1040 notifications. 1041 </p> 1042 <p>It is also worth noting that the logic of the 1043 methods defined in <code>NotificationEmitter</code> would not 1044 be trivial to implement from scratch. Fortunately 1045 the JMX API defines a helper class, called 1046 <code>NotificationBroadcasterSupport</code>, which 1047 provides an implementation for these methods. 1048 </p> 1049 <p>There are actually three ways for an MBean to 1050 implement <code>NotificationEmitter</code>, of which only two 1051 are recommended. 1052 </p> 1053 </ul> 1054 1055 <h4>Extending NotificationBroadcasterSupport</h4> 1056 <ul> 1057 <p>This is the simplest way of coding an MBean which 1058 is a <code>NotificationEmitter</code>: 1059 </p> 1060 <p>Simply extend <code>NotificationBroadcasterSupport</code>, 1061 then override its <code>getNotificationInfo</code> method 1062 which returns the <code>MBeanNotificationInfo[]</code> array 1063 that should be included in your MBean's <code>MBeanInfo</code> 1064 and that's it. 1065 <br>You just need to call the <code>sendNotification</code> method 1066 inherited from <code>NotificationBroadcasterSupport</code> whenever 1067 your MBean needs to send a notification. 1068 </p> 1069 <p>In our example, both the <a 1070 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 1071 title="The ScanDirConfigMXBean is in charge of the configuration" 1072 >ScanDirConfigMXBean</a> and <a 1073 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 1074 title="The ResultLogManagerMXBean is in charge of managing result logs" 1075 >ResultLogManagerMXBean</a> extend 1076 <code>NotificationBroadcasterSupport</code> in order 1077 to send notifications. 1078 </p> 1079 </ul> 1080 <h4>The Delegation Pattern: delegating to a 1081 NotificationBroadcasterSupport delegate</h4> 1082 <ul> 1083 <p>There may be cases however where delegating to a 1084 wrapped <code>NotificationBroadcasterSupport</code> 1085 object may be preferred to extending 1086 <code>NotificationBroadcasterSupport</code>. 1087 </p> 1088 <p>For instance, if your MBeans already derive from 1089 some base class, extending <code>NotificationBroadcasterSupport</code> 1090 might not be an option. 1091 </p> 1092 <p>Similarly, if you do not want to have the inherited 1093 <code>public void sendNotification(Notification notification)</code> 1094 method appear in the Javadoc of the concrete class of your 1095 MBean, you may want to consider using the delegation 1096 pattern instead of extending 1097 <code>NotificationBroadcasterSupport</code> 1098 </p> 1099 <p>In our example both the <a 1100 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 1101 title="The ScanManagerMXBean is the main MBean of the scandir application" 1102 >ScanManagerMXBean</a> and the <a 1103 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 1104 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 1105 >DirectoryScannerMXBean</a> use the delegation 1106 pattern rather than extending 1107 <code>NotificationBroadcasterSupport</code>. 1108 In the end, choosing between one or the other method 1109 is more a question of taste, although the delegation 1110 pattern could be considered more flexible since it 1111 doesn't require extending any given superclass. 1112 </p> 1113 <p>It may be also worth noting that some tools like 1114 the JMX Module of <a 1115 href="http://www.netbeans.org" 1116 >NetBeans IDE</a>, will be able to 1117 generate for you all the code that delegates to a 1118 wrapped <code>NotificationBroadcasterSupport</code>. 1119 </p> 1120 </ul> 1121 1122 <h4>Implementing NotificationEmitter from scratch</h4> 1123 <ul> 1124 <p>This is the last possibility for an MBean that 1125 needs to send notifications: simply implement 1126 <code>NotificationEmitter</code> from scratch. This is highly 1127 discouraged since that logic is not trivial, and 1128 already provided by 1129 <code>NotificationBroadcasterSupport</code> anyway. 1130 </p> 1131 </ul> 1132 1133 <h4>Beware of Synchronization Locks</h4> 1134 <ul> 1135 1136 <p>One thing you must keep in mind when sending 1137 notifications is not to send them from within 1138 a synchronized block, or while holding a lock on 1139 some resource.</p> 1140 <p>Indeed, what happens when you send a notification 1141 may vary greatly depending on whether the client 1142 which has registered for notifications has done 1143 so through a <code>JMXConnector</code> (like the 1144 <code>JMXRMIConnector</code>) 1145 or through a direct reference to the MBeanServer 1146 (by calling 1147 <code>MBeanServer.addNotificationListener</code>). 1148 </p> 1149 <p>In this latter case, the listener will be invoked 1150 synchronously in the same thread that your MBean is 1151 using to send its notification. If by misfortune, the 1152 code of that listener now re-enters your MBean through a 1153 call that flows through a JMXConnector, a deadlock 1154 could occur. It is therefore very important to release 1155 any lock you may have before calling 1156 <code>sendNotification</code>.</p> 1157 <p>An easy way to do that is demonstrated in the 1158 <code>ScanManager</code> class. The ScanManager 1159 has an internal private queue of pending notifications. 1160 When a notification needs to be sent (e.g. because the 1161 ScanManager state is being switched), the notification 1162 is simply prepared and put into the pending notification 1163 queue. 1164 The notification queue is then processed later on, 1165 at the end of the method, when the processing is finally 1166 completed and all the locks have been released. 1167 <br>At this point the notification queue might already 1168 have been emptied by another thread - in which case 1169 the pending notifications will have already been 1170 removed from the queue. Which thread actually gets 1171 to send the notifications is of no importance. The 1172 important point is that all the locks detained by 1173 your MBean code in that thread were released before 1174 the notification was sent. 1175 </p> 1176 <p>In our example the <code>ScanManager</code> class 1177 ensures this by: 1178 <ul> 1179 <li>Only calling <code>sendNotification</code> 1180 in its private <code>sendQueuedNotifications</code> 1181 method. 1182 </li> 1183 <li>Only calling <code>sendQueuedNotifications</code> 1184 when all locks have been released. 1185 </li> 1186 <li>Never calling a method that calls 1187 <code>sendQueuedNotifications</code> from within 1188 a synchronized block.</li> 1189 </ul> 1190 </p> 1191 </ul> 1192 1193 1194 1195 <h4>Don't subclass Notification</h4> 1196 <ul> 1197 <p>Another common best practice when you want 1198 to improve interoperability is to use directly 1199 the Notification base classes provided in the 1200 JMX<sup>TM</sup> API. Do not create your own 1201 subclasses of these standard classes. 1202 </p> 1203 <p>Indeed, if you code your own subclass, a generic 1204 client, like jconsole, will not be able to receive 1205 that notification unless it has that custom 1206 subclass in its classpath. 1207 </p> 1208 <p> 1209 If you want your application to be interoperable, it is 1210 therefore preferable not to subclass any of the standard 1211 Notification classes. You can define your own 1212 Notification type string, and if you need to send 1213 additional data, you can put a CompositeData, or a 1214 HashMap of serializable standard types in the 1215 Notification's user data fields. 1216 </p> 1217 <p>In this example, we are using directly the 1218 standard notification classes: 1219 <ul> 1220 <li>The <a 1221 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 1222 title="The ScanManagerMXBean is the main MBean of the scandir application" 1223 >ScanManagerMXBean</a> and the <a 1224 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 1225 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 1226 >DirectoryScannerMXBean</a> both use directly 1227 <code>AttributeChangeNotification</code> to notify 1228 changes in their <code>State</code> attribute. 1229 </li> 1230 <li>The <a 1231 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 1232 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 1233 >DirectoryScannerMXBean</a> 1234 also uses the base <code>Notification</code> 1235 class directly in order to notify whenever 1236 it finds a matching file. 1237 <br>In that case, we simply use the base 1238 <code>Notification</code> 1239 class with a new 1240 <b><code>com.sun.jmx.examples.scandir.filematch</code></b> 1241 type. 1242 </li> 1243 <li>The <a 1244 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 1245 title="The ScanDirConfigMXBean is in charge of the configuration" 1246 >ScanDirConfigMXBean</a> and <a 1247 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 1248 title="The ResultLogManagerMXBean is in charge of managing result logs" 1249 >ResultLogManagerMXBean</a> also both use the base 1250 <code>Notification</code> class. 1251 </li> 1252 </ul> 1253 <p>Careful readers will have noted that the <a 1254 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 1255 title="The ScanManagerMXBean is the main MBean of the scandir application" 1256 >ScanManagerMXBean</a> and the <a 1257 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 1258 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." 1259 >DirectoryScannerMXBean</a> both use the 1260 <code>AttributeChangeNotification</code> class 1261 to notify about their state change, whereas the 1262 <a 1263 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 1264 title="The ScanDirConfigMXBean is in charge of the configuration" 1265 >ScanDirConfigMXBean</a> uses the base 1266 <code>Notification</code> class. 1267 </p> 1268 <p>In fact, this is because the semantics of these 1269 notifications is not exactly the same - although 1270 both denote a state change: 1271 <ul> 1272 <p>In the case of <code>ScanManagerMXBean</code> 1273 and <code>DirectoryScannerMXBean</code>, the 1274 notification which is emitted is more about a 1275 state transition, from one state to another. 1276 For instance, going from <code>RUNNING</code> 1277 to <code>STOPPED</code>, or from 1278 <code>SCHEDULED</code> to <code>STOPPED</code>. 1279 <br>In that case, the 1280 <code>AttributeChangeNotification</code> was 1281 more appropriate because it made it possible 1282 to send the previous and the new value of the 1283 state attribute, thus reflecting the whole 1284 state transition. 1285 </p> 1286 <p>In the case of the <code>ScanDirConfigMXBean</code> 1287 however, what is of interest is the state in 1288 which the MBean has arrived. Using the base 1289 <code>Notification</code> class with three different 1290 notification type strings - 1291 <b><code>com.sun.jmx.examples.scandir.config.loaded</code></b>, 1292 <b><code>com.sun.jmx.examples.scandir.config.modified</code></b>, 1293 and 1294 <b><code>com.sun.jmx.examples.scandir.config.saved</code></b> - 1295 was therefore closer to what we wanted to model. 1296 </p> 1297 </ul> 1298 </p> 1299 </ul> 1300 1301 <h3>Configuration MBeans</h3> 1302 <ul> 1303 <p>A common practice when designing a management application is 1304 to have an MBean, or a set of MBeans, dedicated to configuration. 1305 Separating configuration from control and monitoring allows 1306 more appropriate logic, and often simplifies the design and 1307 implementation of the management interface. 1308 </p> 1309 <p> 1310 In our example, the <a 1311 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 1312 title="The ScanDirConfigMXBean is in charge of the configuration" 1313 >ScanDirConfigMXBean</a> is dedicated to the application configuration. 1314 </p> 1315 <p>The <code>ScanDirConfigMXBean</code> will let you interactively 1316 modify, save, or load the application configuration. The modifications 1317 will not be taken into account until it is applied, by invoking 1318 <code>applyConfiguration</code> on the <a 1319 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 1320 title="The ScanManagerMXBean is the main MBean of the scandir application" 1321 >ScanManagerMXBean</a>. 1322 It is also possible to create many configurations, by creating as 1323 many <code>ScanDirConfigMXBean</code>s, and then to choose and apply 1324 one of these configurations by calling 1325 <code>ScanManagerMXBean.setConfigurationMBean</code> and then 1326 <code>ScanManagerMXBean.applyConfiguration</code>. 1327 </p> 1328 <p>In this way, all configurations aspects are gathered and concentrated 1329 inside the <code>ScanDirConfigMXBean</code> instead of being scattered 1330 throughout all the MBeans that compose the application. 1331 </p> 1332 <p>In order to save and store the application configuration data, the 1333 <code>ScanDirConfigMXBean</code> uses a set of XML serializable Java beans 1334 defined in the <a 1335 href="dist/javadoc/com/sun/jmx/examples/scandir/config/package-summary.html" 1336 title="The com.sun.jmx.examples.scandir.config package defines XML serializable beans" 1337 >com.sun.jmx.examples.scandir.config</a> package. These beans are very 1338 simple Java beans which have been lightly annotated for XML binding. 1339 </p> 1340 <p>It is worth noting that these same beans can also be handled by the 1341 MXBean framework (our beans don't contain recursive data structures) and can 1342 therefore be used directly as attributes and parameters of MXBeans, without 1343 needing to be Java-serializable (the MXBean framework transform them in 1344 CompositeData objects - which <b>are</b> serializable). 1345 </p> 1346 <p>The same <a 1347 href="dist/javadoc/com/sun/jmx/examples/scandir/config/ScanManagerConfig.html" 1348 title="The com.sun.jmx.examples.scandir.config package defines XML serializable beans" 1349 >ScanManagerConfig</a> bean that we use to read from and write to the 1350 XML configuration file is thus also used as attribute of the <a 1351 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 1352 title="The ScanDirConfigMXBean is in charge of the configuration" 1353 >ScanDirConfigMXBean</a>. It is transformed into a <code>CompositeData</code> 1354 by the MXBean framework, and can be easily introspected with 1355 <a href="#JConsole">jconsole</a>. 1356 </p> 1357 </ul> 1358 <h3>MBeans Must Be Thread-Safe</h3> 1359 <ul> 1360 <p>A question often asked by newcomers to JMX technology 1361 is whether the MBeanServer is thread-safe. Well, the MBeanServer <b>is</b> 1362 thread safe, but it doesn't put any locks on the MBeans it contains. The 1363 MBeans can be concurrently accessed by multiple threads, and must therefore 1364 take care of their own thread safety. 1365 </p> 1366 <p>In this example, we have been using two methods to ensure thread 1367 safety for our MBeans: synchronized blocks, and semaphores. 1368 </p> 1369 <p>Using synchronized blocks is probably the most common and easiest way 1370 to implement thread safety in Java. When dealing with MBeans though, here 1371 are a couple of rules to keep in mind: 1372 <ul> 1373 <li>Don't send notifications from within a synchronized block: there's 1374 no way to tell whether the listener's code will be executed in the 1375 same thread or a different thread, and holding a lock in these 1376 conditions is therefore dangerous, as it could lead to deadlocks.</li> 1377 <li>Also avoid invoking another MBean from a synchronized block 1378 unless you are completely in control of both MBeans, and you can 1379 ascertain that it won't lead to any deadlock. Indeed, if you invoke an 1380 MBean exposed by another application, it can be sometime hard to 1381 know with certainty whether holding a lock while invoking that 1382 MBean will have any side effect. Maybe that MBean will make 1383 further calls to other MBeans which will in turn try to call 1384 your MBean, or maybe it will emit a 1385 notification, and we'll be back to the considerations just 1386 above.</li> 1387 </ul> 1388 </p> 1389 <p>Another means of implementing thread-safe code is to use semaphores. 1390 The <a 1391 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 1392 title="The ScanManagerMXBean is the main MBean of the scandir application" 1393 >ScanManagerMXBean</a> uses a semaphore called 1394 <code>sequencer</code> to ensure 1395 that critical code sections are not executed concurrently. In this 1396 MBean, we use <code>Semaphore.tryAcquire</code> to lock the sequencer 1397 semaphore before entering the critical section. If the 1398 <code>Semaphore.tryAcquire</code> returns true then we enter the critical 1399 section. If it returns false, we throw an IllegalStateException, stating 1400 that we couldn't acquire the lock. The code looks like this: 1401 <pre> 1402 if (!sequencer.tryAcquire()) 1403 throw new IllegalStateException("resource locked"); 1404 try { 1405 // critical code here ... 1406 } finally { 1407 // Always use try/finally to ensure that the semaphore 1408 // will be released, even if exceptions or errors are raised! 1409 sequencer.release(); 1410 } 1411 </pre> 1412 </p> 1413 <p>Using <code>Semaphore.tryAcquire</code> and throwing an exception if 1414 the semaphore is already locked makes it safer to call other MBeans 1415 from within the critical section: in potential deadlock situations 1416 the calling code will get the <code>IllegalStateException</code> 1417 instead of being blocked on the deadlocked lock. 1418 </p> 1419 <p>It is worth noting that each of these techniques has its own 1420 advantages and disadvantages - which can make one of them more or less 1421 appropriate depending on the inner logic of the MBean you're implementing. 1422 </p> 1423 <p>Careful readers will also have noted that we used 1424 <code>IllegalStateException</code> directly, instead of defining 1425 our own subclass of RuntimeException, which could have had a more 1426 precise semantics. If you define a new exception for your JMX application, 1427 you must keep in mind that your client will need to have the class 1428 of your exception in its classpath to get that exception. 1429 Otherwise your client will get a completely different exception, indicating a 1430 deserialization issue. 1431 </p> 1432 </ul> 1433 1434 <h3>Waiting for Notifications</h3> 1435 <ul> 1436 <p>Implementing code that needs to wait for notifications is sometimes 1437 difficult. Because notifications are asynchronous, doing something 1438 like: 1439 <pre> 1440 // register a notification listener 1441 ... 1442 // start a management action 1443 ... 1444 // wait for a notification 1445 ... 1446 // do something based on whether the expected notification 1447 // is received 1448 ... 1449 </pre> 1450 is not always trivial. However, there's a very easy way to do that: use 1451 a blocking queue of notifications. 1452 <pre> 1453 final BlockingQueue<Notification> notifQueue = 1454 new LinkedBlockingQueue<Notification>(); 1455 1456 final NotificationListener listener = new NotificationListener() { 1457 public void handleNotification(Notification notification, 1458 Object handback) { 1459 try { 1460 // Just put the received notification in the queue. 1461 // It will be consumed later on. 1462 // 1463 notifQueue.put(notification); 1464 } catch (InterruptedException ex) { 1465 // OK 1466 } 1467 } 1468 }; 1469 1470 // register the listener - possibly also as a JMXConnectionNotification 1471 // listener to get Notification Lost notification 1472 ... 1473 // start management action 1474 ... 1475 // wait for notification 1476 while (expected notif not received and delay not expired) { 1477 Notification n = notifQueue.poll(3,TimeUnit.SECONDS); 1478 // if expected notif, do something 1479 ... 1480 } 1481 // if expected notification not received do something else. 1482 .... 1483 </pre> 1484 </p> 1485 <p>You will note that this is a technique we've been using in the <a 1486 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html" 1487 title="The ScanDirAgent class defines a main method for the scandir application" 1488 >ScanDirAgent</a> class and in the example unit tests. 1489 </p> 1490 </ul> 1491 1492 <h3>Holding hard references to other MBeans: proxy or direct reference?</h3> 1493 <ul> 1494 <p>We have seen that MXBeans will let you return proxy references to other 1495 MXBeans. But should that MXBean hold a direct reference to the MXBeans it 1496 relates to, or would it be better for it to hold only a proxy? 1497 </p> 1498 <p> 1499 As a general rule it is better when an MBean reference is 1500 only held by the MBeanServer. It is a better design 1501 to hold a reference to a proxy, rather than to hold 1502 a hard reference to an MBean. However there are two cases 1503 when holding a hard reference might be preferred: 1504 <ol> 1505 <li>When MBean A needs to call a method of method B which 1506 is not part of its MBean interface</li> 1507 <li>When the overhead of going through the MBeanServer 1508 plus the MXBean framework is too great (frequently-called 1509 method, with creation of OpenType)</li> 1510 </ol> 1511 However - holding a hard reference is only advisable 1512 when both MBeans are created by the same piece of code, 1513 and the application can ensure that the life cycle 1514 of each MBean is consistent with regard to the other. 1515 </p> 1516 <p>In our example, the <a 1517 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 1518 title="The ScanManagerMXBean is the main MBean of the scandir application" 1519 >ScanManagerMXBean</a> holds only proxy references to the <a 1520 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 1521 >ScanDirConfigMXBean</a> and the <a 1522 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 1523 >DirectoryScannerMXBeans</a>. <br> 1524 However it holds a direct reference to the <a 1525 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManager.html" 1526 >ResultLogManager</a>. This makes it possible to pass a direct 1527 reference to the <code>DirectoryScannerMXBeans</code>, 1528 which can then log their results 1529 more efficiently, and would also make it possible to remove 1530 the <code>log</code> method from the <a 1531 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 1532 >ResultLogManagerMXBean</a> interface - leaving it in the 1533 <code>ResultLogManager</code> class (possibly as a package method) 1534 should we wish to do so. 1535 </p> 1536 1537 </ul> 1538 1539 <h3>Agent Class</h3> 1540 <ul> 1541 <p>The <a 1542 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html" 1543 title="The ScanDirAgent class defines a main method for the scandir application" 1544 >ScanDirAgent</a> is the Agent class for the <i>scandir</i> application. 1545 This class contains the <code>main</code> method to start a standalone 1546 <i>scandir</i> application. 1547 </p> 1548 <p>The <code>main</code> method simply registers a <a 1549 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 1550 title="The ScanManagerMXBean is the main MBean of the scandir application" 1551 >ScanManagerMXBean</a> in the platform MBeanServer, and then waits 1552 for someone to call <code>ScanManagerMXBean.close</code>. 1553 </p> 1554 <p> 1555 When the <code>ScanManagerMXBean</code> state is switched to 1556 <code>ScanManagerMXBean.ScanState.CLOSED</code>, the 1557 <code>ScanManagerMXBean</code> is unregistered, and the application 1558 terminates (i.e. the main thread completes). 1559 </p> 1560 <p>Standalone JMX applications usually have an Agent class that contain 1561 their <code>main</code> method, which performs all the MBean 1562 registration steps. 1563 However, it is usually not a bad idea if that class can 1564 be easily turned into an MBean. Indeed, this will make your 1565 application easier to integrate in an environment where it would 1566 no longer be standalone and would no longer control the implementation 1567 of <code>main</code>. In our example the Agent 1568 class could be easily turned into an MBean, exposing its three 1569 <code>init</code>, <code>waitForClose</code> and <code>cleanup</code> 1570 method. However we didn't go as far as turning it into an MBean since 1571 the application can be already easily started by registering an instance 1572 of <a 1573 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 1574 title="The ScanManagerMXBean is the main MBean of the scandir application" 1575 >ScanManagerMXBean</a>. 1576 </p> 1577 </ul> 1578 <h3>Secure Client Class</h3> 1579 <ul> 1580 <p>The <a 1581 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html" 1582 title="The ScanDirClient class is a very short example of secure programmatic client" 1583 >ScanDirClient</a> is an example class that shows how a 1584 programmatic client can connect to a secured <i>scandir</i> application. 1585 This class contains a <code>main</code> method which creates and 1586 configures a <code>JMXConnector</code> client to connect with 1587 a secured <i>scandir</i> daemon. This class will not work with 1588 the default unsecured agent since it requires mutual authentication. 1589 </p> 1590 <p>How to secure a JMX <i>scandir</i> application and run 1591 the secure <code>ScanDirClient</code> is discussed <a href="#secure" 1592 >later</a> in this document. 1593 </p> 1594 <p>The <code>ScanDirClient</code> is not really part of the 1595 application - and is given here only for the sake of 1596 the example. 1597 </p> 1598 </ul> 1599 1600 <h2><a name="h2-Testing">Testing the <i>scandir</i> Example</a></h2> 1601 <ul> 1602 <p>Make sure that you have access to junit.jar (either 3.8.1 or 3.8.2). 1603 Make sure also that you have junit.jar in your 1604 <code>CLASSPATH</code>.<br> 1605 Then in the example root directory (where the <code>build.xml</code> 1606 file is located) run the following command: 1607 <pre>ant test -Dlibs.junit.classpath=<i><u>path to junit jar (either 3.8.1 or 3.8.2)</u></i></pre> 1608 </p> 1609 <p>Alternatively you can open the jmx-scandir project with the 1610 NetBeans IDE and test the jmx-scandir project from the 1611 <code>Run</code> menu. 1612 </p> 1613 1614 </ul> 1615 1616 <h2><a name="h2-Running">Running the <i>scandir</i> Example</a></h2> 1617 <ul> 1618 <p>In the example root directory (where the <code>build.xml</code> 1619 file is located) run the following commands: 1620 <pre>ant jar 1621 ant run-single -Drun.class=com.sun.jmx.examples.scandir.ScanDirAgent -Djavac.includes=src</pre> 1622 or simply <pre>ant run</pre> 1623 </p> 1624 1625 <p>This will run the example using the configuration 1626 file provided in the src/etc directory. 1627 </p> 1628 <p>Alternatively you can open the jmx-scandir project with the 1629 NetBeans IDE. You can run the example by 1630 selecting the <code>ScanDirAgent</code> file 1631 and run it with <code>Run File</code> in the 1632 <code>Run</code> menu or simply 1633 set the <i>jmx-scandir</i> project as main project and 1634 select <code>Run Main Project</code> from the 1635 main menu. Both targets will use the configuration 1636 file provided in the src/etc directory. 1637 </p> 1638 <p>When the application is started, you can connect to 1639 it with <a href="#JConsole">jconsole</a>. 1640 </p> 1641 <blockquote> 1642 <u>Note:</u> You can also run the <i>scandir</i> 1643 application directly from the <code>java</code> 1644 command line. Make sure to build the project jar 1645 first. 1646 <br>On Unix systems: 1647 <pre>ant jar 1648 java -Djava.util.logging.config.file=logging.properties \ 1649 -Dscandir.config.file=src/etc/testconfig.xml \ 1650 -jar dist/jmx-scandir.jar</pre> 1651 <br>On Windows systems: 1652 <p><code>ant jar<br> 1653 java -Djava.util.logging.config.file=logging.properties 1654 -Dscandir.config.file=src\etc\testconfig.xml 1655 -jar dist\jmx-scandir.jar</code></p> 1656 </blockquote> 1657 </ul> 1658 1659 <h2><a name="h2-Playing">Playing with JConsole</a></h2> 1660 <ul> 1661 <p>Run the example as explained in the previous section, so 1662 that it uses the provided <code>src/etc/testconfig.xml</code> 1663 configuration file. Then start 1664 jconsole. In the connection window choose the process that runs 1665 <code>com.sun.jmx.examples.scandir.ScanDirAgent</code> or 1666 <code>jmx-scandir.jar</code>. 1667 </p> 1668 <p><center> 1669 <table border="0" cellpadding="2" cellspacing="2"> 1670 <tr><td> 1671 <a href="docfiles/connect-local-ant-run.jpg" 1672 title="jconsole connection window - connect to local process" 1673 ><img height="440" 1674 src="docfiles/connect-local-ant-run.jpg" 1675 alt="jconsole connection window - connect to local process" 1676 /></a> 1677 </td> 1678 <td> 1679 <a href="docfiles/connect-local-java-jar.jpg" 1680 title="jconsole connection window - connect to local process" 1681 ><img height="440" 1682 src="docfiles/connect-local-java-jar.jpg" 1683 alt="jconsole connection window - connect to local process" 1684 /></a> 1685 </td></tr></table> 1686 </center> 1687 </p> 1688 <p>Open the MBeans tab, and look for the 1689 <code>ScanDirConfigMXBean</code>. 1690 Click on its <code>Attributes</code> node and double click on its 1691 <code>Configuration</code> attribute, to look at 1692 the loaded configuration - values in bold can 1693 be expanded by a double-click. 1694 </p> 1695 <p><center><a href="docfiles/scandir-config.jpg" 1696 title="jconsole MBean tab: ScanDirConfigMXBean" 1697 ><img 1698 src="docfiles/scandir-config.jpg" 1699 alt="jconsole MBean tab: ScanDirConfigMXBean" 1700 /></a></center> 1701 </p> 1702 <p>Now go to the <code>ScanManagerMXBean</code>, click on 1703 its <code>Notifications</code> node, and subscribe 1704 for notifications. Then click on the 1705 <code>Operations</code> node and invoke the 1706 <code>start()</code> operation: 1707 </p> 1708 <p><center><a href="docfiles/scandir-start.jpg" 1709 title="jconsole MBean tab: ScanDirConfigMXBean" 1710 ><img 1711 src="docfiles/scandir-start.jpg" 1712 alt="jconsole MBean tab: ScanDirConfigMXBean" 1713 /></a></center> 1714 </p> 1715 <p>You can see that the notifications counter was 1716 incremented by three: you have just scheduled, 1717 run, and completed a batch of directory scans. 1718 </p> 1719 <p>Now go to the <code>ResultLogManagerMXBean</code>, 1720 click on its <code>Attributes</code> node, and 1721 expand its <code>MemoryLog</code> attribute: 1722 </p> 1723 <p><center><a href="docfiles/scandir-result.jpg" 1724 title="jconsole MBean tab: ScanDirConfigMXBean" 1725 ><img 1726 src="docfiles/scandir-result.jpg" 1727 alt="jconsole MBean tab: ScanDirConfigMXBean" 1728 /></a></center> 1729 </p> 1730 <p>You can see that the directory scan results have 1731 been logged.</p> 1732 <p>To make the application terminate go back to the 1733 <code>ScanManagerMXBean</code> and invoke 1734 <code>close()</code>. The <code>ScanDirAgent</code> 1735 will receive the notification, step out of 1736 the application main thread, and the application 1737 will terminate. 1738 </p> 1739 <p>This is of course a very limited scenario. Feel free 1740 to improvise with all the features of the example, creating 1741 a new configuration - 1742 <code>ScanManagerMXBean.createOtherConfigurationMBean</code> - 1743 adding multiple directory scanners to that configuration - 1744 <code>ScanDirConfigMXBean.addDirectoryScanner</code> - 1745 then switching the <code>ScanManagerMXBean</code> current 1746 configuration by changing the value of the <i>ConfigurationMBean</i> 1747 attribute - <code>ScanManagerMXBean.setConfigurationMBean</code> 1748 - then applying the new configuration - 1749 <code>ScanManagerMXBean.applyConfiguration(true)</code> - 1750 then scheduling repeated directory scans every 10 seconds - 1751 <code>ScanManagerMXBean.schedule(0,10000)</code> - 1752 subscribing for notifications, etc... 1753 </p> 1754 </ul> 1755 1756 <a name="secure"></a> 1757 <h2><a name="h2-Turning">Turning the example into a Secure JMX Application</a></h2> 1758 <ul> 1759 <p>In this section, we will see how to configure and 1760 start the <i>scandir</i> example so that the JVM agent 1761 is bootstrapped with a secure JMXConnectorServer. Indeed, until 1762 now we have only used the insecure local connection, 1763 which can only be used as long as both the client and 1764 the server run on the same machine. This section will 1765 explain how to start the <code>ScanDirAgent</code> so 1766 that a real secure RMIConnectorServer is started at bootstrap. 1767 </p> 1768 <p>To achieve this we will: <a href="#management.properties" 1769 >provide our own management.properties</a>, <a 1770 href="#password-access">create our own password and access files</a>, 1771 <a href="#keystore-truststore">provide a keystore and truststore</a>, 1772 <a href="#start-secure-agent">start the ScanDirAgent with the 1773 appropriate system properties</a>. 1774 </ul> 1775 <h3>Configuring the JVM Agent for Secure Remote Connection</h3> 1776 <ul> 1777 <p>The easiest way to <a name="management.properties">configure the 1778 JVM Agent</a> for Secure Remote 1779 Connection is to use your own <a 1780 href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#properties" 1781 title="This page describes the properties you can put in your management.properties file" 1782 >management.properties</a> file. 1783 In this example, we have copied the default 1784 <code>$JRE/lib/management/management.properties</code> 1785 file to the example's <code>src/etc</code> directory and 1786 modified it in <a href="src/etc/management.properties" 1787 title="our modified management.properties" 1788 >this way</a>: 1789 <ul> 1790 <li>We have set the RMI port to <u>4545</u> - this is just a 1791 random port number we have picked up. Feel free to use your 1792 own value suited to your environment. 1793 <pre># For setting the JMX RMI agent port use the following line 1794 com.sun.management.jmxremote.port=<b>4545</b></pre> 1795 </li> 1796 <li>We have <u>switched on</u> SSL <u>mutual authentication</u> 1797 <pre># For RMI monitoring with SSL client authentication use the following line 1798 com.sun.management.jmxremote.ssl.<b>need.client.auth</b>=<b>true</b></pre> 1799 </li> 1800 <li>We have also <u>secured the RMI Registry</u> with SSL 1801 <pre># For using an SSL/TLS <b>protected</b> RMI Registry use the following line 1802 com.sun.management.jmxremote.<b>registry.ssl</b>=<b>true</b></pre> 1803 </li> 1804 <li>We have provided <a 1805 href="src/etc/password.properties">our own password file</a> 1806 <pre># For a non-default password file location use the following line 1807 com.sun.management.jmxremote.password.file=<i>src/etc/password.properties</i></pre> 1808 </li> 1809 <li>We have provided <a 1810 href="src/etc/access.properties">our own access file</a> 1811 <pre># For a non-default password file location use the following line 1812 com.sun.management.jmxremote.access.file=<i>src/etc/access.properties</i></pre> 1813 </li> 1814 </ul> 1815 <p>You will note that we haven't provided any value 1816 for the other security properties, like 1817 <code>com.sun.management.jmxremote.authenticate=true</code>, 1818 because these properties already default to a value 1819 which enables security by default. 1820 Note however that protecting the RMI Registry with SSL 1821 improves the application security, but only as long as 1822 mutual authentication is also switched on. Otherwise, just 1823 anybody would be able to connect to the registry and 1824 get the RMIServer stub. 1825 </p> 1826 <p>We do recommend that you <u>use the most secure configuration 1827 when you deploy a JMX agent</u> - which means <u>switching on 1828 SSL protection for the RMI registry</u> <b>and</b> <u>requiring 1829 mutual authentication</u>, as we show in this example. 1830 </p> 1831 <p>We will use the <code>com.sun.management.config.file</code> 1832 system property to pass our <a 1833 href="src/etc/management.properties">management.properties</a> 1834 file to the <code>ScanDirAgent</code>. 1835 </p> 1836 </ul> 1837 1838 <h3>Creating a password and access file</h3> 1839 <ul> 1840 <p>As explained above, we have created our own 1841 <a href="src/etc/password.properties">password file</a> 1842 and <a href="src/etc/access.properties">access file</a> 1843 for <a name="password-access">access control and authorization</a>. 1844 </p> 1845 <p>In the password file, we have defined two logins: 1846 <i>guest</i> and <i>admin</i>. The password for 1847 <i>guest</i> is <i>guestpasswd</i> and the password 1848 for <i>admin</i> is <i>adminpasswd</i>. 1849 </p> 1850 <p>In the access file, we have mapped these two logins 1851 to access rights: the <i>admin</i> login has <i>read-write</i> 1852 access, while the <i>guest</i> login only has <i>read-only</i>. 1853 </p> 1854 <p>Before starting the <code>ScanDirAgent</code>, you will 1855 need to restrict access permission to the password file, 1856 in such a way that nobody but you can read it. Otherwise, the 1857 JVM Agent will refuse to start the JMXConnectorServer, as it will 1858 fear that security can be compromised if other parties can 1859 have read access to the password file. How to restrict 1860 read access to the password file is explained in detail 1861 <a href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#PasswordAccessFiles" 1862 title="Using Password and Access Files" 1863 >here</a>. 1864 </p> 1865 <p>As we have seen above, the location 1866 of our access and password files is configured in our own <a 1867 href="src/etc/management.properties">management.properties</a> 1868 file. 1869 </p> 1870 </ul> 1871 <h3>Keystore and Truststore</h3> 1872 <ul> 1873 <p>Using SSL with mutual authentication means that both 1874 client and server will need a <a name="keystore-truststore" 1875 >keystore and a truststore</a> 1876 to store their own certificates, and the certificates of 1877 the parties they trust. Usually, client and server will 1878 have their own keystore and truststore. 1879 </p> 1880 <p>For the sake of simplicity - and to get you started 1881 without the tedious necessity of creating your own keystore 1882 and truststore, we are providing a dummy keystore and 1883 truststore, containing a certificate self-signed by duke. 1884 The password for our keystore is <i>password</i>, and the 1885 password for our truststore is <i>trustword</i>. 1886 We suggest that you first get the example running with the 1887 keystore and truststore we are providing before attempting 1888 to use your own keystore and truststore. 1889 </p> 1890 <p>A secure application will obviously need to use its own 1891 keystore and truststore, <b><u>and should not rely on the keystore 1892 and truststore we are providing here!</u></b> 1893 </p> 1894 <p>How to create your own keystore and truststore, is explained 1895 in <a 1896 href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#SSL_enabled" 1897 title="Monitoring and Management Using JMX" 1898 >here</a>. 1899 As shown <a href="#start-secure-agent">later</a>, 1900 we will need to use <a 1901 href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#SSL_enabled" 1902 >system properties</a> to pass our truststore 1903 and keystore to the <code>ScanDirAgent</code>. 1904 </p> 1905 </ul> 1906 <h3>Starting a Secure <i>scandir</i> agent</h3> 1907 <ul> 1908 <p>To start a <a name="start-secure-agent" 1909 >secure <i>scandir</i> agent</a>, go to the 1910 <i>scandir</i> example root directory and type the 1911 following command:</p> 1912 <p>On Unix Systems: 1913 <pre>ant jar 1914 java \ 1915 -Djava.util.logging.config.file=logging.properties \ 1916 -Djavax.net.ssl.keyStore=keystore \ 1917 -Djavax.net.ssl.keyStorePassword=password \ 1918 -Djavax.net.ssl.trustStore=truststore \ 1919 -Djavax.net.ssl.trustStorePassword=trustword \ 1920 -Dcom.sun.management.config.file=src/etc/management.properties \ 1921 -Dscandir.config.file=src/etc/testconfig.xml \ 1922 -jar dist/jmx-scandir.jar</pre> 1923 </p> 1924 <p>On Windows Systems: 1925 <p><code>ant jar<br> 1926 java 1927 -Djava.util.logging.config.file=logging.properties 1928 -Djavax.net.ssl.keyStore=keystore 1929 -Djavax.net.ssl.keyStorePassword=password 1930 -Djavax.net.ssl.trustStore=truststore 1931 -Djavax.net.ssl.trustStorePassword=trustword 1932 -Dcom.sun.management.config.file=src\etc\management.properties 1933 -Dscandir.config.file=src\etc\testconfig.xml 1934 -jar dist\jmx-scandir.jar</code></p> 1935 </p> 1936 <p>If you start jconsole now, you will see that you 1937 are still able to connect to the agent using the 1938 local connection. However, if you try to connect 1939 through the remote connector, using 1940 <a href="docfiles/remote-connection.jpg">localhost:4545</a>, 1941 the connection will <a href="docfiles/remote-connection-failed.jpg" 1942 >fail</a>, even if you provide a correct login/password 1943 pair. Indeed, since the JMXConnectorServer is now protected with SSL, 1944 jconsole must also be configured with the appropriate SSL parameters 1945 so that it can authenticate the server and get authenticated by the 1946 server too as the SSL configuration of the server requires mutual 1947 authentication. 1948 </p> 1949 <p>The next section will discuss how to connect to the 1950 secure agent. 1951 </p> 1952 </ul> 1953 1954 <h2><a name="h2-Connecting">Connecting to the Secure JMX Application</a></h2> 1955 <ul> 1956 <p>We will now see how to connect to the secure agent, 1957 using jconsole, and using a programmatic client. 1958 </p> 1959 </ul> 1960 1961 <h3>Using jconsole to connect to the secure agent</h3> 1962 <ul> 1963 <p>The only special thing you need to do in order to 1964 be able to connect to your secure agent with 1965 jconsole, is to give it a keystore (containing 1966 its client certificate) and a truststore (containing 1967 the certificates of the servers it can trust). 1968 In our example, we use the same keystore/truststore 1969 pair on the client and server side - but this is 1970 not what a real application would do. 1971 Indeed a real application would have different 1972 certificates for the client and the server, and 1973 thus use different keystores (and probably truststores). 1974 More information on SSL authentication can be obtained from the <a 1975 href="http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#HowSSLWorks" 1976 title="How SSL Works" 1977 >Java<sup>TM</sup> Secure Socket Extension (JSSE) Reference Guide</a>. 1978 </p> 1979 <p>To start jconsole with our provided keystore and 1980 truststore, go to the scandir example root directory and 1981 type in the following command: 1982 <p><code>jconsole 1983 -J-Djava.util.logging.config.file=logging.properties 1984 -J-Djavax.net.ssl.keyStore=keystore 1985 -J-Djavax.net.ssl.keyStorePassword=password 1986 -J-Djavax.net.ssl.trustStore=truststore 1987 -J-Djavax.net.ssl.trustStorePassword=trustword</code></p> 1988 </p> 1989 <p>The <code>-J-Djava.util.logging.config.file=logging.properties</code> 1990 flag is not mandatory, but passing a <code>logging.properties</code> 1991 may help you debug connection problems if anything goes wrong. 1992 </p> 1993 <p>In jconsole connection window, choose to connect to a 1994 remote process, using the address <i>localhost:4545</i> 1995 and the guest login: 1996 </p> 1997 <p><center><a href="docfiles/remote-connection.jpg" 1998 ><img src="docfiles/remote-connection.jpg" 1999 alt="jconsole connection window"/></a></center> 2000 </p> 2001 <p>You will see that the agent will let view all the 2002 MBeans and their attributes, but will reject any 2003 attribute modification or remote method invocation. 2004 </p> 2005 <hr> 2006 <p><u>Note:</u> if jconsole fails to connect and show 2007 you <a href="docfiles/remote-connection-failed.jpg">this screen</a> 2008 you have probably misspelled some of the properties on jconsole 2009 command line, or you didn't start jconsole from the 2010 scandir example root directory where our <code>truststore</code> 2011 and <code>keystore</code> files are located. This article - <a 2012 href="http://blogs.sun.com/roller/page/jmxetc?entry=troubleshooting_connection_problems_in_jconsole" 2013 title="Troubleshooting connection problems in JConsole" 2014 >Troubleshooting connection problems in JConsole</a> - may help 2015 you figure out what is going wrong. 2016 </p> 2017 <hr> 2018 </ul> 2019 2020 <h3>Writing a programmatic client to connect to the secure agent</h3> 2021 <ul> 2022 <p> 2023 In this section we will show the steps involved in writing 2024 a programmatic client that will connect to our secure agent. 2025 </p> 2026 <p>The <a 2027 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html" 2028 title="The ScanDirClient class is a very short example of secure programmatic client" 2029 >ScanDirClient</a> is an example class that shows how a 2030 programmatic client can connect to a secured <i>scandir</i> application. 2031 This class contains a <code>main</code> method which creates and 2032 configures a <code>JMXConnector</code> client to connect with 2033 the secured <i>scandir</i> agent. 2034 </p> 2035 <p>The secure client differs only from a non secure client in 2036 so far as it needs to use SSL RMI Factories and credentials to 2037 connect to the secure agent. The steps required mainly involve: 2038 <ul> 2039 <li>Creating an empty environment map: 2040 <pre> 2041 // Create an environment map to hold connection properties 2042 // like credentials etc... We will later pass this map 2043 // to the JMX Connector. 2044 // 2045 System.out.println("\nInitialize the environment map"); 2046 final Map<String,Object> env = new HashMap<String,Object>(); 2047 </pre> 2048 </li> 2049 <li>Putting the client's credentials in that map: 2050 <i>(here the client will log in as <b>guest</b>)</i> 2051 <pre> 2052 // Provide the credentials required by the server 2053 // to successfully perform user authentication 2054 // 2055 final String[] credentials = new String[] { "guest" , "guestpasswd" }; 2056 env.put("jmx.remote.credentials", credentials); 2057 </pre> 2058 </li> 2059 <li>Providing an <code>SslRMIClientSocketFactory</code> to interact 2060 with the secure RMI Registry: 2061 <pre> 2062 // Provide the SSL/TLS-based RMI Client Socket Factory required 2063 // by the JNDI/RMI Registry Service Provider to communicate with 2064 // the SSL/TLS-protected RMI Registry 2065 // 2066 env.put("com.sun.jndi.rmi.factory.socket", 2067 new SslRMIClientSocketFactory()); 2068 </pre> 2069 </li> 2070 <li>Creating a JMXConnector and connecting with the 2071 secure server: 2072 <pre> 2073 // Create the RMI connector client and 2074 // connect it to the secure RMI connector server. 2075 // args[0] is the server's host - localhost 2076 // args[1] is the secure server port - 4545 2077 // 2078 System.out.println("\nCreate the RMI connector client and " + 2079 "connect it to the RMI connector server"); 2080 final JMXServiceURL url = new JMXServiceURL( 2081 "service:jmx:rmi:///jndi/rmi://"+args[0]+":"+args[1]+ 2082 "/jmxrmi"); 2083 final JMXConnector jmxc = JMXConnectorFactory.connect(url, env); 2084 </pre> 2085 </li> 2086 </ul> 2087 <p>For this to work, we also need to start the <code>ScanDirClient</code> 2088 with the appropriate system properties that will point to our 2089 <code>keystore</code> and <code>truststore</code>. To start the secure 2090 client, go to the <i>scandir</i> example root directory and type 2091 the following command: 2092 <p><code>ant jar<br> 2093 java 2094 -Djava.util.logging.config.file=logging.properties 2095 -Djavax.net.ssl.keyStore=keystore 2096 -Djavax.net.ssl.keyStorePassword=password 2097 -Djavax.net.ssl.trustStore=truststore 2098 -Djavax.net.ssl.trustStorePassword=trustword 2099 -classpath dist/jmx-scandir.jar 2100 com.sun.jmx.examples.scandir.ScanDirClient localhost 4545 2101 </code></p> 2102 </p> 2103 <p>You should be seeing this trace: 2104 <center><table width="90%" border="0" bgcolor="#eeeeee"> 2105 <tr><td> 2106 <pre> 2107 Initialize the environment map 2108 2109 Create the RMI connector client and connect it to the RMI connector server 2110 Connecting to: service:jmx:rmi:///jndi/rmi://localhost:4545/jmxrmi 2111 2112 Get the MBeanServerConnection 2113 2114 Get ScanDirConfigMXBean from ScanManagerMXBean 2115 2116 Get 'Configuration' attribute on ScanDirConfigMXBean 2117 2118 Configuration: 2119 2120 <ScanManager xmlns="jmx:com.sun.jmx.examples.scandir.config" name="testconfig"> 2121 <InitialResultLogConfig> 2122 <LogFileMaxRecords>2048</LogFileMaxRecords> 2123 <LogFileName>build/scandir.log</LogFileName> 2124 <MemoryMaxRecords>128</MemoryMaxRecords> 2125 </InitialResultLogConfig> 2126 <DirectoryScannerList> 2127 <DirectoryScanner name="scan-build"> 2128 <Actions>NOTIFY LOGRESULT</Actions> 2129 <ExcludeFiles/> 2130 <IncludeFiles> 2131 <FileFilter> 2132 <FilePattern>.*\.class</FilePattern> 2133 <SizeExceedsMaxBytes>4096</SizeExceedsMaxBytes> 2134 </FileFilter> 2135 </IncludeFiles> 2136 <RootDirectory>build</RootDirectory> 2137 </DirectoryScanner> 2138 </DirectoryScannerList> 2139 </ScanManager> 2140 2141 Invoke 'close' on ScanManagerMXBean 2142 2143 Got expected security exception: java.lang.SecurityException: Access denied! 2144 Invalid access level for requested MBeanServer operation. 2145 2146 Close the connection to the server 2147 2148 Bye! Bye! 2149 </pre> 2150 </td></tr></table></center> 2151 <p>If the <code>ScanDirClient</code> fails to connect with 2152 the secure agent, then this article - <a 2153 href="http://blogs.sun.com/roller/page/jmxetc?entry=troubleshooting_connection_problems_in_jconsole" 2154 title="Troubleshooting connection problems in JConsole" 2155 >Troubleshooting connection problems in JConsole</a> - may help 2156 you figure out what is going wrong. Indeed the connection steps 2157 performed by the <code>ScanDirClient</code> are very similar to 2158 those performed by <code>jconsole</code>, and the problems you 2159 could encounter are identical. Just remember that 2160 <code>jconsole</code> needs the extra <code>-J</code> flag to pass 2161 system properties to the VM, which is not needed with regular 2162 <code>java</code> launcher invocations. 2163 </p> 2164 </ul> 2165 2166 <h2><a name="h2-Conclusion">Conclusion</a></h2> 2167 <ul> 2168 <p> 2169 In this document, we have presented an advanced 2170 JMX example, and shown how to run a secure 2171 JMX agent in a production environment. 2172 We have also shown how to connect to such a 2173 secure agent with both jconsole and a programmatic 2174 client. We have also discuss various JMX 2175 design-patterns and best practices. 2176 Readers who would wish to learn more about JMX, and 2177 Monitoring and Management of the JVM, are invited 2178 to follow the links given in reference below. 2179 </p> 2180 </ul> 2181 <h2><a name="h2-References">References</a></h2> 2182 <ol> 2183 <li><a href="http://java.sun.com/products/JavaManagement/best-practices.html" 2184 >JMX Best Practices</a>: This document describes best practices that 2185 have been identified for modeling using the JMX API. </li> 2186 <li><a href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html" 2187 >Monitoring and Management Using JMX</a>: How to enable, configure, and 2188 connect to the JVM JMX agent.</li> 2189 <li><a name="JConsole"><a 2190 href="http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html" 2191 >Using JConsole</a>: JConsole is a JMX-Compliant monitoring tool which allows 2192 you to interact graphically with your own MBeans. 2193 </li> 2194 <li><a href="http://java.sun.com/javase/6/docs/technotes/guides/management/" 2195 >Monitoring and Management for the Java Platform</a>: The Java Platform 2196 Standard Edition (Java SE) 6 provides comprehensive monitoring and 2197 management support for the Java platform. </li> 2198 <li><a href="http://java.sun.com/products/JavaManagement/community/jmx_blogs.html" 2199 >List of JMX-related Blogs</a>: This page provides links to the 2200 different web logs written by members of the Sun team working on the 2201 JMX API.</li> 2202 <li><a 2203 href="http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#HowSSLWorks" 2204 title="The JSSE Reference Guide" 2205 >Java<sup>TM</sup> Secure Socket Extension (JSSE) Reference Guide</a>: 2206 comprehensive documentation about the Java<sup>TM</sup> Secure Socket 2207 Extension (JSSE) 2208 </li> 2209 <li><a href="http://java.sun.com/javase/6/docs/" 2210 >Java SE 6 Documentation Index</a>: This document covers the 2211 Java<sup>TM</sup> Platform, Standard Edition 6 JDK.</li> 2212 </ol> 2213 <p> 2214 <hr> 2215 <p> 2216 </body> 2217 </html> 2218