jdk/src/share/sample/jmx/jmx-scandir/index.html
author tonyp
Wed, 19 Aug 2009 12:53:25 -0400
changeset 3691 c84b8483cd2c
parent 2 90ce3da70b43
child 5506 202f599c92aa
permissions -rw-r--r--
6871111: G1: remove the concurrent overhead tracker Summary: Removing the concurrent overhead tracker from G1, along with the GC overhead reporter and the G1AccountConcurrentOverhead (both of which rely on the the concurrent overhead tracker). Reviewed-by: iveresov, johnc

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
  <head>
<!--
 Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:

   - Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.

   - Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.

   - Neither the name of Sun Microsystems nor the names of its
     contributors may be used to endorse or promote products derived
     from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->

    <title>JMX(TM) "scandir" Example</title>
  </head>
  <body>
  
  <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>
  
  <h2><a name="h2-Introduction">Introduction</a></h2>
  <ul>
  <p>The JMX <i>scandir</i> example is an application that
     scans parts of a filesystem - e.g. a set of directories
     used by a number of lab machines when running tests - in
     order to clean up and optimize disk space by removing
     obsolete files - e.g. files that are leaked by the test
     suites running on those machines, like coredump files, or
     temporary files that might remain after a test crash.
     It could also serve as a basis for an application that
     would monitor disk usage and suggest removal of old big
     long-unaccessed files.
  </p>
  <p>The JMX <i>scandir</i> example does not however implement
     the full fledged logic that such an application might
     have. It implements a subset of this logic which is
     sufficient to demonstrate common patterns and
     solutions used when implementing a monitoring and
     management interface for an application with JMX
     Technology.</p>
  <p>This example is an advanced JMX example, which presents 
     advanced JMX concepts. It is assumed that the reader is already
     familiar with the JMX API. Newcomers to JMX Technology are
     invited to have a look at the <a
     href="http://java.sun.com/javase/6/docs/technotes/guides/jmx/"
     >JMX API Overview, Tutorial and Examples</a> before going any further.
  </p>
  <p></p>
      <hr>
  <blockquote>
    <u>Note:</u> This example was developed using <a 
     href="http://www.netbeans.org">NetBeans 5.0 IDE</a>. The instructions
     given in this document to build, run, and test the example assume that
     you have at your disposal:
     <ul><li>either <a href="http://www.netbeans.org">NetBeans 5.0 IDE</a>,</li>
         <li>or <a href="http://ant.apache.org/">Apache Ant 1.6.5</a> and 
             <a href="http://sourceforge.net/projects/junit/">JUnit 3.8.1 or
             3.8.2</a><br>
             (JUnit is only needed to run the example's unit tests).
         </li>
     </ul>
     <p><a name="setup">In order to build the example</a>, 
     <u>you may need to copy the jmx-scandir</u>
     directory to somewhere where you have write permissions. 
     <br>In that case, you will need to update the <i>nbjdk.home</i> variable
     in the copied <i><a href="build.properties">build.properties</a></i> 
     file located at the root of the copied project directory. 
     Please make sure that this variable points to the JDK 6 home directory.
     </p>
     <p>If you wish to run the testsuite from within the <a 
     href="http://www.netbeans.org">NetBeans IDE</a> you will also have
     to set the <i>libs.junit.classpath</i> variable in 
     <a href="build.properties">build.properties</a>. 
     The <i>libs.junit.classpath</i>  variable should point to your
     <a href="http://sourceforge.net/projects/junit/">junit.jar</a>, 
     version 3.8.1 or 3.8.2.
     </p>
  </blockquote>
     <hr>
     <p></p>
     <p><u>Table Of Contents:</u></p>
  <p><center>[<a href="#h2-Generating">Generating&nbsp;the&nbsp;Java&nbsp;Documentation</a>]
  [<a href="#h2-Overview">Overview&nbsp;of&nbsp;the&nbsp;<i>scandir</i>&nbsp;Example</a>]
  [<a href="#h2-API-Doc">API&nbsp;Documentation&nbsp;and&nbsp;Sources</a>]
  [<a href="#h2-Patterns">Patterns,&nbsp;Best&nbsp;Practices,&nbsp;and&nbsp;Common&nbsp;Pitfalls</a>]
  [<a href="#h2-Testing">Testing&nbsp;the&nbsp;<i>scandir</i>&nbsp;Example</a>]
  [<a href="#h2-Running">Running&nbsp;the&nbsp;<i>scandir</i>&nbsp;Example</a>]
  [<a href="#h2-Playing">Playing&nbsp;with&nbsp;JConsole</a>]
  [<a href="#h2-Turning">Turning&nbsp;the&nbsp;example&nbsp;into&nbsp;a&nbsp;Secure&nbsp;JMX&nbsp;Application</a>]
  [<a href="#h2-Connecting">Connecting&nbsp;to&nbsp;the&nbsp;Secure&nbsp;JMX&nbsp;Application</a>]
  [<a href="#h2-Conclusion">Conclusion</a>]
  [<a href="#h2-References">References</a>]</center></p>

  </ul>
  <h2><a name="h2-Generating">Generating the Java Documentation</a></h2>

    <ul>
        <p>Before reading further, you will need to generate the 
        Java Documentation for the example's sources.</p>
        <p>In the example root directory (where the <code>build.xml</code> 
           file is located) run the following command:
           <pre>ant javadoc</pre>
        </p>
        <p>Alternatively you can open the jmx-scandir project with the 
           NetBeans IDE and generate the Javadoc from its <code>Build</code>
           menu.
        </p>
        <p>If building the documentation fails, please make sure to read the 
           <a href="#setup">note</a> at the beginning of this document.</p> 
    </ul>
  
  <h2><a name="h2-Overview">Overview of the <i>scandir</i> Example</a></h2>
  
  <ul>
    <p>The JMX <i>scandir</i> example is built around the
    following MBeans:</p>
    <ul>
        <li>The first MBean we will present here is the
        <a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
        >DirectoryScannerMXBean</a>. <br>A
        <code>DirectoryScannerMXBean</code> is an MBean that scans a
        file system starting at a given root directory, and then looks
        for files that match the given criteria.  When such a file is
        found, the <code>DirectoryScannerMXBean</code> takes the
        action for which it was configured: emit a notification,
        <i>and/or</i> log a <code>record</code> for this file,
        <i>and/or</i> delete that file. The code that would actually
        delete the file is commented out - so that nothing valuable is
        lost if the example is run by mistake on the wrong set of
        directories.<br> <code>DirectoryScannerMXBeans</code> are
        created by the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
title="The ScanManagerMXBean is the main MBean of the scandir application"
        >ScanManagerMXBean</a> - see next item on the list, from its
        configuration.
        </li>
        <li>
            The <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
title="The ScanManagerMXBean is the main MBean of the scandir application"
            >ScanManagerMXBean</a> is the actual entry point of the
            application. It reads the application's
            configuration, and from that configuration,
            will create a <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManager.html"
title="The ResultLogManager is in charge of managing result logs"
        >ResultLogManager</a> and some <a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
        >DirectoryScannerMXBeans</a>.
            <br>The <code>ScanManagerMXBean</code> lets you start, stop, and
            schedule directory scans. The
            <code>ScanManagerMXBean</code> is a singleton
            MBean: there can be at most one instance of such
            an MBean registered in a given MBeanServer.
        </li>
        <li>The <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a> is an MBean which is able to
           load/save the configuration to/from an XML file. It
           will also let you modify that configuration - by e.g.
           creating new directory scanners in there.
           The corresponding MBeans will be created later, only 
           when you later
           ask the <code><a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a> </code> to apply the
           configuration again.<br>
           The <code>ScanDirConfigMXBean</code> is created by the
           <code>ScanManagerMXBean</code>, when the
           <code>ScanManagerMXBean</code> is registered.
           It is also possible to create an alternate
           <code>ScanDirConfigMXBean</code>, and to switch the
           <code>ScanDirConfigMXBean</code> to use one or the other
           configuration.
           <br>An example of XML configuration file is given
           <a href="src/etc/testconfig.xml"
           title="An Example Of Configuration"
           >here</a>. Although you could edit such a file by
           hand, it is easier to do it programmatically (or
           with <a href="#JConsole">JConsole</a>) through
           the <code>ScanDirConfigMXBean</code> interface.
        </li>
        <li>The <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
        >ResultLogManagerMXBean</a> is in charge of managing result logs.
        <br>Directory Scanners can be configured to log a
        <a
href="dist/javadoc/com/sun/jmx/examples/scandir/config/ResultRecord.html"
title="A ResultRecord contains information about a file matching the criteria of a Directory Scanner"
        >ResultRecord</a> whenever they take action upon a file that
        matches their criteria. The <code>ResultLogManagerMXBean</code> is
        responsible for logging these result records.
        The <code>ResultLogManagerMXBean</code> can be configured to log
        such records to a flat file, or into a log held in memory, or
        both. Both logs (file and memory) can be configured with a
        maximum capacity. 
        <br>When the maximum capacity of the memory
        log is reached, its first entry (i.e. its oldest entry) is
        removed to make place for the latest one.
        <br>When the maximum
        capacity of the file log is reached, the file is
        renamed by appending a tilde '~' to its name and a
        new result log is created. 
        <br>The <code>ResultLogManagerMXBean</code>
        will let you interactively clear these result logs, change their
        capacity, and decide where (memory or file) to log.
        The memory log is useful in that its content can be interactively
        returned by the <code>ResultLogManagerMXBean</code>, while
        the file log doesn't have this facility.<br>
        The result logs are intended to be used by e.g. an offline
        program that would take some actions on the files that
        matched the scan criteria:
        <br>The <i>scandir</i> application
        could be configured to only produce logs (i.e. takes no
        action but logging the matching files), and the real
        action could be performed by another program or module (e.g. mail the result log to the engineer who
        maintains the lab, or parse that log and delete all the
        files listed there, or parse the log and prepare and send
        a single mail to each owner of matching files, containing
        the list of files they should consider deleting).<br>
        The <code>ResultLogManagerMXBean</code> is a singleton
        MBean created by the <code><a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a> </code>
        which reads and writes its configuration from the
        <code><a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a></code>.
        </li>
    </ul>
    <p>An application <code>main()</code> method is
       provided in the <a 
       href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html"
       >ScanDirAgent</a> class. The <code>main()</code> simply registers 
       a <code><a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a> </code> in the platform MBeanServer, and
       then waits for someone to call <code>close()</code> on the
       <code>ScanManagerMXBean</code>.
    </p>
     <p>When the <code>ScanManagerMXBean</code> is registered, it
        will create a default <code><a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a></code> bound
        to a default XML config file.
     </p>
     <p>The application's default XML config file is determined as
        follows:
        <ol>
            <li>If the property <code>scandir.config.file</code> is
                defined, the default application file will be the
                file pointed to by this property. If that file
                doesn't exist, it will be created when 
                <code>ScanDirConfigMXBean.save()</code> is
                invoked.
            </li>
            <li>Otherwise the application config file is
                assumed to be a file called <code>jmx-scandir.xml</code>,
                located in the user's directory (as defined by
                the System property <code>user.home</code>). 
                If that file doesn't exists, it will be created when 
                <code>ScanDirConfigMXBean.save()</code> is
                invoked.
            </li>
        </ol>
        <p>It is worth noting that this project is defined to
           run with the following properties:
           <pre>-Djava.util.logging.config.file=logging.properties</pre>
           <pre>-Dscandir.config.file=src/etc/testconfig.xml</pre>
           With <code>ScanDirAgent</code> defined as the project's
           main class. Hence when you invoke from the NetBeans IDE 
           <i>Run Project</i> on the <i>jmx-scandir</i> project, 
           or <i>Run file</i> on the <code>ScanDirAgent</code>, the
           application starts with the test configuration provided in
           <a href="src/etc/testconfig.xml"
           title="An Example Of Configuration"
           >src/etc/testconfig.xml</a>
        </p>
  </ul>
  <h2><a name="h2-API-Doc">API Documentation and Sources</a></h2>
  <ul>
      <p>Once generated, the Javadoc of example classes can
      be found starting from <a href="dist/javadoc/index.html"
      title="The API Documentation"
      ><code>dist/javadoc/index.html</code></a>.</p>
      <p>You can view the sources in the <a
      href="src"
      title="The Example Source Tree"
      ><code>src</code></a> subdirectory.</p>
  </ul>
  <h2><a name="h2-Patterns">Patterns, Best Practices, and Common Pitfalls</a></h2>
  <ul>  
  <p>This section discusses some common patterns and
     design choices that this example demonstrates, and some pitfalls that
     it avoids.
  </ul>
  <h3>MBeans or MXBeans?</h3>
  <ul>
  <p>What is an MXBean? MXBeans made their appearance in
     J2SE 5.0 (Tiger), with the Management and Monitoring
     API of the JVM. However, Java SE 6 is the first
     Java SE release that contains a standard framework which
     makes it possible to create and register your own MXBeans.
  </p>
  <p>MXBeans are a special kind of MBean, which once registered
     in the MBeanServer, get automatically transformed into
     OpenMBeans. From a developer point of view, nothing changes:
     A Wombat MBean can become an MXBean simply by renaming
     its <code>WombatMBean</code> interface into <code>WombatMXBean</code>.</p>
  <p>Using MXBeans rather than plain Standard MBean brings its
     own advantages:</p>
     <ul>
         <li>
             Generic tools, like JConsole, will be able to
             display and interact with your MXBeans nicely, even
             if your MXBean interfaces reference custom types
             - e.g. custom Java enums. This is because all the types
             exposed by your MXBeans are converted to Open Types.
             Just look at the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
             >ScanDirConfigMXBean</a> with JConsole and you will
             understand the benefits.
         </li>
         <li>
             When writing a programmatic client, you can obtain
             a proxy that implements the original MXBean interface,
             and forget about the Open Type conversion.
             The JUnit unit tests that come with this example
             use this feature very widely. Have a look at them.
         </li>
         <li>
            The MXBean framework also lets you nicely navigate
            from one MXBean to another: your MXBeans can
            have attributes and parameters which are proxies
            to other MXBeans! We demonstrate this in the
            <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
