blob: 0420fa66a5a6d0298c54f31f342190f97d5d3900 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
3<html>
4 <head>
5<!--
6 Copyright 2006 Sun Microsystems, Inc. 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 Sun Microsystems 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&nbsp;the&nbsp;Java&nbsp;Documentation</a>]
104 [<a href="#h2-Overview">Overview&nbsp;of&nbsp;the&nbsp;<i>scandir</i>&nbsp;Example</a>]
105 [<a href="#h2-API-Doc">API&nbsp;Documentation&nbsp;and&nbsp;Sources</a>]
106 [<a href="#h2-Patterns">Patterns,&nbsp;Best&nbsp;Practices,&nbsp;and&nbsp;Common&nbsp;Pitfalls</a>]
107 [<a href="#h2-Testing">Testing&nbsp;the&nbsp;<i>scandir</i>&nbsp;Example</a>]
108 [<a href="#h2-Running">Running&nbsp;the&nbsp;<i>scandir</i>&nbsp;Example</a>]
109 [<a href="#h2-Playing">Playing&nbsp;with&nbsp;JConsole</a>]
110 [<a href="#h2-Turning">Turning&nbsp;the&nbsp;example&nbsp;into&nbsp;a&nbsp;Secure&nbsp;JMX&nbsp;Application</a>]
111 [<a href="#h2-Connecting">Connecting&nbsp;to&nbsp;the&nbsp;Secure&nbsp;JMX&nbsp;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
141href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
142title="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
155href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
156title="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
162href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
163title="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
168href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManager.html"
169title="The ResultLogManager is in charge of managing result logs"
170 >ResultLogManager</a> and some <a
171href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
172title="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
181href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
182title="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
190href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
191title="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
210href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
211title="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
215href="dist/javadoc/com/sun/jmx/examples/scandir/config/ResultRecord.html"
216title="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
250href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
251title="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
255href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
256title="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
265href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
266title="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
273href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
274title="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
351href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
352title="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
369href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
370title="The ScanManagerMXBean is the main MBean of the scandir application"
371 >ScanManagerMXBean</a> which exposes a list
372 of <code><a
373href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
374title="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
377href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
378title="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
387href="http://weblogs.java.net/blog/emcmanus/archive/2006/02/what_is_an_mxbe.html"
388title="What is an MXBean?"
389 >What is an MXBean?</a>
390 and <a
391href="http://weblogs.java.net/blog/emcmanus/archive/2006/06/intermxbean_ref.html"
392title="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
439href="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
460href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
461title="The ScanManagerMXBean is the main MBean of the scandir application"
462 >ScanManagerMXBean</a> and <a
463href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
464title="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
483href="src/com/sun/jmx/examples/scandir/ScanManager.java"
484title="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&lt;String,DirectoryScannerMXBean&gt; getDirectoryScanners();
552 </pre>
553 makes it immediately obvious that the MBeans to which we point are
554 <a
555href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
556title="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&lt;String,ObjectName&gt;</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&lt;String,DirectoryScannerConfig&gt; 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
591href="http://weblogs.java.net/blog/emcmanus/archive/2006/06/intermxbean_ref.html"
592title="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
658href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
659title="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
664href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
665title="The ResultLogManagerMXBean is in charge of managing result logs"
666 >ResultLogManagerMXBean</a>, and the
667 <a
668href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
669title="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
679href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
680title="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
692href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
693title="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
709href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
710title="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
714href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
715title="The ScanManagerMXBean is the main MBean of the scandir application"
716 >ScanManagerMXBean</a>
717 always returns its singleton ObjectName
718 defined by <a
719href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html#SCAN_MANAGER_NAME"
720title="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
728href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
729title="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
749href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
750title="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
754href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
755title="The ResultLogManagerMXBean is in charge of managing result logs"
756 >ResultLogManagerMXBean</a> and the default
757 <a
758href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
759title="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
770href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
771title="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
792href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
793title="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
797href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
798title="The ResultLogManagerMXBean is in charge of managing result logs"
799 >ResultLogManagerMXBean</a>, the
800 <a
801href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
802title="The ScanDirConfigMXBean is in charge of the configuration"
803 >ScanDirConfigMXBeans</a> it has created, and the
804 <a
805href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
806title="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
820href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
821title="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
847href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
848title="The ScanManagerMXBean is the main MBean of the scandir application"
849 >ScanManagerMXBean</a></code> and the
850 <code><a
851href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
852title="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
904href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
905title="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
929href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
930title="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
940href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
941title="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
946href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
947title="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
953href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
954title="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
1070href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
1071title="The ScanDirConfigMXBean is in charge of the configuration"
1072 >ScanDirConfigMXBean</a> and <a
1073href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
1074title="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
1100href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
1101title="The ScanManagerMXBean is the main MBean of the scandir application"
1102 >ScanManagerMXBean</a> and the <a
1103href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
1104title="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
1115href="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
1221href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
1222title="The ScanManagerMXBean is the main MBean of the scandir application"
1223 >ScanManagerMXBean</a> and the <a
1224href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
1225title="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
1231href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
1232title="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
1244href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
1245title="The ScanDirConfigMXBean is in charge of the configuration"
1246 >ScanDirConfigMXBean</a> and <a
1247href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
1248title="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
1254href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
1255title="The ScanManagerMXBean is the main MBean of the scandir application"
1256 >ScanManagerMXBean</a> and the <a
1257href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
1258title="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
1263href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
1264title="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
1311href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
1312title="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
1319href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
1320title="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
1335href="dist/javadoc/com/sun/jmx/examples/scandir/config/package-summary.html"
1336title="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
1347href="dist/javadoc/com/sun/jmx/examples/scandir/config/ScanManagerConfig.html"
1348title="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
1351href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
1352title="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
1391href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
1392title="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&lt;Notification&gt; notifQueue =
1454 new LinkedBlockingQueue&lt;Notification&gt;();
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
1486href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html"
1487title="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
1517href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
1518title="The ScanManagerMXBean is the main MBean of the scandir application"
1519 >ScanManagerMXBean</a> holds only proxy references to the <a
1520href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
1521 >ScanDirConfigMXBean</a> and the <a
1522href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
1523 >DirectoryScannerMXBeans</a>. <br>
1524 However it holds a direct reference to the <a
1525href="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
1531href="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
1542href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html"
1543title="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
1549href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
1550title="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
1573href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
1574title="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
1581href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html"
1582title="The ScanDirClient class is a very short example of secure programatic 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
1621ant 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
1648java -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>
1653java &nbsp;-Djava.util.logging.config.file=logging.properties
1654 &nbsp;-Dscandir.config.file=src\etc\testconfig.xml
1655 &nbsp;-jar&nbsp;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
1794com.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
1798com.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
1802com.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
1807com.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
1812com.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
1896href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#SSL_enabled"
1897title="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
1914java \
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>
1926java
1927 &nbsp;-Djava.util.logging.config.file=logging.properties
1928 &nbsp;-Djavax.net.ssl.keyStore=keystore
1929 &nbsp;-Djavax.net.ssl.keyStorePassword=password
1930 &nbsp;-Djavax.net.ssl.trustStore=truststore
1931 &nbsp;-Djavax.net.ssl.trustStorePassword=trustword
1932 &nbsp;-Dcom.sun.management.config.file=src\etc\management.properties
1933 &nbsp;-Dscandir.config.file=src\etc\testconfig.xml
1934 &nbsp;-jar&nbsp;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 &nbsp;-J-Djava.util.logging.config.file=logging.properties
1984 &nbsp;-J-Djavax.net.ssl.keyStore=keystore
1985 &nbsp;-J-Djavax.net.ssl.keyStorePassword=password
1986 &nbsp;-J-Djavax.net.ssl.trustStore=truststore
1987 &nbsp;-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
2027href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html"
2028title="The ScanDirClient class is a very short example of secure programatic 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&lt;String,Object> env = new HashMap&lt;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>
2093java
2094 &nbsp;-Djava.util.logging.config.file=logging.properties
2095 &nbsp;-Djavax.net.ssl.keyStore=keystore
2096 &nbsp;-Djavax.net.ssl.keyStorePassword=password
2097 &nbsp;-Djavax.net.ssl.trustStore=truststore
2098 &nbsp;-Djavax.net.ssl.trustStorePassword=trustword
2099 &nbsp;-classpath&nbsp;dist/jmx-scandir.jar
2100 &nbsp;com.sun.jmx.examples.scandir.ScanDirClient&nbsp;localhost&nbsp;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>
2107Initialize the environment map
2108
2109Create the RMI connector client and connect it to the RMI connector server
2110Connecting to: service:jmx:rmi:///jndi/rmi://localhost:4545/jmxrmi
2111
2112Get the MBeanServerConnection
2113
2114Get ScanDirConfigMXBean from ScanManagerMXBean
2115
2116Get 'Configuration' attribute on ScanDirConfigMXBean
2117
2118Configuration:
2119
2120&lt;ScanManager xmlns="jmx:com.sun.jmx.examples.scandir.config" name="testconfig">
2121 &lt;InitialResultLogConfig>
2122 &lt;LogFileMaxRecords>2048&lt;/LogFileMaxRecords>
2123 &lt;LogFileName>build/scandir.log&lt;/LogFileName>
2124 &lt;MemoryMaxRecords>128&lt;/MemoryMaxRecords>
2125 &lt;/InitialResultLogConfig>
2126 &lt;DirectoryScannerList>
2127 &lt;DirectoryScanner name="scan-build">
2128 &lt;Actions>NOTIFY LOGRESULT&lt;/Actions>
2129 &lt;ExcludeFiles/>
2130 &lt;IncludeFiles>
2131 &lt;FileFilter>
2132 &lt;FilePattern>.*\.class&lt;/FilePattern>
2133 &lt;SizeExceedsMaxBytes>4096&lt;/SizeExceedsMaxBytes>
2134 &lt;/FileFilter>
2135 &lt;/IncludeFiles>
2136 &lt;RootDirectory>build&lt;/RootDirectory>
2137 &lt;/DirectoryScanner>
2138 &lt;/DirectoryScannerList>
2139&lt;/ScanManager>
2140
2141Invoke 'close' on ScanManagerMXBean
2142
2143Got expected security exception: java.lang.SecurityException: Access denied!
2144Invalid access level for requested MBeanServer operation.
2145
2146Close the connection to the server
2147
2148Bye! 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
2190href="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>