title="The ScanManagerMXBean is the main MBean of the scandir application"
            >ScanManagerMXBean</a> which exposes a list
            of <code><a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
        >DirectoryScannerMXBean</a></code> and points
            towards a <code><a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a></code>.
         </li>
     </ul>
     <p>In short, MXBeans are so much easier to use that
        this example doesn't even have a single regular
        Standard MBean.
     </p>
     <p>See also <a
href="http://weblogs.java.net/blog/emcmanus/archive/2006/02/what_is_an_mxbe.html"
title="What is an MXBean?"
     >What is an MXBean?</a>
     and <a
href="http://weblogs.java.net/blog/emcmanus/archive/2006/06/intermxbean_ref.html"
title="Inter-MXBean references"
     >Inter-MXBean References</a>.
     </p>
     <blockquote><u>Hint:</u> In order to simplify the task of coding a 
        JMX programmatic client, we recommend that getters, setters, and
        operations defined in MBean and MXBean interfaces throw 
        <code>IOException</code>. Proxy objects will then be able
        to rethrow directly any <code>IOException</code> received from
        their underlying MBean Server connection, without wrapping
        them into <code>UndeclaredThrowableExceptions</code>.<br>
        Since the life cycle of the proxy object is not directly tied to 
        the life cycle of the MBean it proxies, you may also want to
        have all methods in the MBean or MXBean interface throw
        <code>InstanceNotFoundException</code> or more generally
        <code>JMException</code>.
    </blockquote>
  </ul>
  <h3>MBean Names - aka ObjectNames</h3>
  <ul>
  <p>As you must know if you've been studying JMX, MBeans are
     named objects. The names of MBeans are represented by
     instances of <code>ObjectName</code>. An ObjectName is
     composed of a <i>domain</i>, followed by a colon ':',
     followed by a comma-separated list of <i>key=value</i>
     pairs.<br>
     The ordering of the <i>key=value</i> pairs is not
     important, but <code>ObjectNames</code> are case sensitive
     (both keys and values are case sensitive) and <b>white space
     is not ignored</b>.<br>
     A common pitfall for JMX beginners is to inadvertently
     insert white space after commas into an ObjectName,
     and expect that two ObjectNames which differ only by such white
     space will be considered identical. This is not the
     case.<br>
     As an example, the ObjectName '<b><code>D:k1=v1, k2=v2, k3=v3</code></b>' has
     three keys, which are '<b><code>k1</code></b>', '<b><code> k2</code></b>',
     and '<b><code> k3</code></b>': beware
     of the space in the name of the second and third
     keys!<br>
     It is therefore a different ObjectName from
     '<b><code>D:k1=v1,k2=v2,k3=v3</code></b>' (the keys are now
     '<b><code>k1</code></b>', '<b><code>k2</code></b>', and
     '<b><code>k3</code></b>'), but the same ObjectName as
     '<b><code>D: k2=v2, k3=v3,k1=v1</code></b>', and yet different
     from '<b><code>D:k2=v2, k3=v3, k1=v1</code></b>'!
     <p>In this example, we are following the rules
        for ObjectName suggested in the <a
href="http://java.sun.com/products/JavaManagement/best-practices.html"
        >JMX Best Practices</a>:</p>
     <ul>
         <li>ObjectNames should be <a
         href="http://java.sun.com/products/JavaManagement/best-practices.html#mozTocId654884"
         >predictable</a>
         </li>
        <li>The domain part of our ObjectNames starts with a Java
            package name
        </li>
        <li>Our ObjectNames contain a <code>type=</code>
            key property. This property is different for every
            object type in our domain.
        </li>
        <li>For every ObjectName with a given type, we have the same set of key
            properties with the same syntax and semantics for their values - in
            fact we only use an additional <code>name=</code> key.
        </li>
        <li>When there can only be one instance of a given type
            there aren't any other key properties than <code>type=</code>.
            The ObjectNames of the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
title="The ScanManagerMXBean is the main MBean of the scandir application"
            >ScanManagerMXBean</a> and <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
        >ResultLogManagerMXBean</a>, which are both singleton MBeans, are
        composed in this way.
        </li>
        <li>When there can be several instances of a given type,
            we differentiate them by further key properties.
            To achieve this, we are using the most usual key property
            in addition to <code>type=</code>: the <code>name=</code> key.
            In this example, a key property list of the form
            <code>type=X,name=Y</code> is always enough to uniquely name
            an MBean. Tools like jconsole are usually aware
            of the semantics of the <code>type=</code> key and
            <code>name=</code> key, and are therefore able to
            display this form of name in a way that
            is easier to read than other name forms.
        </li>
     </ul>
     <p>The rules listed above are implemented by a couple
        of static helper functions in the <a
href="src/com/sun/jmx/examples/scandir/ScanManager.java"
title="ScanManager.java"
      >ScanManager</a> class. See the code of the
      <b><code>makeSingletonName</code></b> and
      <b><code>makeMBeanName</code></b> methods.
     </p>
  </ul>
  <h3>Inter MBean Navigation</h3>
  <ul>
  <p>One of the most common problems that needs to be solved
     when designing a management interface with JMX is to
     choose a representation for inter-MBean relationships.<br>
     Prior to Java 6, there were basically three possible
     choices:</p>
     <ul>
         <li><b>Make the relation appear in the ObjectName</b>.
             For instance, if MBean B was contained in
             MBean A, you could choose to name MBean B so
             that its parent relationship with MBean A
             appeared in its name. <br>
             The obvious limitation of this solution is that
             it only allows to model one such relation (an
             MBean has only one name) and the relation must
             be fixed - it cannot change during the life of
             the MBean since the name of an MBean cannot
             change.<br>
             This scheme is therefore mostly used when
             the application MBeans are modeling objects
             which are conceptually contained within
             each other in a tree-like structure.
             <br>For instance, most MBean names defined by 
             <a href="http://jcp.org/en/jsr/detail?id=77"
              >J2EE Management (JSR 77)</a> follow
              this scheme.
         </li>
         <li><b>Design getters and setters (or operations) which
             return <code>ObjectName</code> or
             <code>ObjectName[]</code> values</b>. The ObjectNames
             point to the MBeans which are related to that
             object. For instance , <a 
             href="http://glassfish.dev.java.net/"
             title="Open Source Java EE 5 Application Server"
             >GlassFish</a>
             defines MBeans which also use this pattern.
         </li>
         <li><b>Use the JMX RelationService</b>. The JMX RelationService
             is quite powerful, but simple relationships often
             do not justify that overhead.
         </li>
     </ul>
     <p>In Java 6, these three possibilities still remain, but
        the new MXBean framework brings up an interesting
        alternative. Instead of returning an ObjectName or
        an ObjectName array, <b>an MXBean can return a proxy</b>
        to its related MXBeans. This is how we have chosen to
        implement our inter MBean relationships in this
        example:
        <br>For instance the
        <code>ScanManagerMXBean</code>/<code>DirectoryScannerMXBean</code>
        relationship and the
        <code>ScanManagerMXBean</code>/<code>ScanDirConfigMXBean</code>
        relationships are implemented in this way.
        <p>
        The additional benefit, as compared to returning ObjectNames or
        using the RelationService is that interface type of the MBeans
        which are pointed to by the relationship becomes directly
        apparent. The method:
        <pre>
            public Map&lt;String,DirectoryScannerMXBean&gt; getDirectoryScanners();
        </pre>
        makes it immediately obvious that the MBeans to which we point are
        <a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
        >DirectoryScannerMXBeans</a>. It would have been much less obvious in prior
        versions of Java SE, were the returned type would have had to be
        <code>Map&lt;String,ObjectName&gt;</code>, or
        even worse just <code>Map</code>.
     </p>
     <p>However, it must be clear that the behaviour will be
        quite different when an MXBean is returned as compared
        to when a simple bean is returned.
     </p>
     <p>When an MXBean is returned, the remote client sees either
        an ObjectName, if it is a generic client like jconsole, or
        a proxy to a remote MXBean, if the client is working with the
        MXBean interface. Invoking an operation on one of the
        proxy returned by a method such as
        <code>getDirectoryScanners</code> will cause the
        MBean to be invoked on the remote server side.
     </p>
     <p>If <code>getDirectoryScanners</code> were
        defined as:
        <pre>
            public Map&lt;String,DirectoryScannerConfig&gt; getDirectoryScanners();
        </pre>
        then invoking a method on one of the returned objects
        would have absolutely no effect on the remote
        server side - because the returned objects in this
        case would simply be a bunch of serialized data objects.
     </p>
     <p>It is worth noting that although an MXBean interface
        can have getters and operations which return an MXBean
        interface, a regular standard MBean shouldn't have
        any getters or methods which return MBean interfaces or
        MXBean interfaces.
     </p>
     <p>For more information see also <a
href="http://weblogs.java.net/blog/emcmanus/archive/2006/06/intermxbean_ref.html"
title="Inter-MXBean references"
     >Inter-MXBean References</a>.
     </p>
  </ul>
  <h3>The MBeanRegistration interface, or how an MBean can
      know or provide its own name</h3>
  <ul>
      <p>
        Sometimes, an MBean needs to have a reference to the
        MBeanServer in which it is registered, or needs to know
        with which ObjectName it has been registered.
      </p>
      <p>
         Sometimes also, an MBean may need to perform some
         checks before being registered, or will need
         to carry out some actions right after it has been 
         successfully registered in the MBeanServer.
      </p>
      <p>
        Sometimes again, an MBean may need to perform some
        checks, or some cleaning actions, just before, or
        just after, it is unregistered.
      </p>
      <p>
      When an MBean has such needs, the easiest solution
      for it is to implement the <code>MBeanRegistration</code>
      interface.
      </p>
      <p>The <code>MBeanRegistration</code> interface is a callback 
      interface which defines pre and post registration and 
      unregistration callbacks.
      </p>
      <p>
       When an MBean implementing this interface is created
      (with <code>createMBean</code>) or registered 
      (with <code>registerMBean</code>) in an MBeanServer,
      the MBeanServer will call the <code>preRegister</code>
      and <code>postRegister</code> method implemented by
      the MBean. The <code>preRegister</code> method
      has an <code>MBeanServer</code> and <code>ObjectName</code>
      parameter, which are passed by the MBeanServer to the
      MBean. The MBean can store the reference it is being passed
      in a private instance variable for later use. 
      </p>
      <p>
      Most of the MXBeans we have defined in this example
      implement the <code>MBeanRegistration</code> interface. The table
      below show how our MBeans use this interface to control
      their own names, make sanity checks, perform 
      initialization steps or cleanup actions.
      </p>
      <p><br><center>
      <table border="1" cellpadding="4" cellspacing="2" 
             bgcolor="#eeeeee" width="95%">
          <thead>
              <tr bgcolor="#cecece">
                  <th width="20%">MBean Requirement</th>
                  <th>callback</th>
                  <th>use case example</th>
              </tr>
          </thead>
          <tbody>
              <tr>
                  <td bgcolor="#dedede">get a reference to the MBeanServer</td>
                  <td><code>preRegister</code></td>
                  <td bgcolor="#fafafa">The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a>  needs a reference
                  to the MBeanServer in order to create and
                  register other MBeans, such as the 
                  <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
        >ResultLogManagerMXBean</a>, and the 
                  <a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
        >DirectoryScannerMXBeans</a>.
                  </td>
              </tr>
              <tr>
                  <td bgcolor="#dedede">reject registration if conditions are
                      not met.
                  </td>
                  <td><code>preRegister</code></td>
                  <td bgcolor="#fafafa">The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html"
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a>  will throw
                  an IllegalArgumentException in <code>preRegister</code>
                  if the ObjectName it is being passed is
                  illegal. Throwing an exception in 
                  <code>preRegister</code> makes the registration fail.
                  </td>
              </tr>
              <tr>
                  <td bgcolor="#dedede">get my client-assigned MBean name</td>
                  <td><code>preRegister</code></td>
                  <td bgcolor="#fafafa">The <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a> propagates the
                  value of the <code>name=</code> property of 
                  the ObjectName it is given into its
                  ScanManagerConfig bean.  
                  </td>
              </tr>
              <tr>
                  <td bgcolor="#dedede">provide my own default ObjectName if none
                      was given to the MBeanServer
                  </td>
                  <td><code>preRegister</code></td>
                  <td bgcolor="#fafafa">The name that is returned by <code>preRegister</code>
                  is the ObjectName with which the MBean will be
                  eventually registered. 
                  The <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a> is able to suggest
                  a value for its own ObjectName if none was
                  provided. Similarly, the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a> 
                  always returns its singleton ObjectName
                  defined by <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html#SCAN_MANAGER_NAME" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean.SCAN_MANAGER_NAME</a>.
                  </td>
              </tr>
              <tr>
                  <td bgcolor="#dedede">perform initialization steps</td>
                  <td><code>preRegister</code></td>
                  <td bgcolor="#fafafa">The <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a> uses <code>preRegister</code>
                  to initialize its internal ScanManagerConfig bean.
                  </td>
              </tr>
              <tr>
                  <td bgcolor="#dedede">perform initialization steps, once it is
                  known that the registration was successful.
                  </td>
                  <td><code>postRegister</code></td>
                  <td bgcolor="#fafafa">The <code>postRegister</code> method 
                  can be used to implement
                  initialization steps that need to be done once it
                  is known that the registration was successful, or to
                  undo any action performed by <code>preRegister</code> once it
                  is known that registration was not successful.
                  The <code>postRegister</code> method has a Boolean parameter
                  which tells the MBean whether it was or wasn't
                  successfully registered in the MBeanServer.
                  The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a>  uses <code>postRegister</code> to create
                  and register other MBeans, such as the 
                  <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
        >ResultLogManagerMXBean</a> and the default
                  <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a>.
                  Note that <code>postRegister</code> is not expected to throw any
                  exception. If an exception needs to be thrown, it should
                  be thrown in <code>preRegister</code>.
                  </td>
              </tr>
              <tr>
                  <td bgcolor="#dedede">check whether the MBean can be deregistered</td>
                  <td><code>preDeregister</code></td>
                  <td bgcolor="#fafafa">The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a>  uses this method to verify
                   that its state allows it to be deregistered. 
                   In particular, it will refuse to be deregistered
                   if it is in the RUNNING or SCHEDULED state.
                   If <code>preDeregister</code> throws an exception, the unregisterMBean
                   call will fail and the MBean will remain registered in
                   the MBeanServer. 
                   Take particular care when implementing business logic
                   in this method: if the logic you implement has an 
                   unfortunate bug which makes it always throw an 
                   exception, you will never be able to unregister
                   that MBean.
                  </td>
              </tr>
              <tr>
                  <td bgcolor="#dedede">clean up resources, refusing to be deregistered if
                      it fails
                  </td>
                  <td><code>preDeregister</code></td>
                  <td bgcolor="#fafafa">The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a>  uses this method to unregister
                  all the other MBeans it has created and registered in the
                  MBeanServer. This includes the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
        >ResultLogManagerMXBean</a>, the 
                  <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBeans</a> it has created, and the 
                  <a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
        >DirectoryScannerMXBeans</a> it has created when
                  applying its configuration.
                  </td>
              </tr>
              <tr>
                  <td bgcolor="#dedede">clean up resources which need to be released in
                  a best-effort way, when it is known that the MBean is no
                  longer registered.
                  </td>
                  <td><code>postDeregister</code></td>
                  <td bgcolor="#fafafa"><code>postDeregister</code> is only called if the MBean was succesfully
                  unregistered.
                  The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a>  uses this method to cancel
                  its internal java.util.Timer.
                  </td>
              </tr>
          </tbody>
      </table>
      </center><br></p>
  </ul>
  <h3>The Singleton MBean Pattern</h3>
  <ul>
      <p>
        A singleton MBean is an MBean which can only have one
        instance registered in a given MBeanServer. <br>
        A singleton MBean usually has a well-known name,
        which can be defined as a constant. In that case,
        clients no longer need to call <code>new ObjectName(...)</code> 
        and catch the declared <code>MalformedObjectNameException</code>.
      </p>
      <p>There are already quite a few examples of singleton
         MBeans in the java.lang.management API. The 
         ThreadingMXBean, ClassLoadingMXBean, RuntimeMXBean, etc.
         are all singleton MBeans.
      </p>
      <p>In this example, we have two singleton MBeans:
         The <code><a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a></code> and the 
         <code><a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
        >ResultLogManagerMXBean</a></code>. But in fact,
         the only real singleton MBean is the 
        <code>ScanManagerMXBean</code>. The 
        <code>ResultLogManagerMXBean</code> just happens to
        be a singleton MBean because it has a 1-1 relationship
        with the <code>ScanManagerMXBean</code>.
      </p>
      <p>The <code>ScanManagerMXBean</code> implements the
         singleton MBean pattern in this way:
      </p>
      <ul>
          <li>The <code>ScanManagerMXBean</code> name has a single 
              key property: <code>type=ScanManagerMXBean</code>.</li>
          <li>Its name is defined by an ObjectName constant called
              <code>SCAN_MANAGER_NAME</code> in the <code>ScanManager</code> class</li>
          <li>The <code>ScanManagerMXBean</code> enforces its status of 
              singleton MBean. It will refuse to be registered
              with a name other than
              the <code>SCAN_MANAGER_NAME</code>. You can therefore depend on
              the fact that the <code>ScanManagerMXBean</code> will always 
              be registered with its singleton <code>SCAN_MANAGER_NAME</code>
              (see <code>preRegister</code>)
          </li>
          <li>You are not obliged to provide a name when you
              register the <code>ScanManagerMXBean</code>: if you pass null,
              then the <code>ScanManager</code> will be registered with
              its singleton <code>SCAN_MANAGER_NAME</code>
              (see <code>preRegister</code>).
          </li>
          <li>The <code>ScanManager</code> class has a no-arg static 
              <code>register</code> method that will register
              the singleton instance in the Platform MBeanServer.
              This static <code>register</code> method returns
              a proxy to the registered singleton.
          </li>
          <li>The <code>ScanManager</code> class has also a static 
              <code>register</code> method that will create
              a singleton instance in a (possibly remote)
              MBeanServerConnection - using 
              <code>createMBean</code>.
              This static <code>register</code> method 
              also returns a proxy to the registered singleton.
          </li>
          <li>Only the MBeanServer has a reference to the
              singleton instance. The singleton instance is
              not returned to the caller, and not kept
              in any other static data structure.
          </li>
      </ul>
      <p>
      On the other hand, the <code><a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
        >ResultLogManagerMXBean</a></code>
      has a much more relaxed implementation of the pattern:
      <br>It simply provides its own singleton name if it is
      registered with a null ObjectName, but will not enforce 
      the use of that name.
      </p>
      <p>Note that all singleton MBean names in this example
      are created using the <code>ScanManager.makeSingletonName</code>
      method, which implements the pattern for ObjectNames suggested
      in the JMX Best Practices.
      </p>
  </ul>
  <h3>Managing the Life Cycle of dependent MBeans</h3>
  <ul>
      <p>A common task that many JMX applications have
        is to manage the life cycle of MBeans registered
        in the MBeanServer.</p>
      <p>In this example, we have decided to follow a simple
      pattern:</p>
      <ul>
          <li>The application is initialized simply 
              by registering the singleton 
              <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a> in 
              the MBeanServer.
          </li>
          <li>The <code>ScanManagerMXBean</code> will then
              in turn register any other MBean that the 
              application might need:
              <ul>
                  <li>It creates and registers the singleton
                      <code><a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
        >ResultLogManagerMXBean</a></code>
                  </li>
                  <li>It creates and registers the default
                      <code><a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a></code>
                      which loads the initial configuration
                  </li>
                  <li>It creates as many 
                     <code><a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
        >DirectoryScannerMXBeans</a></code> as
                     needed when the configuration is applied
                  </li>
                  <li>It lets you create alternate 
                      <code>ScanDirConfigMXBean</code>, to
                      which you can later switch in order
                      to apply a new alternate configuration.
                  </li>
              </ul>
          </li>
          <li>When a new configuration is applied (or if the
              current configuration is reapplied), the 
              <code>ScanManagerMXBean</code> will unregister
              any <code>DirectoryScannerMXBeans</code> it has
              previously registered, and will re-create
              brand new <code>DirectoryScannerMXBeans</code>
              from the applied configuration.
          </li>
          <li>When you unregister the <code>ScanManagerMXBean</code>,
              it does all the cleanup for you, by unregistering
              all the MBeans that it has created during the
              course of the application.
          </li>
      </ul>
      <p>The <code>ScanManagerMXBean</code> makes use of its
         <code>MBeanRegistration</code> interface in order
         to register the other MBeans it needs (see the
         <code>ScanManager.postRegister</code> method) and to unregister
         every MBean it has created (see the <code>ScanManager.preDeregister</code>
         method).
      </p>
      <p>You will note that the <code>ScanManagerMXBean</code>
         will only allow itself to be deregistered if it can be 
         closed - that is if there's no other action in
         progress. 
         This is to make sure that the deregistration of
         dependent MBeans will work smoothly. 
         <br>
         The deregistration of related MBeans will happen
         in the <code>ScanManager.preDeregister</code>
         method.
         <br>
         If one of these MBeans could not be deregistered,
         then the <code>ScanManagerMXBean</code> will throw
         an exception, refusing to be deregistered.
         <br>This leaves you a chance to try to deregister it
         again later. Since the <code>ScanManagerMXBean</code>
         has switched its state to CLOSED before starting
         to unregister its dependent MBeans, it will refuse
         any further actions, ensuring that e.g. nobody
         can try to start it or schedule it while it
         is in that partially-deregistered state.
      </p>
      <p>Handling the LifeCycle of all the application's
         MBeans in a single MBean is usually a good design
         pattern, especially if the application is a 
         module which is intended to share a JVM - or
         an MBeanServer - with other modules.
      </p>
      <p>This is specially useful if the application needs to
         be loaded and unloaded on demand: in that 
         case, simply registering or unregistering the top level 
         MBean (in our example the <code>ScanManagerMXBean</code>) does
         the trick.
      </p>
  </ul>
  <h3>Emitting Notifications</h3>
  <ul>
       <p>In order to emit notifications, an MBean must be
       an instance of <code>NotificationEmitter</code>. 
       The <code>NotificationEmitter</code> interface defines methods 
       that the MBeanServer will call on the MBean in order
       to register <code>NotificationListeners</code> with the MBean.
       </p>
       <p>It is worth noting that the MBean may not be
          invoked each time a JMX client wants to register
          a listener. For instance, the RMIConnectorServer
          registers <i>only once</i> a single listener with each MBean 
          which is a <code>NotificationEmitter</code>.
          In that specific case, the listener may even be registered
          with the MBean before any client has actually subscribed
          for notifications from that particular MBean.
       </p>
       <p>An MBean can therefore make no assumption about 
          which client or how many clients have registered for
          notifications.
       </p>
       <p>It is also worth noting that the logic of the
       methods defined in <code>NotificationEmitter</code> would not
       be trivial to implement from scratch. Fortunately
       the JMX API defines a helper class, called 
       <code>NotificationBroadcasterSupport</code>, which 
       provides an implementation for these methods.
       </p>
       <p>There are actually three ways for an MBean to
       implement <code>NotificationEmitter</code>, of which only two
       are recommended.
       </p>
  </ul>

  <h4>Extending NotificationBroadcasterSupport</h4>
  <ul>
    <p>This is the simplest way of coding an MBean which
       is a <code>NotificationEmitter</code>:
    </p>
    <p>Simply extend <code>NotificationBroadcasterSupport</code>,
    then override its <code>getNotificationInfo</code> method
    which returns the <code>MBeanNotificationInfo[]</code> array
    that should be included in your MBean's <code>MBeanInfo</code>
    and that's it. 
    <br>You just need to call the <code>sendNotification</code> method
    inherited from <code>NotificationBroadcasterSupport</code> whenever
    your MBean needs to send a notification.
    </p>
    <p>In our example, both the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
           >ScanDirConfigMXBean</a> and <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
        >ResultLogManagerMXBean</a> extend 
      <code>NotificationBroadcasterSupport</code> in order
      to send notifications.
    </p>
  </ul>
  <h4>The Delegation Pattern: delegating to a 
      NotificationBroadcasterSupport delegate</h4>
  <ul>
      <p>There may be cases however where delegating to a
      wrapped <code>NotificationBroadcasterSupport</code> 
      object may be preferred to extending 
      <code>NotificationBroadcasterSupport</code>.
      </p>
      <p>For instance, if your MBeans already derive from
      some base class, extending <code>NotificationBroadcasterSupport</code>
      might not be an option.
      </p>
      <p>Similarly, if you do not want to have the inherited 
      <code>public void sendNotification(Notification notification)</code>
      method appear in the Javadoc of the concrete class of your
      MBean, you may want to consider using the delegation
      pattern instead of extending 
      <code>NotificationBroadcasterSupport</code>
      </p>
      <p>In our example both the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a> and the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
        >DirectoryScannerMXBean</a> use the delegation 
       pattern rather than extending 
       <code>NotificationBroadcasterSupport</code>.
       In the end, choosing between one or the other method
       is more a question of taste, although the delegation 
       pattern could be considered more flexible since it
       doesn't require extending any given superclass.
      </p>
      <p>It may be also worth noting that some tools like
      the JMX Module of <a 
href="http://www.netbeans.org"
      >NetBeans IDE</a>, will be able to 
      generate for you all the code that delegates to a
      wrapped <code>NotificationBroadcasterSupport</code>.
      </p>
  </ul>
      
  <h4>Implementing NotificationEmitter from scratch</h4>
  <ul>
    <p>This is the last possibility for an MBean that
    needs to send notifications: simply implement 
    <code>NotificationEmitter</code> from scratch. This is highly
    discouraged since that logic is not trivial, and 
    already provided by 
    <code>NotificationBroadcasterSupport</code> anyway.
    </p>
  </ul>
    
  <h4>Beware of Synchronization Locks</h4>
  <ul>
       
       <p>One thing you must keep in mind when sending
       notifications is not to send them from within
       a synchronized block, or while holding a lock on
       some resource.</p>
       <p>Indeed, what happens when you send a notification
          may vary greatly depending on whether the client
          which has registered for notifications has done
          so through a <code>JMXConnector</code> (like the 
          <code>JMXRMIConnector</code>)
          or through a direct reference to the MBeanServer
          (by calling 
          <code>MBeanServer.addNotificationListener</code>).
       </p>
       <p>In this latter case, the listener will be invoked
       synchronously in the same thread that your MBean is
       using to send its notification. If by misfortune, the
       code of that listener now re-enters your MBean through a
       call that flows through a JMXConnector, a deadlock
       could occur. It is therefore very important to release
       any lock you may have before calling 
       <code>sendNotification</code>.</p>
       <p>An easy way to do that is demonstrated in the
          <code>ScanManager</code> class. The ScanManager
          has an internal private queue of pending notifications.
          When a notification needs to be sent (e.g. because the
          ScanManager state is being switched), the notification
          is simply prepared and put into the pending notification
          queue. 
          The notification queue is then processed later on, 
          at the end of the method, when the processing is finally
          completed and all the locks have been released.
          <br>At this point the notification queue might already
          have been emptied by another thread - in which case
          the pending notifications will have already been
          removed from the queue. Which thread actually gets 
          to send the notifications is of no importance. The 
          important point is that all the locks detained by
          your MBean code in that thread were released before
          the notification was sent.
       </p>
       <p>In our example the <code>ScanManager</code> class 
          ensures this by:
          <ul>
              <li>Only calling <code>sendNotification</code>
                  in its private <code>sendQueuedNotifications</code>
                  method.
              </li>
              <li>Only calling <code>sendQueuedNotifications</code>
                  when all locks have been released.
              </li>
              <li>Never calling a method that calls 
                  <code>sendQueuedNotifications</code> from within
                  a synchronized block.</li>
          </ul>
       </p>
  </ul>
       
       

  <h4>Don't subclass Notification</h4>
  <ul>
       <p>Another common best practice when you want
          to improve interoperability is to use directly
          the Notification base classes provided in the
          JMX<sup>TM</sup> API. Do not create your own
          subclasses of these standard classes.
       </p>
       <p>Indeed, if you code your own subclass, a generic
       client, like jconsole, will not be able to receive
       that notification unless it has that custom 
       subclass in its classpath.
       </p>
       <p>
       If you want your application to be interoperable, it is
       therefore preferable not to subclass any of the standard
       Notification classes. You can define your own 
       Notification type string, and if you need to send
       additional data, you can put a CompositeData, or a 
       HashMap of serializable standard types in the 
       Notification's user data fields.
       </p>
       <p>In this example, we are using directly the 
       standard notification classes:
       <ul>
           <li>The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a> and the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
             >DirectoryScannerMXBean</a> both use directly
             <code>AttributeChangeNotification</code> to notify
             changes in their <code>State</code> attribute.
           </li>
           <li>The <a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
             >DirectoryScannerMXBean</a>
             also uses the base <code>Notification</code>
             class directly in order to notify whenever
             it finds a matching file.
             <br>In that case, we simply use the base
             <code>Notification</code>
             class with a new 
             <b><code>com.sun.jmx.examples.scandir.filematch</code></b>
             type.
           </li>
           <li>The <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
             >ScanDirConfigMXBean</a> and <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html"
title="The ResultLogManagerMXBean is in charge of managing result logs"
             >ResultLogManagerMXBean</a> also both use the base 
             <code>Notification</code> class.
           </li>
       </ul>
       <p>Careful readers will have noted that the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
             >ScanManagerMXBean</a> and the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html"
title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root."
             >DirectoryScannerMXBean</a> both use the 
             <code>AttributeChangeNotification</code> class
             to notify about their state change, whereas the
             <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
             >ScanDirConfigMXBean</a> uses the base
             <code>Notification</code> class.
       </p>
       <p>In fact, this is because the semantics of these
          notifications is not exactly the same - although
          both denote a state change:
          <ul>
              <p>In the case of <code>ScanManagerMXBean</code>
              and <code>DirectoryScannerMXBean</code>, the 
              notification which is emitted is more about a
              state transition, from one state to another.
              For instance, going from <code>RUNNING</code>
              to <code>STOPPED</code>, or from 
              <code>SCHEDULED</code> to <code>STOPPED</code>.
              <br>In that case, the 
              <code>AttributeChangeNotification</code> was
              more appropriate because it made it possible
              to send the previous and the new value of the 
              state attribute, thus reflecting the whole
              state transition.
              </p>
              <p>In the case of the <code>ScanDirConfigMXBean</code>
              however, what is of interest is the state in
              which the MBean has arrived. Using the base
              <code>Notification</code> class with three different 
              notification type strings -  
              <b><code>com.sun.jmx.examples.scandir.config.loaded</code></b>,
              <b><code>com.sun.jmx.examples.scandir.config.modified</code></b>,
              and
              <b><code>com.sun.jmx.examples.scandir.config.saved</code></b> - 
              was therefore closer to what we wanted to model.
              </p>
          </ul>
       </p>
  </ul>
       
  <h3>Configuration MBeans</h3>
    <ul>
    <p>A common practice when designing a management application is
    to have an MBean, or a set of MBeans, dedicated to configuration. 
    Separating configuration from control and monitoring allows
    more appropriate logic, and often simplifies the design and 
    implementation of the management interface.
    </p>
    <p>
    In our example, the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
     >ScanDirConfigMXBean</a> is dedicated to the application configuration.
    </p>
    <p>The <code>ScanDirConfigMXBean</code> will let you interactively 
        modify, save, or load the application configuration. The modifications
        will not be taken into account until it is applied, by invoking
        <code>applyConfiguration</code> on the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
        >ScanManagerMXBean</a>. 
    It is also possible to create many configurations, by creating as
    many <code>ScanDirConfigMXBean</code>s, and then to choose and apply
    one of these configurations by calling 
    <code>ScanManagerMXBean.setConfigurationMBean</code> and then
    <code>ScanManagerMXBean.applyConfiguration</code>.
    </p>
    <p>In this way, all configurations aspects are gathered and concentrated
    inside the <code>ScanDirConfigMXBean</code> instead of being scattered
    throughout all the MBeans that compose the application.
    </p>
    <p>In order to save and store the application configuration data, the
    <code>ScanDirConfigMXBean</code> uses a set of XML serializable Java beans
    defined in the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/config/package-summary.html" 
title="The com.sun.jmx.examples.scandir.config package defines XML serializable beans"
        >com.sun.jmx.examples.scandir.config</a> package. These beans are very
   simple Java beans which have been lightly annotated for XML binding.
    </p>
    <p>It is worth noting that these same beans can also be handled by the
    MXBean framework (our beans don't contain recursive data structures) and can 
    therefore be used directly as attributes and parameters of MXBeans, without
    needing to be Java-serializable (the MXBean framework transform them in
    CompositeData objects - which <b>are</b> serializable).
    </p>
    <p>The same <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/config/ScanManagerConfig.html" 
title="The com.sun.jmx.examples.scandir.config package defines XML serializable beans"
        >ScanManagerConfig</a> bean that we use to read from and write to the
        XML configuration file is thus also used as attribute of the <a
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html"
title="The ScanDirConfigMXBean is in charge of the configuration"
     >ScanDirConfigMXBean</a>. It is transformed into a <code>CompositeData</code> 
       by the MXBean framework, and can be easily introspected with
       <a href="#JConsole">jconsole</a>.
    </p>
    </ul>
  <h3>MBeans Must Be Thread-Safe</h3>
    <ul>
    <p>A question often asked by newcomers to JMX technology
    is whether the MBeanServer is thread-safe. Well, the MBeanServer <b>is</b> 
    thread safe, but it doesn't put any locks on the MBeans it contains. The
    MBeans can be concurrently accessed by multiple threads, and must therefore
    take care of their own thread safety.
    </p>
    <p>In this example, we have been using two methods to ensure thread
    safety for our MBeans: synchronized blocks, and semaphores.
    </p>
    <p>Using synchronized blocks is probably the most common and easiest way
    to implement thread safety in Java. When dealing with MBeans though, here
    are a couple of rules to keep in mind:
    <ul>
        <li>Don't send notifications from within a synchronized block: there's
        no way to tell whether the listener's code will be executed in the
        same thread or a different thread, and holding a lock in these
        conditions is therefore dangerous, as it could lead to deadlocks.</li>
        <li>Also avoid invoking another MBean from a synchronized block
        unless you are completely in control of both MBeans, and you can
        ascertain that it won't lead to any deadlock. Indeed, if you invoke an
        MBean exposed by another application, it can be sometime hard to
        know with certainty whether holding a lock while invoking that
        MBean will have any side effect. Maybe that MBean will make
        further calls to other MBeans which will in turn try to call
        your MBean, or maybe it will emit a
        notification, and we'll be back to the considerations just 
        above.</li>
    </ul>
    </p>
    <p>Another means of implementing thread-safe code is to use semaphores.
    The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
        >ScanManagerMXBean</a> uses a semaphore called
        <code>sequencer</code> to ensure
    that critical code sections are not executed concurrently. In this
    MBean, we use <code>Semaphore.tryAcquire</code> to lock the sequencer
    semaphore before entering the critical section. If the 
    <code>Semaphore.tryAcquire</code> returns true then we enter the critical
    section. If it returns false, we throw an IllegalStateException, stating
    that we couldn't acquire the lock. The code looks like this:
    <pre>
        if (!sequencer.tryAcquire())
            throw new IllegalStateException("resource locked");
        try {
            // critical code here ...
        } finally {
            // Always use try/finally to ensure that the semaphore
            // will be released, even if exceptions or errors are raised!
            sequencer.release();
        }
    </pre>
    </p>
    <p>Using <code>Semaphore.tryAcquire</code> and throwing an exception if
        the semaphore is already locked makes it safer to call other MBeans
        from within the critical section: in potential deadlock situations
        the calling code will get the <code>IllegalStateException</code>
        instead of being blocked on the deadlocked lock.
    </p>
    <p>It is worth noting that each of these techniques has its own 
    advantages and disadvantages - which can make one of them more or less
    appropriate depending on the inner logic of the MBean you're implementing.
    </p>
    <p>Careful readers will also have noted that we used 
       <code>IllegalStateException</code> directly, instead of defining 
       our own subclass of RuntimeException, which could have had a more
       precise semantics. If you define a new exception for your JMX application,
       you must keep in mind that your client will need to have the class
       of your exception in its classpath to get that exception. 
       Otherwise your client will get a completely different exception, indicating a
       deserialization issue.
    </p>
    </ul>
    
  <h3>Waiting for Notifications</h3>
    <ul>
    <p>Implementing code that needs to wait for notifications is sometimes
       difficult. Because notifications are asynchronous, doing something
       like:
        <pre>
          // register a notification listener
          ...
          // start a management action
          ...
          // wait for a notification
          ...
          // do something based on whether the expected notification
          // is received
          ...
        </pre>
       is not always trivial. However, there's a very easy way to do that: use
       a blocking queue of notifications.
       <pre>
       final BlockingQueue&lt;Notification&gt; notifQueue = 
                new LinkedBlockingQueue&lt;Notification&gt;();
                
       final NotificationListener listener = new NotificationListener() {
            public void handleNotification(Notification notification,
                                           Object handback) {
                try {
                    // Just put the received notification in the queue.
                    // It will be consumed later on.
                    //
                    notifQueue.put(notification);
                } catch (InterruptedException ex) {
                    // OK
                }
            }
          };

       // register the listener - possibly also as a JMXConnectionNotification
       // listener to get Notification Lost notification
       ...
       // start management action
       ...
       // wait for notification
       while (expected notif not received and delay not expired) {
            Notification n = notifQueue.poll(3,TimeUnit.SECONDS);
            // if expected notif, do something
            ...
       }
       // if expected notification not received do something else.
       ....
       </pre>
    </p>
    <p>You will note that this is a technique we've been using in the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html" 
title="The ScanDirAgent class defines a main method for the scandir application"
        >ScanDirAgent</a> class and in the example unit tests.
    </p>
    </ul>
    
  <h3>Holding hard references to other MBeans: proxy or direct reference?</h3>
  <ul>
    <p>We have seen that MXBeans will let you return proxy references to other
    MXBeans. But should that MXBean hold a direct reference to the MXBeans it
    relates to, or would it be better for it to hold only a proxy?
    </p>
    <p>
    As a general rule it is better when an MBean reference is
    only held by the MBeanServer. It is a better design
    to hold a reference to a proxy, rather than to hold
    a hard reference to an MBean. However there are two cases
    when holding a hard reference might be preferred: 
     <ol>
        <li>When MBean A needs to call a method of method B which
           is not part of its MBean interface</li>
        <li>When the overhead of going through the MBeanServer
           plus the MXBean framework is too great (frequently-called
           method, with creation of OpenType)</li>
     </ol>
    However - holding a hard reference is only advisable
    when both MBeans are created by the same piece of code,
    and the application can ensure that the life cycle
    of each MBean is consistent with regard to the other.
    </p>
    <p>In our example, the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
        >ScanManagerMXBean</a> holds only proxy references to the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" 
        >ScanDirConfigMXBean</a> and the  <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" 
        >DirectoryScannerMXBeans</a>. <br>
    However it holds a direct reference to the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManager.html" 
        >ResultLogManager</a>. This makes it possible to pass a direct 
        reference to the <code>DirectoryScannerMXBeans</code>, 
        which can then log their results
        more efficiently, and would also make it possible to remove
        the <code>log</code> method from the <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" 
        >ResultLogManagerMXBean</a> interface - leaving it in the 
        <code>ResultLogManager</code> class (possibly as a package method)
        should we wish to do so.
    </p>
    
    </ul>

  <h3>Agent Class</h3>
    <ul>
   <p>The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html" 
title="The ScanDirAgent class defines a main method for the scandir application"
     >ScanDirAgent</a> is the Agent class for the <i>scandir</i> application.
    This class contains the <code>main</code> method to start a standalone  
    <i>scandir</i> application.
    </p>
    <p>The <code>main</code> method simply registers a <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
       >ScanManagerMXBean</a> in the platform MBeanServer, and then waits
    for someone to call <code>ScanManagerMXBean.close</code>.
    </p>
    <p>
    When the <code>ScanManagerMXBean</code> state is switched to 
    <code>ScanManagerMXBean.ScanState.CLOSED</code>, the 
    <code>ScanManagerMXBean</code> is unregistered, and the application
    terminates (i.e. the main thread completes).
    </p>
    <p>Standalone JMX applications usually have an Agent class that contain 
       their <code>main</code> method, which performs all the MBean
       registration steps.
       However, it is usually not a bad idea if that class can
       be easily turned into an MBean. Indeed, this will make your
       application easier to integrate in an environment where it would
       no longer be standalone and would no longer control the implementation
       of <code>main</code>. In our example the Agent
       class could be easily turned into an MBean, exposing its three
    <code>init</code>, <code>waitForClose</code> and <code>cleanup</code> 
    method. However we didn't go as far as turning it into an MBean since 
    the application can be already easily started by registering an instance
    of <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" 
title="The ScanManagerMXBean is the main MBean of the scandir application"
       >ScanManagerMXBean</a>.
    </p>
    </ul>
  <h3>Secure Client Class</h3>
    <ul>
   <p>The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html" 
title="The ScanDirClient class is a very short example of secure programatic client"
     >ScanDirClient</a> is an example class that shows how a
    programmatic client can connect to a secured <i>scandir</i> application.
    This class contains a <code>main</code> method which creates and
    configures a <code>JMXConnector</code> client to connect with
    a secured <i>scandir</i> daemon. This class will not work with
    the default unsecured agent since it requires mutual authentication.
    </p>
    <p>How to secure a JMX <i>scandir</i> application and run
    the secure <code>ScanDirClient</code> is discussed <a href="#secure"
    >later</a> in this document.
    </p>
    <p>The <code>ScanDirClient</code> is not really part of the
       application - and is given here only for the sake of
       the example.
    </p>
    </ul>
    
  <h2><a name="h2-Testing">Testing the <i>scandir</i> Example</a></h2>
    <ul>
        <p>Make sure that you have access to junit.jar (either 3.8.1 or 3.8.2).
           Make sure also that you have junit.jar in your 
           <code>CLASSPATH</code>.<br>
           Then in the example root directory (where the <code>build.xml</code> 
           file is located) run the following command:
           <pre>ant test -Dlibs.junit.classpath=<i><u>path to junit jar (either 3.8.1 or 3.8.2)</u></i></pre>
        </p>
        <p>Alternatively you can open the jmx-scandir project with the 
           NetBeans IDE and test the jmx-scandir project from the 
           <code>Run</code> menu.
        </p>

    </ul>

  <h2><a name="h2-Running">Running the <i>scandir</i> Example</a></h2>
    <ul>
        <p>In the example root directory (where the <code>build.xml</code> 
           file is located) run the following commands:
        <pre>ant jar
ant run-single -Drun.class=com.sun.jmx.examples.scandir.ScanDirAgent -Djavac.includes=src</pre>
           or simply <pre>ant run</pre>
        </p>
        
        <p>This will run the example using the configuration
           file provided in the src/etc directory.
        </p>
        <p>Alternatively you can open the jmx-scandir project with the 
           NetBeans IDE. You can run the example by 
           selecting the <code>ScanDirAgent</code> file
           and run it with <code>Run File</code> in the
           <code>Run</code> menu or simply
           set the <i>jmx-scandir</i> project as main project and
           select <code>Run Main Project</code> from the
           main menu. Both targets will use the configuration
           file provided in the src/etc directory.
        </p>
        <p>When the application is started, you can connect to
           it with <a href="#JConsole">jconsole</a>.
        </p>
        <blockquote>
            <u>Note:</u> You can also run the <i>scandir</i> 
            application directly from the <code>java</code> 
            command line. Make sure to build the project jar
            first. 
            <br>On Unix systems:
            <pre>ant jar
java -Djava.util.logging.config.file=logging.properties \
     -Dscandir.config.file=src/etc/testconfig.xml \
     -jar dist/jmx-scandir.jar</pre>
            <br>On Windows systems:
            <p><code>ant jar<br>
java &nbsp;-Djava.util.logging.config.file=logging.properties
     &nbsp;-Dscandir.config.file=src\etc\testconfig.xml
     &nbsp;-jar&nbsp;dist\jmx-scandir.jar</code></p>
        </blockquote>
    </ul>
    
    <h2><a name="h2-Playing">Playing with JConsole</a></h2>
    <ul>
    <p>Run the example as explained in the previous section, so
    that it uses the provided <code>src/etc/testconfig.xml</code> 
    configuration file. Then start
    jconsole. In the connection window choose the process that runs
    <code>com.sun.jmx.examples.scandir.ScanDirAgent</code> or
    <code>jmx-scandir.jar</code>.
    </p>
    <p><center>
        <table border="0" cellpadding="2" cellspacing="2">
        <tr><td>
    <a href="docfiles/connect-local-ant-run.jpg"
    title="jconsole connection window - connect to local process"
    ><img height="440"
    src="docfiles/connect-local-ant-run.jpg"
    alt="jconsole connection window - connect to local process"
    /></a>
    </td>
    <td>
    <a href="docfiles/connect-local-java-jar.jpg"
    title="jconsole connection window - connect to local process"
    ><img height="440"
    src="docfiles/connect-local-java-jar.jpg"
    alt="jconsole connection window - connect to local process"
    /></a>
    </td></tr></table>
    </center>
    </p>
    <p>Open the MBeans tab, and look for the 
       <code>ScanDirConfigMXBean</code>.
       Click on its <code>Attributes</code> node and double click on its
       <code>Configuration</code> attribute, to look at
       the loaded configuration - values in bold can
       be expanded by a double-click.
    </p>
    <p><center><a href="docfiles/scandir-config.jpg"
    title="jconsole MBean tab: ScanDirConfigMXBean"
    ><img 
    src="docfiles/scandir-config.jpg"
    alt="jconsole MBean tab: ScanDirConfigMXBean"
    /></a></center>
    </p>
    <p>Now go to the <code>ScanManagerMXBean</code>, click on
       its <code>Notifications</code> node, and subscribe
       for notifications. Then click on the 
       <code>Operations</code> node and invoke the
       <code>start()</code> operation:
    </p>
    <p><center><a href="docfiles/scandir-start.jpg"
    title="jconsole MBean tab: ScanDirConfigMXBean"
    ><img 
    src="docfiles/scandir-start.jpg"
    alt="jconsole MBean tab: ScanDirConfigMXBean"
    /></a></center>
    </p>
    <p>You can see that the notifications counter was 
       incremented by three: you have just scheduled, 
       run, and completed a batch of directory scans.
    </p>
    <p>Now go to the <code>ResultLogManagerMXBean</code>,
       click on its <code>Attributes</code> node, and 
       expand its <code>MemoryLog</code> attribute:
    </p>
    <p><center><a href="docfiles/scandir-result.jpg"
    title="jconsole MBean tab: ScanDirConfigMXBean"
    ><img 
    src="docfiles/scandir-result.jpg"
    alt="jconsole MBean tab: ScanDirConfigMXBean"
    /></a></center>
    </p>
    <p>You can see that the directory scan results have
       been logged.</p>
    <p>To make the application terminate go back to the 
       <code>ScanManagerMXBean</code> and invoke
       <code>close()</code>. The <code>ScanDirAgent</code>
       will receive the notification, step out of 
       the application main thread, and the application
       will terminate.
    </p>
    <p>This is of course a very limited scenario. Feel free
    to improvise with all the features of the example, creating
    a new configuration - 
    <code>ScanManagerMXBean.createOtherConfigurationMBean</code> -
    adding multiple directory scanners to that configuration -
    <code>ScanDirConfigMXBean.addDirectoryScanner</code> -
    then switching the <code>ScanManagerMXBean</code> current
    configuration by changing the value of the <i>ConfigurationMBean</i>
    attribute - <code>ScanManagerMXBean.setConfigurationMBean</code>
    - then applying the new configuration - 
    <code>ScanManagerMXBean.applyConfiguration(true)</code> - 
    then scheduling repeated directory scans every 10 seconds - 
    <code>ScanManagerMXBean.schedule(0,10000)</code> - 
    subscribing for notifications, etc...
    </p>
    </ul>
    
  <a name="secure"></a>
  <h2><a name="h2-Turning">Turning the example into a Secure JMX Application</a></h2>
    <ul>
    <p>In this section, we will see how to configure and
    start the <i>scandir</i> example so that the JVM agent
    is bootstrapped with a secure JMXConnectorServer. Indeed, until 
    now we have only used the insecure local connection, 
    which can only be used as long as both the client and
    the server run on the same machine. This section will
    explain how to start the <code>ScanDirAgent</code> so 
    that a real secure RMIConnectorServer is started at bootstrap.
    </p>
    <p>To achieve this we will: <a href="#management.properties"
        >provide our own management.properties</a>, <a 
        href="#password-access">create our own password and access files</a>,
        <a href="#keystore-truststore">provide a keystore and truststore</a>,
        <a href="#start-secure-agent">start the ScanDirAgent with the
        appropriate system properties</a>.
    </ul>
    <h3>Configuring the JVM Agent for Secure Remote Connection</h3>
    <ul>
        <p>The easiest way to <a name="management.properties">configure the 
            JVM Agent</a> for Secure Remote 
           Connection is to use your own <a
           href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#properties"
           title="This page describes the properties you can put in your management.properties file"
           >management.properties</a> file.
           In this example, we have copied the default 
           <code>$JRE/lib/management/management.properties</code>
           file to the example's <code>src/etc</code> directory and
           modified it in <a href="src/etc/management.properties"
           title="our modified management.properties"
           >this way</a>:
           <ul>
               <li>We have set the RMI port to <u>4545</u> - this is just a 
                   random port number we have picked up. Feel free to use your 
                   own value suited to your environment.
               <pre># For setting the JMX RMI agent port use the following line
com.sun.management.jmxremote.port=<b>4545</b></pre>
               </li>
               <li>We have <u>switched on</u> SSL <u>mutual authentication</u>
               <pre># For RMI monitoring with SSL client authentication use the following line
com.sun.management.jmxremote.ssl.<b>need.client.auth</b>=<b>true</b></pre>
               </li>
               <li>We have also <u>secured the RMI Registry</u> with SSL
               <pre># For using an SSL/TLS <b>protected</b> RMI Registry use the following line
com.sun.management.jmxremote.<b>registry.ssl</b>=<b>true</b></pre>
               </li>
               <li>We have provided <a 
                href="src/etc/password.properties">our own password file</a>
               <pre># For a non-default password file location use the following line
com.sun.management.jmxremote.password.file=<i>src/etc/password.properties</i></pre>
               </li>
               <li>We have provided <a 
                href="src/etc/access.properties">our own access file</a>
               <pre># For a non-default password file location use the following line
com.sun.management.jmxremote.access.file=<i>src/etc/access.properties</i></pre>
               </li>
           </ul>
           <p>You will note that we haven't provided any value
              for the other security properties, like 
              <code>com.sun.management.jmxremote.authenticate=true</code>,
              because these properties already default to a value
              which enables security by default. 
              Note however that protecting the RMI Registry with SSL
              improves the application security, but only as long as
              mutual authentication is also switched on. Otherwise, just
              anybody would be able to connect to the registry and 
              get the RMIServer stub.
           </p>
           <p>We do recommend that you <u>use the most secure configuration
              when you deploy a JMX agent</u> - which means <u>switching on
              SSL protection for the RMI registry</u> <b>and</b> <u>requiring
              mutual authentication</u>, as we show in this example.
           </p>
           <p>We will use the <code>com.sun.management.config.file</code>
           system property to pass our <a 
           href="src/etc/management.properties">management.properties</a>
           file to the <code>ScanDirAgent</code>.
           </p>
    </ul>
    
    <h3>Creating a password and access file</h3>
    <ul>
        <p>As explained above, we have created our own
        <a href="src/etc/password.properties">password file</a> 
        and <a href="src/etc/access.properties">access file</a> 
        for <a name="password-access">access control and authorization</a>.
        </p>
        <p>In the password file, we have defined two logins: 
           <i>guest</i> and <i>admin</i>. The password for 
           <i>guest</i> is <i>guestpasswd</i> and the password
           for <i>admin</i> is <i>adminpasswd</i>.
        </p>
        <p>In the access file, we have mapped these two logins
        to access rights: the <i>admin</i> login has <i>read-write</i>
        access, while the <i>guest</i> login only has <i>read-only</i>.
        </p>
        <p>Before starting the <code>ScanDirAgent</code>, you will
           need to restrict access permission to the password file, 
           in such a way that nobody but you can read it. Otherwise, the
           JVM Agent will refuse to start the JMXConnectorServer, as it will
           fear that security can be compromised if other parties can
           have read access to the password file. How to restrict
           read access to the password file is explained in detail
           <a href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#PasswordAccessFiles"
           title="Using Password and Access Files"
           >here</a>.
        </p>
        <p>As we have seen above, the location
           of our access and password files is configured in our own <a 
           href="src/etc/management.properties">management.properties</a>
           file.
        </p>
    </ul>
    <h3>Keystore and Truststore</h3>
    <ul>
        <p>Using SSL with mutual authentication means that both
           client and server will need a <a name="keystore-truststore"
           >keystore and a truststore</a>
           to store their own certificates, and the certificates of
           the parties they trust. Usually, client and server will 
           have their own keystore and truststore. 
        </p>
        <p>For the sake of simplicity - and to get you started
        without the tedious necessity of creating your own keystore
        and truststore, we are providing a dummy keystore and 
        truststore, containing a certificate self-signed by duke.
        The password for our keystore is <i>password</i>, and the
        password for our truststore is <i>trustword</i>.
        We suggest that you first get the example running with the
        keystore and truststore we are providing before attempting 
        to use your own keystore and truststore.
        </p>
        <p>A secure application will obviously need to use its own
        keystore and truststore, <b><u>and should not rely on the keystore
        and truststore we are providing here!</u></b>
        </p>
        <p>How to create your own keystore and truststore, is explained
        in <a
href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#SSL_enabled"
title="Monitoring and Management Using JMX"
        >here</a>.          
        As shown <a href="#start-secure-agent">later</a>, 
        we will need to use <a 
        href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#SSL_enabled"
        >system properties</a> to pass our truststore
        and keystore to the <code>ScanDirAgent</code>.
        </p>
    </ul>
    <h3>Starting a Secure <i>scandir</i> agent</h3>
    <ul>
        <p>To start a <a name="start-secure-agent"
        >secure <i>scandir</i> agent</a>, go to the
        <i>scandir</i> example root directory and type the
        following command:</p>
        <p>On Unix Systems:
<pre>ant jar
java \
    -Djava.util.logging.config.file=logging.properties \
    -Djavax.net.ssl.keyStore=keystore \
    -Djavax.net.ssl.keyStorePassword=password \
    -Djavax.net.ssl.trustStore=truststore \
    -Djavax.net.ssl.trustStorePassword=trustword \
    -Dcom.sun.management.config.file=src/etc/management.properties \
    -Dscandir.config.file=src/etc/testconfig.xml \
    -jar dist/jmx-scandir.jar</pre>
        </p>
         <p>On Windows Systems:
<p><code>ant jar<br>
java 
    &nbsp;-Djava.util.logging.config.file=logging.properties
    &nbsp;-Djavax.net.ssl.keyStore=keystore
    &nbsp;-Djavax.net.ssl.keyStorePassword=password
    &nbsp;-Djavax.net.ssl.trustStore=truststore
    &nbsp;-Djavax.net.ssl.trustStorePassword=trustword
    &nbsp;-Dcom.sun.management.config.file=src\etc\management.properties
    &nbsp;-Dscandir.config.file=src\etc\testconfig.xml
    &nbsp;-jar&nbsp;dist\jmx-scandir.jar</code></p>
         </p>
    <p>If you start jconsole now, you will see that you
       are still able to connect to the agent using the 
       local connection. However, if you try to connect
       through the remote connector, using 
       <a href="docfiles/remote-connection.jpg">localhost:4545</a>, 
       the connection will <a href="docfiles/remote-connection-failed.jpg"
       >fail</a>, even if you provide a correct login/password
       pair. Indeed, since the JMXConnectorServer is now protected with SSL,
       jconsole must also be configured with the appropriate SSL parameters
       so that it can authenticate the server and get authenticated by the
       server too as the SSL configuration of the server requires mutual
       authentication.
    </p>
    <p>The next section will discuss how to connect to the 
    secure agent.
    </p>
   </ul>
   
  <h2><a name="h2-Connecting">Connecting to the Secure JMX Application</a></h2>
    <ul>
    <p>We will now see how to connect to the secure agent,
       using jconsole, and using a programmatic client.
    </p>
    </ul>
    
    <h3>Using jconsole to connect to the secure agent</h3>
    <ul>
    <p>The only special thing you need to do in order to
        be able to connect to your secure agent with
        jconsole, is to give it a keystore (containing
        its client certificate) and a truststore (containing
        the certificates of the servers it can trust).
        In our example, we use the same keystore/truststore
        pair on the client and server side - but this is
        not what a real application would do.
        Indeed a real application would have different 
        certificates for the client and the server, and 
        thus use different keystores (and probably truststores).
        More information on SSL authentication can be obtained from the <a
        href="http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#HowSSLWorks"
        title="How SSL Works"
        >Java<sup>TM</sup> Secure Socket Extension (JSSE) Reference Guide</a>.
    </p>
    <p>To start jconsole with our provided keystore and
    truststore, go to the scandir example root directory and 
    type in the following command:
    <p><code>jconsole 
    &nbsp;-J-Djava.util.logging.config.file=logging.properties 
    &nbsp;-J-Djavax.net.ssl.keyStore=keystore 
    &nbsp;-J-Djavax.net.ssl.keyStorePassword=password 
    &nbsp;-J-Djavax.net.ssl.trustStore=truststore 
    &nbsp;-J-Djavax.net.ssl.trustStorePassword=trustword</code></p>
    </p>
    <p>The <code>-J-Djava.util.logging.config.file=logging.properties</code>
       flag is not mandatory, but passing a <code>logging.properties</code>
       may help you debug connection problems if anything goes wrong.
    </p>
    <p>In jconsole connection window, choose to connect to a 
       remote process, using the address <i>localhost:4545</i>
       and the guest login:
    </p>
    <p><center><a href="docfiles/remote-connection.jpg"
       ><img src="docfiles/remote-connection.jpg"
        alt="jconsole connection window"/></a></center>
    </p>
    <p>You will see that the agent will let view all the
       MBeans and their attributes, but will reject any
       attribute modification or remote method invocation.
    </p>
    <hr>
    <p><u>Note:</u> if jconsole fails to connect and show
    you <a href="docfiles/remote-connection-failed.jpg">this screen</a>
    you have probably misspelled some of the properties on jconsole
    command line, or you didn't start jconsole from the 
    scandir example root directory where our <code>truststore</code>
    and <code>keystore</code> files are located. This article - <a 
    href="http://blogs.sun.com/roller/page/jmxetc?entry=troubleshooting_connection_problems_in_jconsole"
    title="Troubleshooting connection problems in JConsole"
    >Troubleshooting connection problems in JConsole</a> - may help
    you figure out what is going wrong.
    </p>
    <hr>
    </ul>
    
    <h3>Writing a programmatic client to connect to the secure agent</h3>
    <ul>
        <p>
        In this section we will show the steps involved in writing 
        a programmatic client that will connect to our secure agent.
        </p>
   <p>The <a 
href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html" 
title="The ScanDirClient class is a very short example of secure programatic client"
     >ScanDirClient</a> is an example class that shows how a
    programmatic client can connect to a secured <i>scandir</i> application.
    This class contains a <code>main</code> method which creates and
    configures a <code>JMXConnector</code> client to connect with
    the secured <i>scandir</i> agent. 
    </p>
    <p>The secure client differs only from a non secure client in
    so far as it needs to use SSL RMI Factories and credentials to
    connect to the secure agent. The steps required mainly involve:
       <ul>
           <li>Creating an empty environment map:
           <pre>            
            // Create an environment map to hold connection properties
            // like credentials etc... We will later pass this map
            // to the JMX Connector.
            //
            System.out.println("\nInitialize the environment map");
            final Map&lt;String,Object> env = new HashMap&lt;String,Object>();
           </pre>
           </li>
           <li>Putting the client's credentials in that map:
           <i>(here the client will log in as <b>guest</b>)</i>
           <pre>            
            // Provide the credentials required by the server
            // to successfully perform user authentication
            //
            final String[] credentials = new String[] { "guest" , "guestpasswd" };
            env.put("jmx.remote.credentials", credentials);
           </pre>
           </li>
           <li>Providing an <code>SslRMIClientSocketFactory</code> to interact
           with the secure RMI Registry:
           <pre>            
            // Provide the SSL/TLS-based RMI Client Socket Factory required
            // by the JNDI/RMI Registry Service Provider to communicate with
            // the SSL/TLS-protected RMI Registry
            //
            env.put("com.sun.jndi.rmi.factory.socket",
                    new SslRMIClientSocketFactory());
           </pre>
           </li>
           <li>Creating a JMXConnector and connecting with the
               secure server:
           <pre>
            // Create the RMI connector client and
            // connect it to the secure RMI connector server.
            // args[0] is the server's host - localhost
            // args[1] is the secure server port - 4545
            //
            System.out.println("\nCreate the RMI connector client and " +
                    "connect it to the RMI connector server");
            final JMXServiceURL url = new JMXServiceURL(
                    "service:jmx:rmi:///jndi/rmi://"+args[0]+":"+args[1]+ 
                    "/jmxrmi");
            final JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
           </pre>
           </li>
       </ul>
       <p>For this to work, we also need to start the <code>ScanDirClient</code>
       with the appropriate system properties that will point to our 
       <code>keystore</code> and <code>truststore</code>. To start the secure 
       client, go to the <i>scandir</i> example root directory and type
       the following command:
       <p><code>ant jar<br>
java 
    &nbsp;-Djava.util.logging.config.file=logging.properties 
    &nbsp;-Djavax.net.ssl.keyStore=keystore
    &nbsp;-Djavax.net.ssl.keyStorePassword=password
    &nbsp;-Djavax.net.ssl.trustStore=truststore
    &nbsp;-Djavax.net.ssl.trustStorePassword=trustword
    &nbsp;-classpath&nbsp;dist/jmx-scandir.jar
     &nbsp;com.sun.jmx.examples.scandir.ScanDirClient&nbsp;localhost&nbsp;4545
       </code></p>
       </p>
       <p>You should be seeing this trace:
<center><table width="90%" border="0" bgcolor="#eeeeee">
<tr><td>
<pre>
Initialize the environment map

Create the RMI connector client and connect it to the RMI connector server
Connecting to: service:jmx:rmi:///jndi/rmi://localhost:4545/jmxrmi

Get the MBeanServerConnection

Get ScanDirConfigMXBean from ScanManagerMXBean

Get 'Configuration' attribute on ScanDirConfigMXBean

Configuration:

&lt;ScanManager xmlns="jmx:com.sun.jmx.examples.scandir.config" name="testconfig">
    &lt;InitialResultLogConfig>
        &lt;LogFileMaxRecords>2048&lt;/LogFileMaxRecords>
        &lt;LogFileName>build/scandir.log&lt;/LogFileName>
        &lt;MemoryMaxRecords>128&lt;/MemoryMaxRecords>
    &lt;/InitialResultLogConfig>
    &lt;DirectoryScannerList>
        &lt;DirectoryScanner name="scan-build">
            &lt;Actions>NOTIFY LOGRESULT&lt;/Actions>
            &lt;ExcludeFiles/>
            &lt;IncludeFiles>
                &lt;FileFilter>
                    &lt;FilePattern>.*\.class&lt;/FilePattern>
                    &lt;SizeExceedsMaxBytes>4096&lt;/SizeExceedsMaxBytes>
                &lt;/FileFilter>
            &lt;/IncludeFiles>
            &lt;RootDirectory>build&lt;/RootDirectory>
        &lt;/DirectoryScanner>
    &lt;/DirectoryScannerList>
&lt;/ScanManager>

Invoke 'close' on ScanManagerMXBean

Got expected security exception: java.lang.SecurityException: Access denied! 
Invalid access level for requested MBeanServer operation.

Close the connection to the server

Bye! Bye!
</pre>
</td></tr></table></center>
    <p>If the <code>ScanDirClient</code> fails to connect with 
       the secure agent, then this article - <a 
    href="http://blogs.sun.com/roller/page/jmxetc?entry=troubleshooting_connection_problems_in_jconsole"
    title="Troubleshooting connection problems in JConsole"
    >Troubleshooting connection problems in JConsole</a> - may help
    you figure out what is going wrong. Indeed the connection steps
    performed by the <code>ScanDirClient</code> are very similar to
    those performed by <code>jconsole</code>, and the problems you
    could encounter are identical. Just remember that 
   <code>jconsole</code> needs the extra <code>-J</code> flag to pass
   system properties to the VM, which is not needed with regular
   <code>java</code> launcher invocations.
    </p>
    </ul>
    
    <h2><a name="h2-Conclusion">Conclusion</a></h2>
    <ul>
    <p>
        In this document, we have presented an advanced 
        JMX example, and shown how to run a secure 
        JMX agent in a production environment. 
        We have also shown how to connect to such a 
        secure agent with both jconsole and a programmatic 
        client. We have also discuss various JMX 
        design-patterns and best practices. 
        Readers who would wish to learn more about JMX, and
        Monitoring and Management of the JVM, are invited
        to follow the links given in reference below.
    </p>
    </ul>
  <h2><a name="h2-References">References</a></h2>
  <ol>
     <li><a href="http://java.sun.com/products/JavaManagement/best-practices.html"
        >JMX Best Practices</a>: This document describes best practices that
      have been identified for modeling using the JMX API. </li>
     <li><a href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html"
      >Monitoring and Management Using JMX</a>: How to enable, configure, and 
      connect to the JVM JMX agent.</li> 
     <li><a name="JConsole"><a 
href="http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html"
>Using JConsole</a>: JConsole is a JMX-Compliant monitoring tool which allows
     you to interact graphically with your own MBeans.
     </li>
     <li><a href="http://java.sun.com/javase/6/docs/technotes/guides/management/"
     >Monitoring and Management for the Java Platform</a>: The Java Platform 
      Standard Edition (Java SE) 6 provides comprehensive monitoring and 
      management support for the Java platform. </li>
     <li><a href="http://java.sun.com/products/JavaManagement/community/jmx_blogs.html"
         >List of JMX-related Blogs</a>: This page provides links to the 
          different web logs written by members of the Sun team working on the 
          JMX API.</li>
     <li><a
        href="http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#HowSSLWorks"
        title="The JSSE Reference Guide"
        >Java<sup>TM</sup> Secure Socket Extension (JSSE) Reference Guide</a>:
        comprehensive documentation about the Java<sup>TM</sup> Secure Socket 
        Extension (JSSE)
     </li>
     <li><a href="http://java.sun.com/javase/6/docs/"
         >Java SE 6 Documentation Index</a>: This document covers the
          Java<sup>TM</sup> Platform, Standard Edition 6 JDK.</li>
  </ol>
  <p>
  <hr>
  <p>
  </body>
</html>