57 have. It implements a subset of this logic which is |
57 have. It implements a subset of this logic which is |
58 sufficient to demonstrate common patterns and |
58 sufficient to demonstrate common patterns and |
59 solutions used when implementing a monitoring and |
59 solutions used when implementing a monitoring and |
60 management interface for an application with JMX |
60 management interface for an application with JMX |
61 Technology.</p> |
61 Technology.</p> |
62 <p>This example is an advanced JMX example, which presents |
62 <p>This example is an advanced JMX example, which presents |
63 advanced JMX concepts. It is assumed that the reader is already |
63 advanced JMX concepts. It is assumed that the reader is already |
64 familiar with the JMX API. Newcomers to JMX Technology are |
64 familiar with the JMX API. Newcomers to JMX Technology are |
65 invited to have a look at the <a |
65 invited to have a look at the <a |
66 href="http://java.sun.com/javase/6/docs/technotes/guides/jmx/" |
66 href="http://java.sun.com/javase/6/docs/technotes/guides/jmx/" |
67 >JMX API Overview, Tutorial and Examples</a> before going any further. |
67 >JMX API Overview, Tutorial and Examples</a> before going any further. |
68 </p> |
68 </p> |
69 <p></p> |
69 <p></p> |
70 <hr> |
70 <hr> |
71 <blockquote> |
71 <blockquote> |
72 <u>Note:</u> This example was developed using <a |
72 <u>Note:</u> This example was developed using <a |
73 href="http://www.netbeans.org">NetBeans 5.0 IDE</a>. The instructions |
73 href="http://www.netbeans.org">NetBeans 5.0 IDE</a>. The instructions |
74 given in this document to build, run, and test the example assume that |
74 given in this document to build, run, and test the example assume that |
75 you have at your disposal: |
75 you have at your disposal: |
76 <ul><li>either <a href="http://www.netbeans.org">NetBeans 5.0 IDE</a>,</li> |
76 <ul><li>either <a href="http://www.netbeans.org">NetBeans 5.0 IDE</a>,</li> |
77 <li>or <a href="http://ant.apache.org/">Apache Ant 1.6.5</a> and |
77 <li>or <a href="http://ant.apache.org/">Apache Ant 1.6.5</a> and |
78 <a href="http://sourceforge.net/projects/junit/">JUnit 3.8.1 or |
78 <a href="http://sourceforge.net/projects/junit/">JUnit 3.8.1 or |
79 3.8.2</a><br> |
79 3.8.2</a><br> |
80 (JUnit is only needed to run the example's unit tests). |
80 (JUnit is only needed to run the example's unit tests). |
81 </li> |
81 </li> |
82 </ul> |
82 </ul> |
83 <p><a name="setup">In order to build the example</a>, |
83 <p><a name="setup">In order to build the example</a>, |
84 <u>you may need to copy the jmx-scandir</u> |
84 <u>you may need to copy the jmx-scandir</u> |
85 directory to somewhere where you have write permissions. |
85 directory to somewhere where you have write permissions. |
86 <br>In that case, you will need to update the <i>nbjdk.home</i> variable |
86 <br>In that case, you will need to update the <i>nbjdk.home</i> variable |
87 in the copied <i><a href="build.properties">build.properties</a></i> |
87 in the copied <i><a href="build.properties">build.properties</a></i> |
88 file located at the root of the copied project directory. |
88 file located at the root of the copied project directory. |
89 Please make sure that this variable points to the JDK 6 home directory. |
89 Please make sure that this variable points to the JDK 6 home directory. |
90 </p> |
90 </p> |
91 <p>If you wish to run the testsuite from within the <a |
91 <p>If you wish to run the testsuite from within the <a |
92 href="http://www.netbeans.org">NetBeans IDE</a> you will also have |
92 href="http://www.netbeans.org">NetBeans IDE</a> you will also have |
93 to set the <i>libs.junit.classpath</i> variable in |
93 to set the <i>libs.junit.classpath</i> variable in |
94 <a href="build.properties">build.properties</a>. |
94 <a href="build.properties">build.properties</a>. |
95 The <i>libs.junit.classpath</i> variable should point to your |
95 The <i>libs.junit.classpath</i> variable should point to your |
96 <a href="http://sourceforge.net/projects/junit/">junit.jar</a>, |
96 <a href="http://sourceforge.net/projects/junit/">junit.jar</a>, |
97 version 3.8.1 or 3.8.2. |
97 version 3.8.1 or 3.8.2. |
98 </p> |
98 </p> |
99 </blockquote> |
99 </blockquote> |
100 <hr> |
100 <hr> |
101 <p></p> |
101 <p></p> |
279 follows: |
279 follows: |
280 <ol> |
280 <ol> |
281 <li>If the property <code>scandir.config.file</code> is |
281 <li>If the property <code>scandir.config.file</code> is |
282 defined, the default application file will be the |
282 defined, the default application file will be the |
283 file pointed to by this property. If that file |
283 file pointed to by this property. If that file |
284 doesn't exist, it will be created when |
284 doesn't exist, it will be created when |
285 <code>ScanDirConfigMXBean.save()</code> is |
285 <code>ScanDirConfigMXBean.save()</code> is |
286 invoked. |
286 invoked. |
287 </li> |
287 </li> |
288 <li>Otherwise the application config file is |
288 <li>Otherwise the application config file is |
289 assumed to be a file called <code>jmx-scandir.xml</code>, |
289 assumed to be a file called <code>jmx-scandir.xml</code>, |
290 located in the user's directory (as defined by |
290 located in the user's directory (as defined by |
291 the System property <code>user.home</code>). |
291 the System property <code>user.home</code>). |
292 If that file doesn't exists, it will be created when |
292 If that file doesn't exists, it will be created when |
293 <code>ScanDirConfigMXBean.save()</code> is |
293 <code>ScanDirConfigMXBean.save()</code> is |
294 invoked. |
294 invoked. |
295 </li> |
295 </li> |
296 </ol> |
296 </ol> |
297 <p>It is worth noting that this project is defined to |
297 <p>It is worth noting that this project is defined to |
298 run with the following properties: |
298 run with the following properties: |
299 <pre>-Djava.util.logging.config.file=logging.properties</pre> |
299 <pre>-Djava.util.logging.config.file=logging.properties</pre> |
300 <pre>-Dscandir.config.file=src/etc/testconfig.xml</pre> |
300 <pre>-Dscandir.config.file=src/etc/testconfig.xml</pre> |
301 With <code>ScanDirAgent</code> defined as the project's |
301 With <code>ScanDirAgent</code> defined as the project's |
302 main class. Hence when you invoke from the NetBeans IDE |
302 main class. Hence when you invoke from the NetBeans IDE |
303 <i>Run Project</i> on the <i>jmx-scandir</i> project, |
303 <i>Run Project</i> on the <i>jmx-scandir</i> project, |
304 or <i>Run file</i> on the <code>ScanDirAgent</code>, the |
304 or <i>Run file</i> on the <code>ScanDirAgent</code>, the |
305 application starts with the test configuration provided in |
305 application starts with the test configuration provided in |
306 <a href="src/etc/testconfig.xml" |
306 <a href="src/etc/testconfig.xml" |
307 title="An Example Of Configuration" |
307 title="An Example Of Configuration" |
308 >src/etc/testconfig.xml</a> |
308 >src/etc/testconfig.xml</a> |
615 <p> |
615 <p> |
616 When an MBean has such needs, the easiest solution |
616 When an MBean has such needs, the easiest solution |
617 for it is to implement the <code>MBeanRegistration</code> |
617 for it is to implement the <code>MBeanRegistration</code> |
618 interface. |
618 interface. |
619 </p> |
619 </p> |
620 <p>The <code>MBeanRegistration</code> interface is a callback |
620 <p>The <code>MBeanRegistration</code> interface is a callback |
621 interface which defines pre and post registration and |
621 interface which defines pre and post registration and |
622 unregistration callbacks. |
622 unregistration callbacks. |
623 </p> |
623 </p> |
624 <p> |
624 <p> |
625 When an MBean implementing this interface is created |
625 When an MBean implementing this interface is created |
626 (with <code>createMBean</code>) or registered |
626 (with <code>createMBean</code>) or registered |
627 (with <code>registerMBean</code>) in an MBeanServer, |
627 (with <code>registerMBean</code>) in an MBeanServer, |
628 the MBeanServer will call the <code>preRegister</code> |
628 the MBeanServer will call the <code>preRegister</code> |
629 and <code>postRegister</code> method implemented by |
629 and <code>postRegister</code> method implemented by |
630 the MBean. The <code>preRegister</code> method |
630 the MBean. The <code>preRegister</code> method |
631 has an <code>MBeanServer</code> and <code>ObjectName</code> |
631 has an <code>MBeanServer</code> and <code>ObjectName</code> |
632 parameter, which are passed by the MBeanServer to the |
632 parameter, which are passed by the MBeanServer to the |
633 MBean. The MBean can store the reference it is being passed |
633 MBean. The MBean can store the reference it is being passed |
634 in a private instance variable for later use. |
634 in a private instance variable for later use. |
635 </p> |
635 </p> |
636 <p> |
636 <p> |
637 Most of the MXBeans we have defined in this example |
637 Most of the MXBeans we have defined in this example |
638 implement the <code>MBeanRegistration</code> interface. The table |
638 implement the <code>MBeanRegistration</code> interface. The table |
639 below show how our MBeans use this interface to control |
639 below show how our MBeans use this interface to control |
640 their own names, make sanity checks, perform |
640 their own names, make sanity checks, perform |
641 initialization steps or cleanup actions. |
641 initialization steps or cleanup actions. |
642 </p> |
642 </p> |
643 <p><br><center> |
643 <p><br><center> |
644 <table border="1" cellpadding="4" cellspacing="2" |
644 <table border="1" cellpadding="4" cellspacing="2" |
645 bgcolor="#eeeeee" width="95%"> |
645 bgcolor="#eeeeee" width="95%"> |
646 <thead> |
646 <thead> |
647 <tr bgcolor="#cecece"> |
647 <tr bgcolor="#cecece"> |
648 <th width="20%">MBean Requirement</th> |
648 <th width="20%">MBean Requirement</th> |
649 <th>callback</th> |
649 <th>callback</th> |
673 <tr> |
673 <tr> |
674 <td bgcolor="#dedede">reject registration if conditions are |
674 <td bgcolor="#dedede">reject registration if conditions are |
675 not met. |
675 not met. |
676 </td> |
676 </td> |
677 <td><code>preRegister</code></td> |
677 <td><code>preRegister</code></td> |
678 <td bgcolor="#fafafa">The <a |
678 <td bgcolor="#fafafa">The <a |
679 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
679 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
680 title="The ScanManagerMXBean is the main MBean of the scandir application" |
680 title="The ScanManagerMXBean is the main MBean of the scandir application" |
681 >ScanManagerMXBean</a> will throw |
681 >ScanManagerMXBean</a> will throw |
682 an IllegalArgumentException in <code>preRegister</code> |
682 an IllegalArgumentException in <code>preRegister</code> |
683 if the ObjectName it is being passed is |
683 if the ObjectName it is being passed is |
684 illegal. Throwing an exception in |
684 illegal. Throwing an exception in |
685 <code>preRegister</code> makes the registration fail. |
685 <code>preRegister</code> makes the registration fail. |
686 </td> |
686 </td> |
687 </tr> |
687 </tr> |
688 <tr> |
688 <tr> |
689 <td bgcolor="#dedede">get my client-assigned MBean name</td> |
689 <td bgcolor="#dedede">get my client-assigned MBean name</td> |
690 <td><code>preRegister</code></td> |
690 <td><code>preRegister</code></td> |
691 <td bgcolor="#fafafa">The <a |
691 <td bgcolor="#fafafa">The <a |
692 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
692 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
693 title="The ScanDirConfigMXBean is in charge of the configuration" |
693 title="The ScanDirConfigMXBean is in charge of the configuration" |
694 >ScanDirConfigMXBean</a> propagates the |
694 >ScanDirConfigMXBean</a> propagates the |
695 value of the <code>name=</code> property of |
695 value of the <code>name=</code> property of |
696 the ObjectName it is given into its |
696 the ObjectName it is given into its |
697 ScanManagerConfig bean. |
697 ScanManagerConfig bean. |
698 </td> |
698 </td> |
699 </tr> |
699 </tr> |
700 <tr> |
700 <tr> |
701 <td bgcolor="#dedede">provide my own default ObjectName if none |
701 <td bgcolor="#dedede">provide my own default ObjectName if none |
702 was given to the MBeanServer |
702 was given to the MBeanServer |
703 </td> |
703 </td> |
704 <td><code>preRegister</code></td> |
704 <td><code>preRegister</code></td> |
705 <td bgcolor="#fafafa">The name that is returned by <code>preRegister</code> |
705 <td bgcolor="#fafafa">The name that is returned by <code>preRegister</code> |
706 is the ObjectName with which the MBean will be |
706 is the ObjectName with which the MBean will be |
707 eventually registered. |
707 eventually registered. |
708 The <a |
708 The <a |
709 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
709 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
710 title="The ScanDirConfigMXBean is in charge of the configuration" |
710 title="The ScanDirConfigMXBean is in charge of the configuration" |
711 >ScanDirConfigMXBean</a> is able to suggest |
711 >ScanDirConfigMXBean</a> is able to suggest |
712 a value for its own ObjectName if none was |
712 a value for its own ObjectName if none was |
713 provided. Similarly, the <a |
713 provided. Similarly, the <a |
714 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
714 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
715 title="The ScanManagerMXBean is the main MBean of the scandir application" |
715 title="The ScanManagerMXBean is the main MBean of the scandir application" |
716 >ScanManagerMXBean</a> |
716 >ScanManagerMXBean</a> |
717 always returns its singleton ObjectName |
717 always returns its singleton ObjectName |
718 defined by <a |
718 defined by <a |
719 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html#SCAN_MANAGER_NAME" |
719 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html#SCAN_MANAGER_NAME" |
720 title="The ScanManagerMXBean is the main MBean of the scandir application" |
720 title="The ScanManagerMXBean is the main MBean of the scandir application" |
721 >ScanManagerMXBean.SCAN_MANAGER_NAME</a>. |
721 >ScanManagerMXBean.SCAN_MANAGER_NAME</a>. |
722 </td> |
722 </td> |
723 </tr> |
723 </tr> |
724 <tr> |
724 <tr> |
764 </td> |
764 </td> |
765 </tr> |
765 </tr> |
766 <tr> |
766 <tr> |
767 <td bgcolor="#dedede">check whether the MBean can be deregistered</td> |
767 <td bgcolor="#dedede">check whether the MBean can be deregistered</td> |
768 <td><code>preDeregister</code></td> |
768 <td><code>preDeregister</code></td> |
769 <td bgcolor="#fafafa">The <a |
769 <td bgcolor="#fafafa">The <a |
770 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
770 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
771 title="The ScanManagerMXBean is the main MBean of the scandir application" |
771 title="The ScanManagerMXBean is the main MBean of the scandir application" |
772 >ScanManagerMXBean</a> uses this method to verify |
772 >ScanManagerMXBean</a> uses this method to verify |
773 that its state allows it to be deregistered. |
773 that its state allows it to be deregistered. |
774 In particular, it will refuse to be deregistered |
774 In particular, it will refuse to be deregistered |
775 if it is in the RUNNING or SCHEDULED state. |
775 if it is in the RUNNING or SCHEDULED state. |
776 If <code>preDeregister</code> throws an exception, the unregisterMBean |
776 If <code>preDeregister</code> throws an exception, the unregisterMBean |
777 call will fail and the MBean will remain registered in |
777 call will fail and the MBean will remain registered in |
778 the MBeanServer. |
778 the MBeanServer. |
779 Take particular care when implementing business logic |
779 Take particular care when implementing business logic |
780 in this method: if the logic you implement has an |
780 in this method: if the logic you implement has an |
781 unfortunate bug which makes it always throw an |
781 unfortunate bug which makes it always throw an |
782 exception, you will never be able to unregister |
782 exception, you will never be able to unregister |
783 that MBean. |
783 that MBean. |
784 </td> |
784 </td> |
785 </tr> |
785 </tr> |
786 <tr> |
786 <tr> |
787 <td bgcolor="#dedede">clean up resources, refusing to be deregistered if |
787 <td bgcolor="#dedede">clean up resources, refusing to be deregistered if |
788 it fails |
788 it fails |
789 </td> |
789 </td> |
790 <td><code>preDeregister</code></td> |
790 <td><code>preDeregister</code></td> |
791 <td bgcolor="#fafafa">The <a |
791 <td bgcolor="#fafafa">The <a |
792 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
792 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
793 title="The ScanManagerMXBean is the main MBean of the scandir application" |
793 title="The ScanManagerMXBean is the main MBean of the scandir application" |
794 >ScanManagerMXBean</a> uses this method to unregister |
794 >ScanManagerMXBean</a> uses this method to unregister |
795 all the other MBeans it has created and registered in the |
795 all the other MBeans it has created and registered in the |
796 MBeanServer. This includes the <a |
796 MBeanServer. This includes the <a |
797 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
797 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
798 title="The ResultLogManagerMXBean is in charge of managing result logs" |
798 title="The ResultLogManagerMXBean is in charge of managing result logs" |
799 >ResultLogManagerMXBean</a>, the |
799 >ResultLogManagerMXBean</a>, the |
800 <a |
800 <a |
801 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
801 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
802 title="The ScanDirConfigMXBean is in charge of the configuration" |
802 title="The ScanDirConfigMXBean is in charge of the configuration" |
803 >ScanDirConfigMXBeans</a> it has created, and the |
803 >ScanDirConfigMXBeans</a> it has created, and the |
804 <a |
804 <a |
805 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
805 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
806 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." |
806 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." |
807 >DirectoryScannerMXBeans</a> it has created when |
807 >DirectoryScannerMXBeans</a> it has created when |
808 applying its configuration. |
808 applying its configuration. |
832 <p> |
832 <p> |
833 A singleton MBean is an MBean which can only have one |
833 A singleton MBean is an MBean which can only have one |
834 instance registered in a given MBeanServer. <br> |
834 instance registered in a given MBeanServer. <br> |
835 A singleton MBean usually has a well-known name, |
835 A singleton MBean usually has a well-known name, |
836 which can be defined as a constant. In that case, |
836 which can be defined as a constant. In that case, |
837 clients no longer need to call <code>new ObjectName(...)</code> |
837 clients no longer need to call <code>new ObjectName(...)</code> |
838 and catch the declared <code>MalformedObjectNameException</code>. |
838 and catch the declared <code>MalformedObjectNameException</code>. |
839 </p> |
839 </p> |
840 <p>There are already quite a few examples of singleton |
840 <p>There are already quite a few examples of singleton |
841 MBeans in the java.lang.management API. The |
841 MBeans in the java.lang.management API. The |
842 ThreadingMXBean, ClassLoadingMXBean, RuntimeMXBean, etc. |
842 ThreadingMXBean, ClassLoadingMXBean, RuntimeMXBean, etc. |
843 are all singleton MBeans. |
843 are all singleton MBeans. |
844 </p> |
844 </p> |
845 <p>In this example, we have two singleton MBeans: |
845 <p>In this example, we have two singleton MBeans: |
846 The <code><a |
846 The <code><a |
847 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
847 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
848 title="The ScanManagerMXBean is the main MBean of the scandir application" |
848 title="The ScanManagerMXBean is the main MBean of the scandir application" |
849 >ScanManagerMXBean</a></code> and the |
849 >ScanManagerMXBean</a></code> and the |
850 <code><a |
850 <code><a |
851 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
851 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
852 title="The ResultLogManagerMXBean is in charge of managing result logs" |
852 title="The ResultLogManagerMXBean is in charge of managing result logs" |
853 >ResultLogManagerMXBean</a></code>. But in fact, |
853 >ResultLogManagerMXBean</a></code>. But in fact, |
854 the only real singleton MBean is the |
854 the only real singleton MBean is the |
855 <code>ScanManagerMXBean</code>. The |
855 <code>ScanManagerMXBean</code>. The |
856 <code>ResultLogManagerMXBean</code> just happens to |
856 <code>ResultLogManagerMXBean</code> just happens to |
857 be a singleton MBean because it has a 1-1 relationship |
857 be a singleton MBean because it has a 1-1 relationship |
858 with the <code>ScanManagerMXBean</code>. |
858 with the <code>ScanManagerMXBean</code>. |
859 </p> |
859 </p> |
860 <p>The <code>ScanManagerMXBean</code> implements the |
860 <p>The <code>ScanManagerMXBean</code> implements the |
861 singleton MBean pattern in this way: |
861 singleton MBean pattern in this way: |
862 </p> |
862 </p> |
863 <ul> |
863 <ul> |
864 <li>The <code>ScanManagerMXBean</code> name has a single |
864 <li>The <code>ScanManagerMXBean</code> name has a single |
865 key property: <code>type=ScanManagerMXBean</code>.</li> |
865 key property: <code>type=ScanManagerMXBean</code>.</li> |
866 <li>Its name is defined by an ObjectName constant called |
866 <li>Its name is defined by an ObjectName constant called |
867 <code>SCAN_MANAGER_NAME</code> in the <code>ScanManager</code> class</li> |
867 <code>SCAN_MANAGER_NAME</code> in the <code>ScanManager</code> class</li> |
868 <li>The <code>ScanManagerMXBean</code> enforces its status of |
868 <li>The <code>ScanManagerMXBean</code> enforces its status of |
869 singleton MBean. It will refuse to be registered |
869 singleton MBean. It will refuse to be registered |
870 with a name other than |
870 with a name other than |
871 the <code>SCAN_MANAGER_NAME</code>. You can therefore depend on |
871 the <code>SCAN_MANAGER_NAME</code>. You can therefore depend on |
872 the fact that the <code>ScanManagerMXBean</code> will always |
872 the fact that the <code>ScanManagerMXBean</code> will always |
873 be registered with its singleton <code>SCAN_MANAGER_NAME</code> |
873 be registered with its singleton <code>SCAN_MANAGER_NAME</code> |
874 (see <code>preRegister</code>) |
874 (see <code>preRegister</code>) |
875 </li> |
875 </li> |
876 <li>You are not obliged to provide a name when you |
876 <li>You are not obliged to provide a name when you |
877 register the <code>ScanManagerMXBean</code>: if you pass null, |
877 register the <code>ScanManagerMXBean</code>: if you pass null, |
878 then the <code>ScanManager</code> will be registered with |
878 then the <code>ScanManager</code> will be registered with |
879 its singleton <code>SCAN_MANAGER_NAME</code> |
879 its singleton <code>SCAN_MANAGER_NAME</code> |
880 (see <code>preRegister</code>). |
880 (see <code>preRegister</code>). |
881 </li> |
881 </li> |
882 <li>The <code>ScanManager</code> class has a no-arg static |
882 <li>The <code>ScanManager</code> class has a no-arg static |
883 <code>register</code> method that will register |
883 <code>register</code> method that will register |
884 the singleton instance in the Platform MBeanServer. |
884 the singleton instance in the Platform MBeanServer. |
885 This static <code>register</code> method returns |
885 This static <code>register</code> method returns |
886 a proxy to the registered singleton. |
886 a proxy to the registered singleton. |
887 </li> |
887 </li> |
888 <li>The <code>ScanManager</code> class has also a static |
888 <li>The <code>ScanManager</code> class has also a static |
889 <code>register</code> method that will create |
889 <code>register</code> method that will create |
890 a singleton instance in a (possibly remote) |
890 a singleton instance in a (possibly remote) |
891 MBeanServerConnection - using |
891 MBeanServerConnection - using |
892 <code>createMBean</code>. |
892 <code>createMBean</code>. |
893 This static <code>register</code> method |
893 This static <code>register</code> method |
894 also returns a proxy to the registered singleton. |
894 also returns a proxy to the registered singleton. |
895 </li> |
895 </li> |
896 <li>Only the MBeanServer has a reference to the |
896 <li>Only the MBeanServer has a reference to the |
897 singleton instance. The singleton instance is |
897 singleton instance. The singleton instance is |
898 not returned to the caller, and not kept |
898 not returned to the caller, and not kept |
1005 can try to start it or schedule it while it |
1005 can try to start it or schedule it while it |
1006 is in that partially-deregistered state. |
1006 is in that partially-deregistered state. |
1007 </p> |
1007 </p> |
1008 <p>Handling the LifeCycle of all the application's |
1008 <p>Handling the LifeCycle of all the application's |
1009 MBeans in a single MBean is usually a good design |
1009 MBeans in a single MBean is usually a good design |
1010 pattern, especially if the application is a |
1010 pattern, especially if the application is a |
1011 module which is intended to share a JVM - or |
1011 module which is intended to share a JVM - or |
1012 an MBeanServer - with other modules. |
1012 an MBeanServer - with other modules. |
1013 </p> |
1013 </p> |
1014 <p>This is specially useful if the application needs to |
1014 <p>This is specially useful if the application needs to |
1015 be loaded and unloaded on demand: in that |
1015 be loaded and unloaded on demand: in that |
1016 case, simply registering or unregistering the top level |
1016 case, simply registering or unregistering the top level |
1017 MBean (in our example the <code>ScanManagerMXBean</code>) does |
1017 MBean (in our example the <code>ScanManagerMXBean</code>) does |
1018 the trick. |
1018 the trick. |
1019 </p> |
1019 </p> |
1020 </ul> |
1020 </ul> |
1021 <h3>Emitting Notifications</h3> |
1021 <h3>Emitting Notifications</h3> |
1022 <ul> |
1022 <ul> |
1023 <p>In order to emit notifications, an MBean must be |
1023 <p>In order to emit notifications, an MBean must be |
1024 an instance of <code>NotificationEmitter</code>. |
1024 an instance of <code>NotificationEmitter</code>. |
1025 The <code>NotificationEmitter</code> interface defines methods |
1025 The <code>NotificationEmitter</code> interface defines methods |
1026 that the MBeanServer will call on the MBean in order |
1026 that the MBeanServer will call on the MBean in order |
1027 to register <code>NotificationListeners</code> with the MBean. |
1027 to register <code>NotificationListeners</code> with the MBean. |
1028 </p> |
1028 </p> |
1029 <p>It is worth noting that the MBean may not be |
1029 <p>It is worth noting that the MBean may not be |
1030 invoked each time a JMX client wants to register |
1030 invoked each time a JMX client wants to register |
1031 a listener. For instance, the RMIConnectorServer |
1031 a listener. For instance, the RMIConnectorServer |
1032 registers <i>only once</i> a single listener with each MBean |
1032 registers <i>only once</i> a single listener with each MBean |
1033 which is a <code>NotificationEmitter</code>. |
1033 which is a <code>NotificationEmitter</code>. |
1034 In that specific case, the listener may even be registered |
1034 In that specific case, the listener may even be registered |
1035 with the MBean before any client has actually subscribed |
1035 with the MBean before any client has actually subscribed |
1036 for notifications from that particular MBean. |
1036 for notifications from that particular MBean. |
1037 </p> |
1037 </p> |
1038 <p>An MBean can therefore make no assumption about |
1038 <p>An MBean can therefore make no assumption about |
1039 which client or how many clients have registered for |
1039 which client or how many clients have registered for |
1040 notifications. |
1040 notifications. |
1041 </p> |
1041 </p> |
1042 <p>It is also worth noting that the logic of the |
1042 <p>It is also worth noting that the logic of the |
1043 methods defined in <code>NotificationEmitter</code> would not |
1043 methods defined in <code>NotificationEmitter</code> would not |
1044 be trivial to implement from scratch. Fortunately |
1044 be trivial to implement from scratch. Fortunately |
1045 the JMX API defines a helper class, called |
1045 the JMX API defines a helper class, called |
1046 <code>NotificationBroadcasterSupport</code>, which |
1046 <code>NotificationBroadcasterSupport</code>, which |
1047 provides an implementation for these methods. |
1047 provides an implementation for these methods. |
1048 </p> |
1048 </p> |
1049 <p>There are actually three ways for an MBean to |
1049 <p>There are actually three ways for an MBean to |
1050 implement <code>NotificationEmitter</code>, of which only two |
1050 implement <code>NotificationEmitter</code>, of which only two |
1051 are recommended. |
1051 are recommended. |
1059 </p> |
1059 </p> |
1060 <p>Simply extend <code>NotificationBroadcasterSupport</code>, |
1060 <p>Simply extend <code>NotificationBroadcasterSupport</code>, |
1061 then override its <code>getNotificationInfo</code> method |
1061 then override its <code>getNotificationInfo</code> method |
1062 which returns the <code>MBeanNotificationInfo[]</code> array |
1062 which returns the <code>MBeanNotificationInfo[]</code> array |
1063 that should be included in your MBean's <code>MBeanInfo</code> |
1063 that should be included in your MBean's <code>MBeanInfo</code> |
1064 and that's it. |
1064 and that's it. |
1065 <br>You just need to call the <code>sendNotification</code> method |
1065 <br>You just need to call the <code>sendNotification</code> method |
1066 inherited from <code>NotificationBroadcasterSupport</code> whenever |
1066 inherited from <code>NotificationBroadcasterSupport</code> whenever |
1067 your MBean needs to send a notification. |
1067 your MBean needs to send a notification. |
1068 </p> |
1068 </p> |
1069 <p>In our example, both the <a |
1069 <p>In our example, both the <a |
1070 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1070 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1071 title="The ScanDirConfigMXBean is in charge of the configuration" |
1071 title="The ScanDirConfigMXBean is in charge of the configuration" |
1072 >ScanDirConfigMXBean</a> and <a |
1072 >ScanDirConfigMXBean</a> and <a |
1073 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
1073 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
1074 title="The ResultLogManagerMXBean is in charge of managing result logs" |
1074 title="The ResultLogManagerMXBean is in charge of managing result logs" |
1075 >ResultLogManagerMXBean</a> extend |
1075 >ResultLogManagerMXBean</a> extend |
1076 <code>NotificationBroadcasterSupport</code> in order |
1076 <code>NotificationBroadcasterSupport</code> in order |
1077 to send notifications. |
1077 to send notifications. |
1078 </p> |
1078 </p> |
1079 </ul> |
1079 </ul> |
1080 <h4>The Delegation Pattern: delegating to a |
1080 <h4>The Delegation Pattern: delegating to a |
1081 NotificationBroadcasterSupport delegate</h4> |
1081 NotificationBroadcasterSupport delegate</h4> |
1082 <ul> |
1082 <ul> |
1083 <p>There may be cases however where delegating to a |
1083 <p>There may be cases however where delegating to a |
1084 wrapped <code>NotificationBroadcasterSupport</code> |
1084 wrapped <code>NotificationBroadcasterSupport</code> |
1085 object may be preferred to extending |
1085 object may be preferred to extending |
1086 <code>NotificationBroadcasterSupport</code>. |
1086 <code>NotificationBroadcasterSupport</code>. |
1087 </p> |
1087 </p> |
1088 <p>For instance, if your MBeans already derive from |
1088 <p>For instance, if your MBeans already derive from |
1089 some base class, extending <code>NotificationBroadcasterSupport</code> |
1089 some base class, extending <code>NotificationBroadcasterSupport</code> |
1090 might not be an option. |
1090 might not be an option. |
1091 </p> |
1091 </p> |
1092 <p>Similarly, if you do not want to have the inherited |
1092 <p>Similarly, if you do not want to have the inherited |
1093 <code>public void sendNotification(Notification notification)</code> |
1093 <code>public void sendNotification(Notification notification)</code> |
1094 method appear in the Javadoc of the concrete class of your |
1094 method appear in the Javadoc of the concrete class of your |
1095 MBean, you may want to consider using the delegation |
1095 MBean, you may want to consider using the delegation |
1096 pattern instead of extending |
1096 pattern instead of extending |
1097 <code>NotificationBroadcasterSupport</code> |
1097 <code>NotificationBroadcasterSupport</code> |
1098 </p> |
1098 </p> |
1099 <p>In our example both the <a |
1099 <p>In our example both the <a |
1100 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1100 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1101 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1101 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1102 >ScanManagerMXBean</a> and the <a |
1102 >ScanManagerMXBean</a> and the <a |
1103 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
1103 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
1104 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." |
1104 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." |
1105 >DirectoryScannerMXBean</a> use the delegation |
1105 >DirectoryScannerMXBean</a> use the delegation |
1106 pattern rather than extending |
1106 pattern rather than extending |
1107 <code>NotificationBroadcasterSupport</code>. |
1107 <code>NotificationBroadcasterSupport</code>. |
1108 In the end, choosing between one or the other method |
1108 In the end, choosing between one or the other method |
1109 is more a question of taste, although the delegation |
1109 is more a question of taste, although the delegation |
1110 pattern could be considered more flexible since it |
1110 pattern could be considered more flexible since it |
1111 doesn't require extending any given superclass. |
1111 doesn't require extending any given superclass. |
1112 </p> |
1112 </p> |
1113 <p>It may be also worth noting that some tools like |
1113 <p>It may be also worth noting that some tools like |
1114 the JMX Module of <a |
1114 the JMX Module of <a |
1115 href="http://www.netbeans.org" |
1115 href="http://www.netbeans.org" |
1116 >NetBeans IDE</a>, will be able to |
1116 >NetBeans IDE</a>, will be able to |
1117 generate for you all the code that delegates to a |
1117 generate for you all the code that delegates to a |
1118 wrapped <code>NotificationBroadcasterSupport</code>. |
1118 wrapped <code>NotificationBroadcasterSupport</code>. |
1119 </p> |
1119 </p> |
1120 </ul> |
1120 </ul> |
1121 |
1121 |
1122 <h4>Implementing NotificationEmitter from scratch</h4> |
1122 <h4>Implementing NotificationEmitter from scratch</h4> |
1123 <ul> |
1123 <ul> |
1124 <p>This is the last possibility for an MBean that |
1124 <p>This is the last possibility for an MBean that |
1125 needs to send notifications: simply implement |
1125 needs to send notifications: simply implement |
1126 <code>NotificationEmitter</code> from scratch. This is highly |
1126 <code>NotificationEmitter</code> from scratch. This is highly |
1127 discouraged since that logic is not trivial, and |
1127 discouraged since that logic is not trivial, and |
1128 already provided by |
1128 already provided by |
1129 <code>NotificationBroadcasterSupport</code> anyway. |
1129 <code>NotificationBroadcasterSupport</code> anyway. |
1130 </p> |
1130 </p> |
1131 </ul> |
1131 </ul> |
1132 |
1132 |
1133 <h4>Beware of Synchronization Locks</h4> |
1133 <h4>Beware of Synchronization Locks</h4> |
1134 <ul> |
1134 <ul> |
1135 |
1135 |
1136 <p>One thing you must keep in mind when sending |
1136 <p>One thing you must keep in mind when sending |
1137 notifications is not to send them from within |
1137 notifications is not to send them from within |
1138 a synchronized block, or while holding a lock on |
1138 a synchronized block, or while holding a lock on |
1139 some resource.</p> |
1139 some resource.</p> |
1140 <p>Indeed, what happens when you send a notification |
1140 <p>Indeed, what happens when you send a notification |
1141 may vary greatly depending on whether the client |
1141 may vary greatly depending on whether the client |
1142 which has registered for notifications has done |
1142 which has registered for notifications has done |
1143 so through a <code>JMXConnector</code> (like the |
1143 so through a <code>JMXConnector</code> (like the |
1144 <code>JMXRMIConnector</code>) |
1144 <code>JMXRMIConnector</code>) |
1145 or through a direct reference to the MBeanServer |
1145 or through a direct reference to the MBeanServer |
1146 (by calling |
1146 (by calling |
1147 <code>MBeanServer.addNotificationListener</code>). |
1147 <code>MBeanServer.addNotificationListener</code>). |
1148 </p> |
1148 </p> |
1149 <p>In this latter case, the listener will be invoked |
1149 <p>In this latter case, the listener will be invoked |
1150 synchronously in the same thread that your MBean is |
1150 synchronously in the same thread that your MBean is |
1151 using to send its notification. If by misfortune, the |
1151 using to send its notification. If by misfortune, the |
1152 code of that listener now re-enters your MBean through a |
1152 code of that listener now re-enters your MBean through a |
1153 call that flows through a JMXConnector, a deadlock |
1153 call that flows through a JMXConnector, a deadlock |
1154 could occur. It is therefore very important to release |
1154 could occur. It is therefore very important to release |
1155 any lock you may have before calling |
1155 any lock you may have before calling |
1156 <code>sendNotification</code>.</p> |
1156 <code>sendNotification</code>.</p> |
1157 <p>An easy way to do that is demonstrated in the |
1157 <p>An easy way to do that is demonstrated in the |
1158 <code>ScanManager</code> class. The ScanManager |
1158 <code>ScanManager</code> class. The ScanManager |
1159 has an internal private queue of pending notifications. |
1159 has an internal private queue of pending notifications. |
1160 When a notification needs to be sent (e.g. because the |
1160 When a notification needs to be sent (e.g. because the |
1161 ScanManager state is being switched), the notification |
1161 ScanManager state is being switched), the notification |
1162 is simply prepared and put into the pending notification |
1162 is simply prepared and put into the pending notification |
1163 queue. |
1163 queue. |
1164 The notification queue is then processed later on, |
1164 The notification queue is then processed later on, |
1165 at the end of the method, when the processing is finally |
1165 at the end of the method, when the processing is finally |
1166 completed and all the locks have been released. |
1166 completed and all the locks have been released. |
1167 <br>At this point the notification queue might already |
1167 <br>At this point the notification queue might already |
1168 have been emptied by another thread - in which case |
1168 have been emptied by another thread - in which case |
1169 the pending notifications will have already been |
1169 the pending notifications will have already been |
1170 removed from the queue. Which thread actually gets |
1170 removed from the queue. Which thread actually gets |
1171 to send the notifications is of no importance. The |
1171 to send the notifications is of no importance. The |
1172 important point is that all the locks detained by |
1172 important point is that all the locks detained by |
1173 your MBean code in that thread were released before |
1173 your MBean code in that thread were released before |
1174 the notification was sent. |
1174 the notification was sent. |
1175 </p> |
1175 </p> |
1176 <p>In our example the <code>ScanManager</code> class |
1176 <p>In our example the <code>ScanManager</code> class |
1177 ensures this by: |
1177 ensures this by: |
1178 <ul> |
1178 <ul> |
1179 <li>Only calling <code>sendNotification</code> |
1179 <li>Only calling <code>sendNotification</code> |
1180 in its private <code>sendQueuedNotifications</code> |
1180 in its private <code>sendQueuedNotifications</code> |
1181 method. |
1181 method. |
1182 </li> |
1182 </li> |
1183 <li>Only calling <code>sendQueuedNotifications</code> |
1183 <li>Only calling <code>sendQueuedNotifications</code> |
1184 when all locks have been released. |
1184 when all locks have been released. |
1185 </li> |
1185 </li> |
1186 <li>Never calling a method that calls |
1186 <li>Never calling a method that calls |
1187 <code>sendQueuedNotifications</code> from within |
1187 <code>sendQueuedNotifications</code> from within |
1188 a synchronized block.</li> |
1188 a synchronized block.</li> |
1189 </ul> |
1189 </ul> |
1190 </p> |
1190 </p> |
1191 </ul> |
1191 </ul> |
1192 |
1192 |
1193 |
1193 |
1194 |
1194 |
1195 <h4>Don't subclass Notification</h4> |
1195 <h4>Don't subclass Notification</h4> |
1196 <ul> |
1196 <ul> |
1197 <p>Another common best practice when you want |
1197 <p>Another common best practice when you want |
1198 to improve interoperability is to use directly |
1198 to improve interoperability is to use directly |
1200 JMX<sup>TM</sup> API. Do not create your own |
1200 JMX<sup>TM</sup> API. Do not create your own |
1201 subclasses of these standard classes. |
1201 subclasses of these standard classes. |
1202 </p> |
1202 </p> |
1203 <p>Indeed, if you code your own subclass, a generic |
1203 <p>Indeed, if you code your own subclass, a generic |
1204 client, like jconsole, will not be able to receive |
1204 client, like jconsole, will not be able to receive |
1205 that notification unless it has that custom |
1205 that notification unless it has that custom |
1206 subclass in its classpath. |
1206 subclass in its classpath. |
1207 </p> |
1207 </p> |
1208 <p> |
1208 <p> |
1209 If you want your application to be interoperable, it is |
1209 If you want your application to be interoperable, it is |
1210 therefore preferable not to subclass any of the standard |
1210 therefore preferable not to subclass any of the standard |
1211 Notification classes. You can define your own |
1211 Notification classes. You can define your own |
1212 Notification type string, and if you need to send |
1212 Notification type string, and if you need to send |
1213 additional data, you can put a CompositeData, or a |
1213 additional data, you can put a CompositeData, or a |
1214 HashMap of serializable standard types in the |
1214 HashMap of serializable standard types in the |
1215 Notification's user data fields. |
1215 Notification's user data fields. |
1216 </p> |
1216 </p> |
1217 <p>In this example, we are using directly the |
1217 <p>In this example, we are using directly the |
1218 standard notification classes: |
1218 standard notification classes: |
1219 <ul> |
1219 <ul> |
1220 <li>The <a |
1220 <li>The <a |
1221 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1221 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1222 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1222 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1223 >ScanManagerMXBean</a> and the <a |
1223 >ScanManagerMXBean</a> and the <a |
1224 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
1224 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
1225 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." |
1225 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." |
1226 >DirectoryScannerMXBean</a> both use directly |
1226 >DirectoryScannerMXBean</a> both use directly |
1234 also uses the base <code>Notification</code> |
1234 also uses the base <code>Notification</code> |
1235 class directly in order to notify whenever |
1235 class directly in order to notify whenever |
1236 it finds a matching file. |
1236 it finds a matching file. |
1237 <br>In that case, we simply use the base |
1237 <br>In that case, we simply use the base |
1238 <code>Notification</code> |
1238 <code>Notification</code> |
1239 class with a new |
1239 class with a new |
1240 <b><code>com.sun.jmx.examples.scandir.filematch</code></b> |
1240 <b><code>com.sun.jmx.examples.scandir.filematch</code></b> |
1241 type. |
1241 type. |
1242 </li> |
1242 </li> |
1243 <li>The <a |
1243 <li>The <a |
1244 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1244 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1245 title="The ScanDirConfigMXBean is in charge of the configuration" |
1245 title="The ScanDirConfigMXBean is in charge of the configuration" |
1246 >ScanDirConfigMXBean</a> and <a |
1246 >ScanDirConfigMXBean</a> and <a |
1247 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
1247 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
1248 title="The ResultLogManagerMXBean is in charge of managing result logs" |
1248 title="The ResultLogManagerMXBean is in charge of managing result logs" |
1249 >ResultLogManagerMXBean</a> also both use the base |
1249 >ResultLogManagerMXBean</a> also both use the base |
1250 <code>Notification</code> class. |
1250 <code>Notification</code> class. |
1251 </li> |
1251 </li> |
1252 </ul> |
1252 </ul> |
1253 <p>Careful readers will have noted that the <a |
1253 <p>Careful readers will have noted that the <a |
1254 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1254 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1255 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1255 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1256 >ScanManagerMXBean</a> and the <a |
1256 >ScanManagerMXBean</a> and the <a |
1257 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
1257 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
1258 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." |
1258 title="A DirectoryScannerMXBean looks for file matching a given set of criteria, starting at a given root." |
1259 >DirectoryScannerMXBean</a> both use the |
1259 >DirectoryScannerMXBean</a> both use the |
1260 <code>AttributeChangeNotification</code> class |
1260 <code>AttributeChangeNotification</code> class |
1261 to notify about their state change, whereas the |
1261 to notify about their state change, whereas the |
1262 <a |
1262 <a |
1263 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1263 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1264 title="The ScanDirConfigMXBean is in charge of the configuration" |
1264 title="The ScanDirConfigMXBean is in charge of the configuration" |
1268 <p>In fact, this is because the semantics of these |
1268 <p>In fact, this is because the semantics of these |
1269 notifications is not exactly the same - although |
1269 notifications is not exactly the same - although |
1270 both denote a state change: |
1270 both denote a state change: |
1271 <ul> |
1271 <ul> |
1272 <p>In the case of <code>ScanManagerMXBean</code> |
1272 <p>In the case of <code>ScanManagerMXBean</code> |
1273 and <code>DirectoryScannerMXBean</code>, the |
1273 and <code>DirectoryScannerMXBean</code>, the |
1274 notification which is emitted is more about a |
1274 notification which is emitted is more about a |
1275 state transition, from one state to another. |
1275 state transition, from one state to another. |
1276 For instance, going from <code>RUNNING</code> |
1276 For instance, going from <code>RUNNING</code> |
1277 to <code>STOPPED</code>, or from |
1277 to <code>STOPPED</code>, or from |
1278 <code>SCHEDULED</code> to <code>STOPPED</code>. |
1278 <code>SCHEDULED</code> to <code>STOPPED</code>. |
1279 <br>In that case, the |
1279 <br>In that case, the |
1280 <code>AttributeChangeNotification</code> was |
1280 <code>AttributeChangeNotification</code> was |
1281 more appropriate because it made it possible |
1281 more appropriate because it made it possible |
1282 to send the previous and the new value of the |
1282 to send the previous and the new value of the |
1283 state attribute, thus reflecting the whole |
1283 state attribute, thus reflecting the whole |
1284 state transition. |
1284 state transition. |
1285 </p> |
1285 </p> |
1286 <p>In the case of the <code>ScanDirConfigMXBean</code> |
1286 <p>In the case of the <code>ScanDirConfigMXBean</code> |
1287 however, what is of interest is the state in |
1287 however, what is of interest is the state in |
1288 which the MBean has arrived. Using the base |
1288 which the MBean has arrived. Using the base |
1289 <code>Notification</code> class with three different |
1289 <code>Notification</code> class with three different |
1290 notification type strings - |
1290 notification type strings - |
1291 <b><code>com.sun.jmx.examples.scandir.config.loaded</code></b>, |
1291 <b><code>com.sun.jmx.examples.scandir.config.loaded</code></b>, |
1292 <b><code>com.sun.jmx.examples.scandir.config.modified</code></b>, |
1292 <b><code>com.sun.jmx.examples.scandir.config.modified</code></b>, |
1293 and |
1293 and |
1294 <b><code>com.sun.jmx.examples.scandir.config.saved</code></b> - |
1294 <b><code>com.sun.jmx.examples.scandir.config.saved</code></b> - |
1295 was therefore closer to what we wanted to model. |
1295 was therefore closer to what we wanted to model. |
1296 </p> |
1296 </p> |
1297 </ul> |
1297 </ul> |
1298 </p> |
1298 </p> |
1299 </ul> |
1299 </ul> |
1300 |
1300 |
1301 <h3>Configuration MBeans</h3> |
1301 <h3>Configuration MBeans</h3> |
1302 <ul> |
1302 <ul> |
1303 <p>A common practice when designing a management application is |
1303 <p>A common practice when designing a management application is |
1304 to have an MBean, or a set of MBeans, dedicated to configuration. |
1304 to have an MBean, or a set of MBeans, dedicated to configuration. |
1305 Separating configuration from control and monitoring allows |
1305 Separating configuration from control and monitoring allows |
1306 more appropriate logic, and often simplifies the design and |
1306 more appropriate logic, and often simplifies the design and |
1307 implementation of the management interface. |
1307 implementation of the management interface. |
1308 </p> |
1308 </p> |
1309 <p> |
1309 <p> |
1310 In our example, the <a |
1310 In our example, the <a |
1311 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1311 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1312 title="The ScanDirConfigMXBean is in charge of the configuration" |
1312 title="The ScanDirConfigMXBean is in charge of the configuration" |
1313 >ScanDirConfigMXBean</a> is dedicated to the application configuration. |
1313 >ScanDirConfigMXBean</a> is dedicated to the application configuration. |
1314 </p> |
1314 </p> |
1315 <p>The <code>ScanDirConfigMXBean</code> will let you interactively |
1315 <p>The <code>ScanDirConfigMXBean</code> will let you interactively |
1316 modify, save, or load the application configuration. The modifications |
1316 modify, save, or load the application configuration. The modifications |
1317 will not be taken into account until it is applied, by invoking |
1317 will not be taken into account until it is applied, by invoking |
1318 <code>applyConfiguration</code> on the <a |
1318 <code>applyConfiguration</code> on the <a |
1319 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1319 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1320 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1320 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1321 >ScanManagerMXBean</a>. |
1321 >ScanManagerMXBean</a>. |
1322 It is also possible to create many configurations, by creating as |
1322 It is also possible to create many configurations, by creating as |
1323 many <code>ScanDirConfigMXBean</code>s, and then to choose and apply |
1323 many <code>ScanDirConfigMXBean</code>s, and then to choose and apply |
1324 one of these configurations by calling |
1324 one of these configurations by calling |
1325 <code>ScanManagerMXBean.setConfigurationMBean</code> and then |
1325 <code>ScanManagerMXBean.setConfigurationMBean</code> and then |
1326 <code>ScanManagerMXBean.applyConfiguration</code>. |
1326 <code>ScanManagerMXBean.applyConfiguration</code>. |
1327 </p> |
1327 </p> |
1328 <p>In this way, all configurations aspects are gathered and concentrated |
1328 <p>In this way, all configurations aspects are gathered and concentrated |
1329 inside the <code>ScanDirConfigMXBean</code> instead of being scattered |
1329 inside the <code>ScanDirConfigMXBean</code> instead of being scattered |
1330 throughout all the MBeans that compose the application. |
1330 throughout all the MBeans that compose the application. |
1331 </p> |
1331 </p> |
1332 <p>In order to save and store the application configuration data, the |
1332 <p>In order to save and store the application configuration data, the |
1333 <code>ScanDirConfigMXBean</code> uses a set of XML serializable Java beans |
1333 <code>ScanDirConfigMXBean</code> uses a set of XML serializable Java beans |
1334 defined in the <a |
1334 defined in the <a |
1335 href="dist/javadoc/com/sun/jmx/examples/scandir/config/package-summary.html" |
1335 href="dist/javadoc/com/sun/jmx/examples/scandir/config/package-summary.html" |
1336 title="The com.sun.jmx.examples.scandir.config package defines XML serializable beans" |
1336 title="The com.sun.jmx.examples.scandir.config package defines XML serializable beans" |
1337 >com.sun.jmx.examples.scandir.config</a> package. These beans are very |
1337 >com.sun.jmx.examples.scandir.config</a> package. These beans are very |
1338 simple Java beans which have been lightly annotated for XML binding. |
1338 simple Java beans which have been lightly annotated for XML binding. |
1339 </p> |
1339 </p> |
1340 <p>It is worth noting that these same beans can also be handled by the |
1340 <p>It is worth noting that these same beans can also be handled by the |
1341 MXBean framework (our beans don't contain recursive data structures) and can |
1341 MXBean framework (our beans don't contain recursive data structures) and can |
1342 therefore be used directly as attributes and parameters of MXBeans, without |
1342 therefore be used directly as attributes and parameters of MXBeans, without |
1343 needing to be Java-serializable (the MXBean framework transform them in |
1343 needing to be Java-serializable (the MXBean framework transform them in |
1344 CompositeData objects - which <b>are</b> serializable). |
1344 CompositeData objects - which <b>are</b> serializable). |
1345 </p> |
1345 </p> |
1346 <p>The same <a |
1346 <p>The same <a |
1347 href="dist/javadoc/com/sun/jmx/examples/scandir/config/ScanManagerConfig.html" |
1347 href="dist/javadoc/com/sun/jmx/examples/scandir/config/ScanManagerConfig.html" |
1348 title="The com.sun.jmx.examples.scandir.config package defines XML serializable beans" |
1348 title="The com.sun.jmx.examples.scandir.config package defines XML serializable beans" |
1349 >ScanManagerConfig</a> bean that we use to read from and write to the |
1349 >ScanManagerConfig</a> bean that we use to read from and write to the |
1350 XML configuration file is thus also used as attribute of the <a |
1350 XML configuration file is thus also used as attribute of the <a |
1351 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1351 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1352 title="The ScanDirConfigMXBean is in charge of the configuration" |
1352 title="The ScanDirConfigMXBean is in charge of the configuration" |
1353 >ScanDirConfigMXBean</a>. It is transformed into a <code>CompositeData</code> |
1353 >ScanDirConfigMXBean</a>. It is transformed into a <code>CompositeData</code> |
1354 by the MXBean framework, and can be easily introspected with |
1354 by the MXBean framework, and can be easily introspected with |
1355 <a href="#JConsole">jconsole</a>. |
1355 <a href="#JConsole">jconsole</a>. |
1356 </p> |
1356 </p> |
1357 </ul> |
1357 </ul> |
1358 <h3>MBeans Must Be Thread-Safe</h3> |
1358 <h3>MBeans Must Be Thread-Safe</h3> |
1359 <ul> |
1359 <ul> |
1360 <p>A question often asked by newcomers to JMX technology |
1360 <p>A question often asked by newcomers to JMX technology |
1361 is whether the MBeanServer is thread-safe. Well, the MBeanServer <b>is</b> |
1361 is whether the MBeanServer is thread-safe. Well, the MBeanServer <b>is</b> |
1362 thread safe, but it doesn't put any locks on the MBeans it contains. The |
1362 thread safe, but it doesn't put any locks on the MBeans it contains. The |
1363 MBeans can be concurrently accessed by multiple threads, and must therefore |
1363 MBeans can be concurrently accessed by multiple threads, and must therefore |
1364 take care of their own thread safety. |
1364 take care of their own thread safety. |
1365 </p> |
1365 </p> |
1366 <p>In this example, we have been using two methods to ensure thread |
1366 <p>In this example, we have been using two methods to ensure thread |
1511 However - holding a hard reference is only advisable |
1511 However - holding a hard reference is only advisable |
1512 when both MBeans are created by the same piece of code, |
1512 when both MBeans are created by the same piece of code, |
1513 and the application can ensure that the life cycle |
1513 and the application can ensure that the life cycle |
1514 of each MBean is consistent with regard to the other. |
1514 of each MBean is consistent with regard to the other. |
1515 </p> |
1515 </p> |
1516 <p>In our example, the <a |
1516 <p>In our example, the <a |
1517 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1517 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1518 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1518 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1519 >ScanManagerMXBean</a> holds only proxy references to the <a |
1519 >ScanManagerMXBean</a> holds only proxy references to the <a |
1520 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1520 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirConfigMXBean.html" |
1521 >ScanDirConfigMXBean</a> and the <a |
1521 >ScanDirConfigMXBean</a> and the <a |
1522 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
1522 href="dist/javadoc/com/sun/jmx/examples/scandir/DirectoryScannerMXBean.html" |
1523 >DirectoryScannerMXBeans</a>. <br> |
1523 >DirectoryScannerMXBeans</a>. <br> |
1524 However it holds a direct reference to the <a |
1524 However it holds a direct reference to the <a |
1525 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManager.html" |
1525 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManager.html" |
1526 >ResultLogManager</a>. This makes it possible to pass a direct |
1526 >ResultLogManager</a>. This makes it possible to pass a direct |
1527 reference to the <code>DirectoryScannerMXBeans</code>, |
1527 reference to the <code>DirectoryScannerMXBeans</code>, |
1528 which can then log their results |
1528 which can then log their results |
1529 more efficiently, and would also make it possible to remove |
1529 more efficiently, and would also make it possible to remove |
1530 the <code>log</code> method from the <a |
1530 the <code>log</code> method from the <a |
1531 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
1531 href="dist/javadoc/com/sun/jmx/examples/scandir/ResultLogManagerMXBean.html" |
1532 >ResultLogManagerMXBean</a> interface - leaving it in the |
1532 >ResultLogManagerMXBean</a> interface - leaving it in the |
1533 <code>ResultLogManager</code> class (possibly as a package method) |
1533 <code>ResultLogManager</code> class (possibly as a package method) |
1534 should we wish to do so. |
1534 should we wish to do so. |
1535 </p> |
1535 </p> |
1536 |
1536 |
1537 </ul> |
1537 </ul> |
1538 |
1538 |
1539 <h3>Agent Class</h3> |
1539 <h3>Agent Class</h3> |
1540 <ul> |
1540 <ul> |
1541 <p>The <a |
1541 <p>The <a |
1542 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html" |
1542 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirAgent.html" |
1543 title="The ScanDirAgent class defines a main method for the scandir application" |
1543 title="The ScanDirAgent class defines a main method for the scandir application" |
1544 >ScanDirAgent</a> is the Agent class for the <i>scandir</i> application. |
1544 >ScanDirAgent</a> is the Agent class for the <i>scandir</i> application. |
1545 This class contains the <code>main</code> method to start a standalone |
1545 This class contains the <code>main</code> method to start a standalone |
1546 <i>scandir</i> application. |
1546 <i>scandir</i> application. |
1547 </p> |
1547 </p> |
1548 <p>The <code>main</code> method simply registers a <a |
1548 <p>The <code>main</code> method simply registers a <a |
1549 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1549 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1550 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1550 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1551 >ScanManagerMXBean</a> in the platform MBeanServer, and then waits |
1551 >ScanManagerMXBean</a> in the platform MBeanServer, and then waits |
1552 for someone to call <code>ScanManagerMXBean.close</code>. |
1552 for someone to call <code>ScanManagerMXBean.close</code>. |
1553 </p> |
1553 </p> |
1554 <p> |
1554 <p> |
1555 When the <code>ScanManagerMXBean</code> state is switched to |
1555 When the <code>ScanManagerMXBean</code> state is switched to |
1556 <code>ScanManagerMXBean.ScanState.CLOSED</code>, the |
1556 <code>ScanManagerMXBean.ScanState.CLOSED</code>, the |
1557 <code>ScanManagerMXBean</code> is unregistered, and the application |
1557 <code>ScanManagerMXBean</code> is unregistered, and the application |
1558 terminates (i.e. the main thread completes). |
1558 terminates (i.e. the main thread completes). |
1559 </p> |
1559 </p> |
1560 <p>Standalone JMX applications usually have an Agent class that contain |
1560 <p>Standalone JMX applications usually have an Agent class that contain |
1561 their <code>main</code> method, which performs all the MBean |
1561 their <code>main</code> method, which performs all the MBean |
1562 registration steps. |
1562 registration steps. |
1563 However, it is usually not a bad idea if that class can |
1563 However, it is usually not a bad idea if that class can |
1564 be easily turned into an MBean. Indeed, this will make your |
1564 be easily turned into an MBean. Indeed, this will make your |
1565 application easier to integrate in an environment where it would |
1565 application easier to integrate in an environment where it would |
1566 no longer be standalone and would no longer control the implementation |
1566 no longer be standalone and would no longer control the implementation |
1567 of <code>main</code>. In our example the Agent |
1567 of <code>main</code>. In our example the Agent |
1568 class could be easily turned into an MBean, exposing its three |
1568 class could be easily turned into an MBean, exposing its three |
1569 <code>init</code>, <code>waitForClose</code> and <code>cleanup</code> |
1569 <code>init</code>, <code>waitForClose</code> and <code>cleanup</code> |
1570 method. However we didn't go as far as turning it into an MBean since |
1570 method. However we didn't go as far as turning it into an MBean since |
1571 the application can be already easily started by registering an instance |
1571 the application can be already easily started by registering an instance |
1572 of <a |
1572 of <a |
1573 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1573 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanManagerMXBean.html" |
1574 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1574 title="The ScanManagerMXBean is the main MBean of the scandir application" |
1575 >ScanManagerMXBean</a>. |
1575 >ScanManagerMXBean</a>. |
1576 </p> |
1576 </p> |
1577 </ul> |
1577 </ul> |
1578 <h3>Secure Client Class</h3> |
1578 <h3>Secure Client Class</h3> |
1579 <ul> |
1579 <ul> |
1580 <p>The <a |
1580 <p>The <a |
1581 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html" |
1581 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html" |
1582 title="The ScanDirClient class is a very short example of secure programmatic client" |
1582 title="The ScanDirClient class is a very short example of secure programmatic client" |
1583 >ScanDirClient</a> is an example class that shows how a |
1583 >ScanDirClient</a> is an example class that shows how a |
1584 programmatic client can connect to a secured <i>scandir</i> application. |
1584 programmatic client can connect to a secured <i>scandir</i> application. |
1585 This class contains a <code>main</code> method which creates and |
1585 This class contains a <code>main</code> method which creates and |
1586 configures a <code>JMXConnector</code> client to connect with |
1586 configures a <code>JMXConnector</code> client to connect with |
1594 <p>The <code>ScanDirClient</code> is not really part of the |
1594 <p>The <code>ScanDirClient</code> is not really part of the |
1595 application - and is given here only for the sake of |
1595 application - and is given here only for the sake of |
1596 the example. |
1596 the example. |
1597 </p> |
1597 </p> |
1598 </ul> |
1598 </ul> |
1599 |
1599 |
1600 <h2><a name="h2-Testing">Testing the <i>scandir</i> Example</a></h2> |
1600 <h2><a name="h2-Testing">Testing the <i>scandir</i> Example</a></h2> |
1601 <ul> |
1601 <ul> |
1602 <p>Make sure that you have access to junit.jar (either 3.8.1 or 3.8.2). |
1602 <p>Make sure that you have access to junit.jar (either 3.8.1 or 3.8.2). |
1603 Make sure also that you have junit.jar in your |
1603 Make sure also that you have junit.jar in your |
1604 <code>CLASSPATH</code>.<br> |
1604 <code>CLASSPATH</code>.<br> |
1605 Then in the example root directory (where the <code>build.xml</code> |
1605 Then in the example root directory (where the <code>build.xml</code> |
1606 file is located) run the following command: |
1606 file is located) run the following command: |
1607 <pre>ant test -Dlibs.junit.classpath=<i><u>path to junit jar (either 3.8.1 or 3.8.2)</u></i></pre> |
1607 <pre>ant test -Dlibs.junit.classpath=<i><u>path to junit jar (either 3.8.1 or 3.8.2)</u></i></pre> |
1608 </p> |
1608 </p> |
1609 <p>Alternatively you can open the jmx-scandir project with the |
1609 <p>Alternatively you can open the jmx-scandir project with the |
1610 NetBeans IDE and test the jmx-scandir project from the |
1610 NetBeans IDE and test the jmx-scandir project from the |
1611 <code>Run</code> menu. |
1611 <code>Run</code> menu. |
1612 </p> |
1612 </p> |
1613 |
1613 |
1614 </ul> |
1614 </ul> |
1615 |
1615 |
1616 <h2><a name="h2-Running">Running the <i>scandir</i> Example</a></h2> |
1616 <h2><a name="h2-Running">Running the <i>scandir</i> Example</a></h2> |
1617 <ul> |
1617 <ul> |
1618 <p>In the example root directory (where the <code>build.xml</code> |
1618 <p>In the example root directory (where the <code>build.xml</code> |
1619 file is located) run the following commands: |
1619 file is located) run the following commands: |
1620 <pre>ant jar |
1620 <pre>ant jar |
1621 ant run-single -Drun.class=com.sun.jmx.examples.scandir.ScanDirAgent -Djavac.includes=src</pre> |
1621 ant run-single -Drun.class=com.sun.jmx.examples.scandir.ScanDirAgent -Djavac.includes=src</pre> |
1622 or simply <pre>ant run</pre> |
1622 or simply <pre>ant run</pre> |
1623 </p> |
1623 </p> |
1624 |
1624 |
1625 <p>This will run the example using the configuration |
1625 <p>This will run the example using the configuration |
1626 file provided in the src/etc directory. |
1626 file provided in the src/etc directory. |
1627 </p> |
1627 </p> |
1628 <p>Alternatively you can open the jmx-scandir project with the |
1628 <p>Alternatively you can open the jmx-scandir project with the |
1629 NetBeans IDE. You can run the example by |
1629 NetBeans IDE. You can run the example by |
1630 selecting the <code>ScanDirAgent</code> file |
1630 selecting the <code>ScanDirAgent</code> file |
1631 and run it with <code>Run File</code> in the |
1631 and run it with <code>Run File</code> in the |
1632 <code>Run</code> menu or simply |
1632 <code>Run</code> menu or simply |
1633 set the <i>jmx-scandir</i> project as main project and |
1633 set the <i>jmx-scandir</i> project as main project and |
1634 select <code>Run Main Project</code> from the |
1634 select <code>Run Main Project</code> from the |
1683 alt="jconsole connection window - connect to local process" |
1683 alt="jconsole connection window - connect to local process" |
1684 /></a> |
1684 /></a> |
1685 </td></tr></table> |
1685 </td></tr></table> |
1686 </center> |
1686 </center> |
1687 </p> |
1687 </p> |
1688 <p>Open the MBeans tab, and look for the |
1688 <p>Open the MBeans tab, and look for the |
1689 <code>ScanDirConfigMXBean</code>. |
1689 <code>ScanDirConfigMXBean</code>. |
1690 Click on its <code>Attributes</code> node and double click on its |
1690 Click on its <code>Attributes</code> node and double click on its |
1691 <code>Configuration</code> attribute, to look at |
1691 <code>Configuration</code> attribute, to look at |
1692 the loaded configuration - values in bold can |
1692 the loaded configuration - values in bold can |
1693 be expanded by a double-click. |
1693 be expanded by a double-click. |
1694 </p> |
1694 </p> |
1695 <p><center><a href="docfiles/scandir-config.jpg" |
1695 <p><center><a href="docfiles/scandir-config.jpg" |
1696 title="jconsole MBean tab: ScanDirConfigMXBean" |
1696 title="jconsole MBean tab: ScanDirConfigMXBean" |
1697 ><img |
1697 ><img |
1698 src="docfiles/scandir-config.jpg" |
1698 src="docfiles/scandir-config.jpg" |
1699 alt="jconsole MBean tab: ScanDirConfigMXBean" |
1699 alt="jconsole MBean tab: ScanDirConfigMXBean" |
1700 /></a></center> |
1700 /></a></center> |
1701 </p> |
1701 </p> |
1702 <p>Now go to the <code>ScanManagerMXBean</code>, click on |
1702 <p>Now go to the <code>ScanManagerMXBean</code>, click on |
1703 its <code>Notifications</code> node, and subscribe |
1703 its <code>Notifications</code> node, and subscribe |
1704 for notifications. Then click on the |
1704 for notifications. Then click on the |
1705 <code>Operations</code> node and invoke the |
1705 <code>Operations</code> node and invoke the |
1706 <code>start()</code> operation: |
1706 <code>start()</code> operation: |
1707 </p> |
1707 </p> |
1708 <p><center><a href="docfiles/scandir-start.jpg" |
1708 <p><center><a href="docfiles/scandir-start.jpg" |
1709 title="jconsole MBean tab: ScanDirConfigMXBean" |
1709 title="jconsole MBean tab: ScanDirConfigMXBean" |
1710 ><img |
1710 ><img |
1711 src="docfiles/scandir-start.jpg" |
1711 src="docfiles/scandir-start.jpg" |
1712 alt="jconsole MBean tab: ScanDirConfigMXBean" |
1712 alt="jconsole MBean tab: ScanDirConfigMXBean" |
1713 /></a></center> |
1713 /></a></center> |
1714 </p> |
1714 </p> |
1715 <p>You can see that the notifications counter was |
1715 <p>You can see that the notifications counter was |
1716 incremented by three: you have just scheduled, |
1716 incremented by three: you have just scheduled, |
1717 run, and completed a batch of directory scans. |
1717 run, and completed a batch of directory scans. |
1718 </p> |
1718 </p> |
1719 <p>Now go to the <code>ResultLogManagerMXBean</code>, |
1719 <p>Now go to the <code>ResultLogManagerMXBean</code>, |
1720 click on its <code>Attributes</code> node, and |
1720 click on its <code>Attributes</code> node, and |
1721 expand its <code>MemoryLog</code> attribute: |
1721 expand its <code>MemoryLog</code> attribute: |
1722 </p> |
1722 </p> |
1723 <p><center><a href="docfiles/scandir-result.jpg" |
1723 <p><center><a href="docfiles/scandir-result.jpg" |
1724 title="jconsole MBean tab: ScanDirConfigMXBean" |
1724 title="jconsole MBean tab: ScanDirConfigMXBean" |
1725 ><img |
1725 ><img |
1726 src="docfiles/scandir-result.jpg" |
1726 src="docfiles/scandir-result.jpg" |
1727 alt="jconsole MBean tab: ScanDirConfigMXBean" |
1727 alt="jconsole MBean tab: ScanDirConfigMXBean" |
1728 /></a></center> |
1728 /></a></center> |
1729 </p> |
1729 </p> |
1730 <p>You can see that the directory scan results have |
1730 <p>You can see that the directory scan results have |
1731 been logged.</p> |
1731 been logged.</p> |
1732 <p>To make the application terminate go back to the |
1732 <p>To make the application terminate go back to the |
1733 <code>ScanManagerMXBean</code> and invoke |
1733 <code>ScanManagerMXBean</code> and invoke |
1734 <code>close()</code>. The <code>ScanDirAgent</code> |
1734 <code>close()</code>. The <code>ScanDirAgent</code> |
1735 will receive the notification, step out of |
1735 will receive the notification, step out of |
1736 the application main thread, and the application |
1736 the application main thread, and the application |
1737 will terminate. |
1737 will terminate. |
1738 </p> |
1738 </p> |
1739 <p>This is of course a very limited scenario. Feel free |
1739 <p>This is of course a very limited scenario. Feel free |
1740 to improvise with all the features of the example, creating |
1740 to improvise with all the features of the example, creating |
1741 a new configuration - |
1741 a new configuration - |
1742 <code>ScanManagerMXBean.createOtherConfigurationMBean</code> - |
1742 <code>ScanManagerMXBean.createOtherConfigurationMBean</code> - |
1743 adding multiple directory scanners to that configuration - |
1743 adding multiple directory scanners to that configuration - |
1744 <code>ScanDirConfigMXBean.addDirectoryScanner</code> - |
1744 <code>ScanDirConfigMXBean.addDirectoryScanner</code> - |
1745 then switching the <code>ScanManagerMXBean</code> current |
1745 then switching the <code>ScanManagerMXBean</code> current |
1746 configuration by changing the value of the <i>ConfigurationMBean</i> |
1746 configuration by changing the value of the <i>ConfigurationMBean</i> |
1747 attribute - <code>ScanManagerMXBean.setConfigurationMBean</code> |
1747 attribute - <code>ScanManagerMXBean.setConfigurationMBean</code> |
1748 - then applying the new configuration - |
1748 - then applying the new configuration - |
1749 <code>ScanManagerMXBean.applyConfiguration(true)</code> - |
1749 <code>ScanManagerMXBean.applyConfiguration(true)</code> - |
1750 then scheduling repeated directory scans every 10 seconds - |
1750 then scheduling repeated directory scans every 10 seconds - |
1751 <code>ScanManagerMXBean.schedule(0,10000)</code> - |
1751 <code>ScanManagerMXBean.schedule(0,10000)</code> - |
1752 subscribing for notifications, etc... |
1752 subscribing for notifications, etc... |
1753 </p> |
1753 </p> |
1754 </ul> |
1754 </ul> |
1755 |
1755 |
1756 <a name="secure"></a> |
1756 <a name="secure"></a> |
1757 <h2><a name="h2-Turning">Turning the example into a Secure JMX Application</a></h2> |
1757 <h2><a name="h2-Turning">Turning the example into a Secure JMX Application</a></h2> |
1758 <ul> |
1758 <ul> |
1759 <p>In this section, we will see how to configure and |
1759 <p>In this section, we will see how to configure and |
1760 start the <i>scandir</i> example so that the JVM agent |
1760 start the <i>scandir</i> example so that the JVM agent |
1761 is bootstrapped with a secure JMXConnectorServer. Indeed, until |
1761 is bootstrapped with a secure JMXConnectorServer. Indeed, until |
1762 now we have only used the insecure local connection, |
1762 now we have only used the insecure local connection, |
1763 which can only be used as long as both the client and |
1763 which can only be used as long as both the client and |
1764 the server run on the same machine. This section will |
1764 the server run on the same machine. This section will |
1765 explain how to start the <code>ScanDirAgent</code> so |
1765 explain how to start the <code>ScanDirAgent</code> so |
1766 that a real secure RMIConnectorServer is started at bootstrap. |
1766 that a real secure RMIConnectorServer is started at bootstrap. |
1767 </p> |
1767 </p> |
1768 <p>To achieve this we will: <a href="#management.properties" |
1768 <p>To achieve this we will: <a href="#management.properties" |
1769 >provide our own management.properties</a>, <a |
1769 >provide our own management.properties</a>, <a |
1770 href="#password-access">create our own password and access files</a>, |
1770 href="#password-access">create our own password and access files</a>, |
1771 <a href="#keystore-truststore">provide a keystore and truststore</a>, |
1771 <a href="#keystore-truststore">provide a keystore and truststore</a>, |
1772 <a href="#start-secure-agent">start the ScanDirAgent with the |
1772 <a href="#start-secure-agent">start the ScanDirAgent with the |
1773 appropriate system properties</a>. |
1773 appropriate system properties</a>. |
1774 </ul> |
1774 </ul> |
1775 <h3>Configuring the JVM Agent for Secure Remote Connection</h3> |
1775 <h3>Configuring the JVM Agent for Secure Remote Connection</h3> |
1776 <ul> |
1776 <ul> |
1777 <p>The easiest way to <a name="management.properties">configure the |
1777 <p>The easiest way to <a name="management.properties">configure the |
1778 JVM Agent</a> for Secure Remote |
1778 JVM Agent</a> for Secure Remote |
1779 Connection is to use your own <a |
1779 Connection is to use your own <a |
1780 href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#properties" |
1780 href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#properties" |
1781 title="This page describes the properties you can put in your management.properties file" |
1781 title="This page describes the properties you can put in your management.properties file" |
1782 >management.properties</a> file. |
1782 >management.properties</a> file. |
1783 In this example, we have copied the default |
1783 In this example, we have copied the default |
1784 <code>$JRE/lib/management/management.properties</code> |
1784 <code>$JRE/conf/management/management.properties</code> |
1785 file to the example's <code>src/etc</code> directory and |
1785 file to the example's <code>src/etc</code> directory and |
1786 modified it in <a href="src/etc/management.properties" |
1786 modified it in <a href="src/etc/management.properties" |
1787 title="our modified management.properties" |
1787 title="our modified management.properties" |
1788 >this way</a>: |
1788 >this way</a>: |
1789 <ul> |
1789 <ul> |
1790 <li>We have set the RMI port to <u>4545</u> - this is just a |
1790 <li>We have set the RMI port to <u>4545</u> - this is just a |
1791 random port number we have picked up. Feel free to use your |
1791 random port number we have picked up. Feel free to use your |
1792 own value suited to your environment. |
1792 own value suited to your environment. |
1793 <pre># For setting the JMX RMI agent port use the following line |
1793 <pre># For setting the JMX RMI agent port use the following line |
1794 com.sun.management.jmxremote.port=<b>4545</b></pre> |
1794 com.sun.management.jmxremote.port=<b>4545</b></pre> |
1795 </li> |
1795 </li> |
1796 <li>We have <u>switched on</u> SSL <u>mutual authentication</u> |
1796 <li>We have <u>switched on</u> SSL <u>mutual authentication</u> |
1799 </li> |
1799 </li> |
1800 <li>We have also <u>secured the RMI Registry</u> with SSL |
1800 <li>We have also <u>secured the RMI Registry</u> with SSL |
1801 <pre># For using an SSL/TLS <b>protected</b> RMI Registry use the following line |
1801 <pre># For using an SSL/TLS <b>protected</b> RMI Registry use the following line |
1802 com.sun.management.jmxremote.<b>registry.ssl</b>=<b>true</b></pre> |
1802 com.sun.management.jmxremote.<b>registry.ssl</b>=<b>true</b></pre> |
1803 </li> |
1803 </li> |
1804 <li>We have provided <a |
1804 <li>We have provided <a |
1805 href="src/etc/password.properties">our own password file</a> |
1805 href="src/etc/password.properties">our own password file</a> |
1806 <pre># For a non-default password file location use the following line |
1806 <pre># For a non-default password file location use the following line |
1807 com.sun.management.jmxremote.password.file=<i>src/etc/password.properties</i></pre> |
1807 com.sun.management.jmxremote.password.file=<i>src/etc/password.properties</i></pre> |
1808 </li> |
1808 </li> |
1809 <li>We have provided <a |
1809 <li>We have provided <a |
1810 href="src/etc/access.properties">our own access file</a> |
1810 href="src/etc/access.properties">our own access file</a> |
1811 <pre># For a non-default password file location use the following line |
1811 <pre># For a non-default password file location use the following line |
1812 com.sun.management.jmxremote.access.file=<i>src/etc/access.properties</i></pre> |
1812 com.sun.management.jmxremote.access.file=<i>src/etc/access.properties</i></pre> |
1813 </li> |
1813 </li> |
1814 </ul> |
1814 </ul> |
1815 <p>You will note that we haven't provided any value |
1815 <p>You will note that we haven't provided any value |
1816 for the other security properties, like |
1816 for the other security properties, like |
1817 <code>com.sun.management.jmxremote.authenticate=true</code>, |
1817 <code>com.sun.management.jmxremote.authenticate=true</code>, |
1818 because these properties already default to a value |
1818 because these properties already default to a value |
1819 which enables security by default. |
1819 which enables security by default. |
1820 Note however that protecting the RMI Registry with SSL |
1820 Note however that protecting the RMI Registry with SSL |
1821 improves the application security, but only as long as |
1821 improves the application security, but only as long as |
1822 mutual authentication is also switched on. Otherwise, just |
1822 mutual authentication is also switched on. Otherwise, just |
1823 anybody would be able to connect to the registry and |
1823 anybody would be able to connect to the registry and |
1824 get the RMIServer stub. |
1824 get the RMIServer stub. |
1825 </p> |
1825 </p> |
1826 <p>We do recommend that you <u>use the most secure configuration |
1826 <p>We do recommend that you <u>use the most secure configuration |
1827 when you deploy a JMX agent</u> - which means <u>switching on |
1827 when you deploy a JMX agent</u> - which means <u>switching on |
1828 SSL protection for the RMI registry</u> <b>and</b> <u>requiring |
1828 SSL protection for the RMI registry</u> <b>and</b> <u>requiring |
1829 mutual authentication</u>, as we show in this example. |
1829 mutual authentication</u>, as we show in this example. |
1830 </p> |
1830 </p> |
1831 <p>We will use the <code>com.sun.management.config.file</code> |
1831 <p>We will use the <code>com.sun.management.config.file</code> |
1832 system property to pass our <a |
1832 system property to pass our <a |
1833 href="src/etc/management.properties">management.properties</a> |
1833 href="src/etc/management.properties">management.properties</a> |
1834 file to the <code>ScanDirAgent</code>. |
1834 file to the <code>ScanDirAgent</code>. |
1835 </p> |
1835 </p> |
1836 </ul> |
1836 </ul> |
1837 |
1837 |
1838 <h3>Creating a password and access file</h3> |
1838 <h3>Creating a password and access file</h3> |
1839 <ul> |
1839 <ul> |
1840 <p>As explained above, we have created our own |
1840 <p>As explained above, we have created our own |
1841 <a href="src/etc/password.properties">password file</a> |
1841 <a href="src/etc/password.properties">password file</a> |
1842 and <a href="src/etc/access.properties">access file</a> |
1842 and <a href="src/etc/access.properties">access file</a> |
1843 for <a name="password-access">access control and authorization</a>. |
1843 for <a name="password-access">access control and authorization</a>. |
1844 </p> |
1844 </p> |
1845 <p>In the password file, we have defined two logins: |
1845 <p>In the password file, we have defined two logins: |
1846 <i>guest</i> and <i>admin</i>. The password for |
1846 <i>guest</i> and <i>admin</i>. The password for |
1847 <i>guest</i> is <i>guestpasswd</i> and the password |
1847 <i>guest</i> is <i>guestpasswd</i> and the password |
1848 for <i>admin</i> is <i>adminpasswd</i>. |
1848 for <i>admin</i> is <i>adminpasswd</i>. |
1849 </p> |
1849 </p> |
1850 <p>In the access file, we have mapped these two logins |
1850 <p>In the access file, we have mapped these two logins |
1851 to access rights: the <i>admin</i> login has <i>read-write</i> |
1851 to access rights: the <i>admin</i> login has <i>read-write</i> |
1852 access, while the <i>guest</i> login only has <i>read-only</i>. |
1852 access, while the <i>guest</i> login only has <i>read-only</i>. |
1853 </p> |
1853 </p> |
1854 <p>Before starting the <code>ScanDirAgent</code>, you will |
1854 <p>Before starting the <code>ScanDirAgent</code>, you will |
1855 need to restrict access permission to the password file, |
1855 need to restrict access permission to the password file, |
1856 in such a way that nobody but you can read it. Otherwise, the |
1856 in such a way that nobody but you can read it. Otherwise, the |
1857 JVM Agent will refuse to start the JMXConnectorServer, as it will |
1857 JVM Agent will refuse to start the JMXConnectorServer, as it will |
1858 fear that security can be compromised if other parties can |
1858 fear that security can be compromised if other parties can |
1859 have read access to the password file. How to restrict |
1859 have read access to the password file. How to restrict |
1860 read access to the password file is explained in detail |
1860 read access to the password file is explained in detail |
1861 <a href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#PasswordAccessFiles" |
1861 <a href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#PasswordAccessFiles" |
1862 title="Using Password and Access Files" |
1862 title="Using Password and Access Files" |
1863 >here</a>. |
1863 >here</a>. |
1864 </p> |
1864 </p> |
1865 <p>As we have seen above, the location |
1865 <p>As we have seen above, the location |
1866 of our access and password files is configured in our own <a |
1866 of our access and password files is configured in our own <a |
1867 href="src/etc/management.properties">management.properties</a> |
1867 href="src/etc/management.properties">management.properties</a> |
1868 file. |
1868 file. |
1869 </p> |
1869 </p> |
1870 </ul> |
1870 </ul> |
1871 <h3>Keystore and Truststore</h3> |
1871 <h3>Keystore and Truststore</h3> |
1872 <ul> |
1872 <ul> |
1873 <p>Using SSL with mutual authentication means that both |
1873 <p>Using SSL with mutual authentication means that both |
1874 client and server will need a <a name="keystore-truststore" |
1874 client and server will need a <a name="keystore-truststore" |
1875 >keystore and a truststore</a> |
1875 >keystore and a truststore</a> |
1876 to store their own certificates, and the certificates of |
1876 to store their own certificates, and the certificates of |
1877 the parties they trust. Usually, client and server will |
1877 the parties they trust. Usually, client and server will |
1878 have their own keystore and truststore. |
1878 have their own keystore and truststore. |
1879 </p> |
1879 </p> |
1880 <p>For the sake of simplicity - and to get you started |
1880 <p>For the sake of simplicity - and to get you started |
1881 without the tedious necessity of creating your own keystore |
1881 without the tedious necessity of creating your own keystore |
1882 and truststore, we are providing a dummy keystore and |
1882 and truststore, we are providing a dummy keystore and |
1883 truststore, containing a certificate self-signed by duke. |
1883 truststore, containing a certificate self-signed by duke. |
1884 The password for our keystore is <i>password</i>, and the |
1884 The password for our keystore is <i>password</i>, and the |
1885 password for our truststore is <i>trustword</i>. |
1885 password for our truststore is <i>trustword</i>. |
1886 We suggest that you first get the example running with the |
1886 We suggest that you first get the example running with the |
1887 keystore and truststore we are providing before attempting |
1887 keystore and truststore we are providing before attempting |
1888 to use your own keystore and truststore. |
1888 to use your own keystore and truststore. |
1889 </p> |
1889 </p> |
1890 <p>A secure application will obviously need to use its own |
1890 <p>A secure application will obviously need to use its own |
1891 keystore and truststore, <b><u>and should not rely on the keystore |
1891 keystore and truststore, <b><u>and should not rely on the keystore |
1892 and truststore we are providing here!</u></b> |
1892 and truststore we are providing here!</u></b> |
1893 </p> |
1893 </p> |
1894 <p>How to create your own keystore and truststore, is explained |
1894 <p>How to create your own keystore and truststore, is explained |
1895 in <a |
1895 in <a |
1896 href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#SSL_enabled" |
1896 href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#SSL_enabled" |
1897 title="Monitoring and Management Using JMX" |
1897 title="Monitoring and Management Using JMX" |
1898 >here</a>. |
1898 >here</a>. |
1899 As shown <a href="#start-secure-agent">later</a>, |
1899 As shown <a href="#start-secure-agent">later</a>, |
1900 we will need to use <a |
1900 we will need to use <a |
1901 href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#SSL_enabled" |
1901 href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#SSL_enabled" |
1902 >system properties</a> to pass our truststore |
1902 >system properties</a> to pass our truststore |
1903 and keystore to the <code>ScanDirAgent</code>. |
1903 and keystore to the <code>ScanDirAgent</code>. |
1904 </p> |
1904 </p> |
1905 </ul> |
1905 </ul> |
1921 -Dscandir.config.file=src/etc/testconfig.xml \ |
1921 -Dscandir.config.file=src/etc/testconfig.xml \ |
1922 -jar dist/jmx-scandir.jar</pre> |
1922 -jar dist/jmx-scandir.jar</pre> |
1923 </p> |
1923 </p> |
1924 <p>On Windows Systems: |
1924 <p>On Windows Systems: |
1925 <p><code>ant jar<br> |
1925 <p><code>ant jar<br> |
1926 java |
1926 java |
1927 -Djava.util.logging.config.file=logging.properties |
1927 -Djava.util.logging.config.file=logging.properties |
1928 -Djavax.net.ssl.keyStore=keystore |
1928 -Djavax.net.ssl.keyStore=keystore |
1929 -Djavax.net.ssl.keyStorePassword=password |
1929 -Djavax.net.ssl.keyStorePassword=password |
1930 -Djavax.net.ssl.trustStore=truststore |
1930 -Djavax.net.ssl.trustStore=truststore |
1931 -Djavax.net.ssl.trustStorePassword=trustword |
1931 -Djavax.net.ssl.trustStorePassword=trustword |
1932 -Dcom.sun.management.config.file=src\etc\management.properties |
1932 -Dcom.sun.management.config.file=src\etc\management.properties |
1933 -Dscandir.config.file=src\etc\testconfig.xml |
1933 -Dscandir.config.file=src\etc\testconfig.xml |
1934 -jar dist\jmx-scandir.jar</code></p> |
1934 -jar dist\jmx-scandir.jar</code></p> |
1935 </p> |
1935 </p> |
1936 <p>If you start jconsole now, you will see that you |
1936 <p>If you start jconsole now, you will see that you |
1937 are still able to connect to the agent using the |
1937 are still able to connect to the agent using the |
1938 local connection. However, if you try to connect |
1938 local connection. However, if you try to connect |
1939 through the remote connector, using |
1939 through the remote connector, using |
1940 <a href="docfiles/remote-connection.jpg">localhost:4545</a>, |
1940 <a href="docfiles/remote-connection.jpg">localhost:4545</a>, |
1941 the connection will <a href="docfiles/remote-connection-failed.jpg" |
1941 the connection will <a href="docfiles/remote-connection-failed.jpg" |
1942 >fail</a>, even if you provide a correct login/password |
1942 >fail</a>, even if you provide a correct login/password |
1943 pair. Indeed, since the JMXConnectorServer is now protected with SSL, |
1943 pair. Indeed, since the JMXConnectorServer is now protected with SSL, |
1944 jconsole must also be configured with the appropriate SSL parameters |
1944 jconsole must also be configured with the appropriate SSL parameters |
1945 so that it can authenticate the server and get authenticated by the |
1945 so that it can authenticate the server and get authenticated by the |
1946 server too as the SSL configuration of the server requires mutual |
1946 server too as the SSL configuration of the server requires mutual |
1947 authentication. |
1947 authentication. |
1948 </p> |
1948 </p> |
1949 <p>The next section will discuss how to connect to the |
1949 <p>The next section will discuss how to connect to the |
1950 secure agent. |
1950 secure agent. |
1951 </p> |
1951 </p> |
1952 </ul> |
1952 </ul> |
1953 |
1953 |
1954 <h2><a name="h2-Connecting">Connecting to the Secure JMX Application</a></h2> |
1954 <h2><a name="h2-Connecting">Connecting to the Secure JMX Application</a></h2> |
1955 <ul> |
1955 <ul> |
1956 <p>We will now see how to connect to the secure agent, |
1956 <p>We will now see how to connect to the secure agent, |
1957 using jconsole, and using a programmatic client. |
1957 using jconsole, and using a programmatic client. |
1958 </p> |
1958 </p> |
1959 </ul> |
1959 </ul> |
1960 |
1960 |
1961 <h3>Using jconsole to connect to the secure agent</h3> |
1961 <h3>Using jconsole to connect to the secure agent</h3> |
1962 <ul> |
1962 <ul> |
1963 <p>The only special thing you need to do in order to |
1963 <p>The only special thing you need to do in order to |
1964 be able to connect to your secure agent with |
1964 be able to connect to your secure agent with |
1965 jconsole, is to give it a keystore (containing |
1965 jconsole, is to give it a keystore (containing |
1966 its client certificate) and a truststore (containing |
1966 its client certificate) and a truststore (containing |
1967 the certificates of the servers it can trust). |
1967 the certificates of the servers it can trust). |
1968 In our example, we use the same keystore/truststore |
1968 In our example, we use the same keystore/truststore |
1969 pair on the client and server side - but this is |
1969 pair on the client and server side - but this is |
1970 not what a real application would do. |
1970 not what a real application would do. |
1971 Indeed a real application would have different |
1971 Indeed a real application would have different |
1972 certificates for the client and the server, and |
1972 certificates for the client and the server, and |
1973 thus use different keystores (and probably truststores). |
1973 thus use different keystores (and probably truststores). |
1974 More information on SSL authentication can be obtained from the <a |
1974 More information on SSL authentication can be obtained from the <a |
1975 href="http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#HowSSLWorks" |
1975 href="http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#HowSSLWorks" |
1976 title="How SSL Works" |
1976 title="How SSL Works" |
1977 >Java<sup>TM</sup> Secure Socket Extension (JSSE) Reference Guide</a>. |
1977 >Java<sup>TM</sup> Secure Socket Extension (JSSE) Reference Guide</a>. |
1978 </p> |
1978 </p> |
1979 <p>To start jconsole with our provided keystore and |
1979 <p>To start jconsole with our provided keystore and |
1980 truststore, go to the scandir example root directory and |
1980 truststore, go to the scandir example root directory and |
1981 type in the following command: |
1981 type in the following command: |
1982 <p><code>jconsole |
1982 <p><code>jconsole |
1983 -J-Djava.util.logging.config.file=logging.properties |
1983 -J-Djava.util.logging.config.file=logging.properties |
1984 -J-Djavax.net.ssl.keyStore=keystore |
1984 -J-Djavax.net.ssl.keyStore=keystore |
1985 -J-Djavax.net.ssl.keyStorePassword=password |
1985 -J-Djavax.net.ssl.keyStorePassword=password |
1986 -J-Djavax.net.ssl.trustStore=truststore |
1986 -J-Djavax.net.ssl.trustStore=truststore |
1987 -J-Djavax.net.ssl.trustStorePassword=trustword</code></p> |
1987 -J-Djavax.net.ssl.trustStorePassword=trustword</code></p> |
1988 </p> |
1988 </p> |
1989 <p>The <code>-J-Djava.util.logging.config.file=logging.properties</code> |
1989 <p>The <code>-J-Djava.util.logging.config.file=logging.properties</code> |
1990 flag is not mandatory, but passing a <code>logging.properties</code> |
1990 flag is not mandatory, but passing a <code>logging.properties</code> |
1991 may help you debug connection problems if anything goes wrong. |
1991 may help you debug connection problems if anything goes wrong. |
1992 </p> |
1992 </p> |
1993 <p>In jconsole connection window, choose to connect to a |
1993 <p>In jconsole connection window, choose to connect to a |
1994 remote process, using the address <i>localhost:4545</i> |
1994 remote process, using the address <i>localhost:4545</i> |
1995 and the guest login: |
1995 and the guest login: |
1996 </p> |
1996 </p> |
1997 <p><center><a href="docfiles/remote-connection.jpg" |
1997 <p><center><a href="docfiles/remote-connection.jpg" |
1998 ><img src="docfiles/remote-connection.jpg" |
1998 ><img src="docfiles/remote-connection.jpg" |
2004 </p> |
2004 </p> |
2005 <hr> |
2005 <hr> |
2006 <p><u>Note:</u> if jconsole fails to connect and show |
2006 <p><u>Note:</u> if jconsole fails to connect and show |
2007 you <a href="docfiles/remote-connection-failed.jpg">this screen</a> |
2007 you <a href="docfiles/remote-connection-failed.jpg">this screen</a> |
2008 you have probably misspelled some of the properties on jconsole |
2008 you have probably misspelled some of the properties on jconsole |
2009 command line, or you didn't start jconsole from the |
2009 command line, or you didn't start jconsole from the |
2010 scandir example root directory where our <code>truststore</code> |
2010 scandir example root directory where our <code>truststore</code> |
2011 and <code>keystore</code> files are located. This article - <a |
2011 and <code>keystore</code> files are located. This article - <a |
2012 href="http://blogs.sun.com/roller/page/jmxetc?entry=troubleshooting_connection_problems_in_jconsole" |
2012 href="http://blogs.sun.com/roller/page/jmxetc?entry=troubleshooting_connection_problems_in_jconsole" |
2013 title="Troubleshooting connection problems in JConsole" |
2013 title="Troubleshooting connection problems in JConsole" |
2014 >Troubleshooting connection problems in JConsole</a> - may help |
2014 >Troubleshooting connection problems in JConsole</a> - may help |
2015 you figure out what is going wrong. |
2015 you figure out what is going wrong. |
2016 </p> |
2016 </p> |
2017 <hr> |
2017 <hr> |
2018 </ul> |
2018 </ul> |
2019 |
2019 |
2020 <h3>Writing a programmatic client to connect to the secure agent</h3> |
2020 <h3>Writing a programmatic client to connect to the secure agent</h3> |
2021 <ul> |
2021 <ul> |
2022 <p> |
2022 <p> |
2023 In this section we will show the steps involved in writing |
2023 In this section we will show the steps involved in writing |
2024 a programmatic client that will connect to our secure agent. |
2024 a programmatic client that will connect to our secure agent. |
2025 </p> |
2025 </p> |
2026 <p>The <a |
2026 <p>The <a |
2027 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html" |
2027 href="dist/javadoc/com/sun/jmx/examples/scandir/ScanDirClient.html" |
2028 title="The ScanDirClient class is a very short example of secure programmatic client" |
2028 title="The ScanDirClient class is a very short example of secure programmatic client" |
2029 >ScanDirClient</a> is an example class that shows how a |
2029 >ScanDirClient</a> is an example class that shows how a |
2030 programmatic client can connect to a secured <i>scandir</i> application. |
2030 programmatic client can connect to a secured <i>scandir</i> application. |
2031 This class contains a <code>main</code> method which creates and |
2031 This class contains a <code>main</code> method which creates and |
2032 configures a <code>JMXConnector</code> client to connect with |
2032 configures a <code>JMXConnector</code> client to connect with |
2033 the secured <i>scandir</i> agent. |
2033 the secured <i>scandir</i> agent. |
2034 </p> |
2034 </p> |
2035 <p>The secure client differs only from a non secure client in |
2035 <p>The secure client differs only from a non secure client in |
2036 so far as it needs to use SSL RMI Factories and credentials to |
2036 so far as it needs to use SSL RMI Factories and credentials to |
2037 connect to the secure agent. The steps required mainly involve: |
2037 connect to the secure agent. The steps required mainly involve: |
2038 <ul> |
2038 <ul> |
2039 <li>Creating an empty environment map: |
2039 <li>Creating an empty environment map: |
2040 <pre> |
2040 <pre> |
2041 // Create an environment map to hold connection properties |
2041 // Create an environment map to hold connection properties |
2042 // like credentials etc... We will later pass this map |
2042 // like credentials etc... We will later pass this map |
2043 // to the JMX Connector. |
2043 // to the JMX Connector. |
2044 // |
2044 // |
2045 System.out.println("\nInitialize the environment map"); |
2045 System.out.println("\nInitialize the environment map"); |
2046 final Map<String,Object> env = new HashMap<String,Object>(); |
2046 final Map<String,Object> env = new HashMap<String,Object>(); |
2047 </pre> |
2047 </pre> |
2048 </li> |
2048 </li> |
2049 <li>Putting the client's credentials in that map: |
2049 <li>Putting the client's credentials in that map: |
2050 <i>(here the client will log in as <b>guest</b>)</i> |
2050 <i>(here the client will log in as <b>guest</b>)</i> |
2051 <pre> |
2051 <pre> |
2052 // Provide the credentials required by the server |
2052 // Provide the credentials required by the server |
2053 // to successfully perform user authentication |
2053 // to successfully perform user authentication |
2054 // |
2054 // |
2055 final String[] credentials = new String[] { "guest" , "guestpasswd" }; |
2055 final String[] credentials = new String[] { "guest" , "guestpasswd" }; |
2056 env.put("jmx.remote.credentials", credentials); |
2056 env.put("jmx.remote.credentials", credentials); |
2057 </pre> |
2057 </pre> |
2058 </li> |
2058 </li> |
2059 <li>Providing an <code>SslRMIClientSocketFactory</code> to interact |
2059 <li>Providing an <code>SslRMIClientSocketFactory</code> to interact |
2060 with the secure RMI Registry: |
2060 with the secure RMI Registry: |
2061 <pre> |
2061 <pre> |
2062 // Provide the SSL/TLS-based RMI Client Socket Factory required |
2062 // Provide the SSL/TLS-based RMI Client Socket Factory required |
2063 // by the JNDI/RMI Registry Service Provider to communicate with |
2063 // by the JNDI/RMI Registry Service Provider to communicate with |
2064 // the SSL/TLS-protected RMI Registry |
2064 // the SSL/TLS-protected RMI Registry |
2065 // |
2065 // |
2066 env.put("com.sun.jndi.rmi.factory.socket", |
2066 env.put("com.sun.jndi.rmi.factory.socket", |
2138 </DirectoryScannerList> |
2138 </DirectoryScannerList> |
2139 </ScanManager> |
2139 </ScanManager> |
2140 |
2140 |
2141 Invoke 'close' on ScanManagerMXBean |
2141 Invoke 'close' on ScanManagerMXBean |
2142 |
2142 |
2143 Got expected security exception: java.lang.SecurityException: Access denied! |
2143 Got expected security exception: java.lang.SecurityException: Access denied! |
2144 Invalid access level for requested MBeanServer operation. |
2144 Invalid access level for requested MBeanServer operation. |
2145 |
2145 |
2146 Close the connection to the server |
2146 Close the connection to the server |
2147 |
2147 |
2148 Bye! Bye! |
2148 Bye! Bye! |
2149 </pre> |
2149 </pre> |
2150 </td></tr></table></center> |
2150 </td></tr></table></center> |
2151 <p>If the <code>ScanDirClient</code> fails to connect with |
2151 <p>If the <code>ScanDirClient</code> fails to connect with |
2152 the secure agent, then this article - <a |
2152 the secure agent, then this article - <a |
2153 href="http://blogs.sun.com/roller/page/jmxetc?entry=troubleshooting_connection_problems_in_jconsole" |
2153 href="http://blogs.sun.com/roller/page/jmxetc?entry=troubleshooting_connection_problems_in_jconsole" |
2154 title="Troubleshooting connection problems in JConsole" |
2154 title="Troubleshooting connection problems in JConsole" |
2155 >Troubleshooting connection problems in JConsole</a> - may help |
2155 >Troubleshooting connection problems in JConsole</a> - may help |
2156 you figure out what is going wrong. Indeed the connection steps |
2156 you figure out what is going wrong. Indeed the connection steps |
2157 performed by the <code>ScanDirClient</code> are very similar to |
2157 performed by the <code>ScanDirClient</code> are very similar to |
2158 those performed by <code>jconsole</code>, and the problems you |
2158 those performed by <code>jconsole</code>, and the problems you |
2159 could encounter are identical. Just remember that |
2159 could encounter are identical. Just remember that |
2160 <code>jconsole</code> needs the extra <code>-J</code> flag to pass |
2160 <code>jconsole</code> needs the extra <code>-J</code> flag to pass |
2161 system properties to the VM, which is not needed with regular |
2161 system properties to the VM, which is not needed with regular |
2162 <code>java</code> launcher invocations. |
2162 <code>java</code> launcher invocations. |
2163 </p> |
2163 </p> |
2164 </ul> |
2164 </ul> |
2165 |
2165 |
2166 <h2><a name="h2-Conclusion">Conclusion</a></h2> |
2166 <h2><a name="h2-Conclusion">Conclusion</a></h2> |
2167 <ul> |
2167 <ul> |
2168 <p> |
2168 <p> |
2169 In this document, we have presented an advanced |
2169 In this document, we have presented an advanced |
2170 JMX example, and shown how to run a secure |
2170 JMX example, and shown how to run a secure |
2171 JMX agent in a production environment. |
2171 JMX agent in a production environment. |
2172 We have also shown how to connect to such a |
2172 We have also shown how to connect to such a |
2173 secure agent with both jconsole and a programmatic |
2173 secure agent with both jconsole and a programmatic |
2174 client. We have also discuss various JMX |
2174 client. We have also discuss various JMX |
2175 design-patterns and best practices. |
2175 design-patterns and best practices. |
2176 Readers who would wish to learn more about JMX, and |
2176 Readers who would wish to learn more about JMX, and |
2177 Monitoring and Management of the JVM, are invited |
2177 Monitoring and Management of the JVM, are invited |
2178 to follow the links given in reference below. |
2178 to follow the links given in reference below. |
2179 </p> |
2179 </p> |
2180 </ul> |
2180 </ul> |
2182 <ol> |
2182 <ol> |
2183 <li><a href="http://java.sun.com/products/JavaManagement/best-practices.html" |
2183 <li><a href="http://java.sun.com/products/JavaManagement/best-practices.html" |
2184 >JMX Best Practices</a>: This document describes best practices that |
2184 >JMX Best Practices</a>: This document describes best practices that |
2185 have been identified for modeling using the JMX API. </li> |
2185 have been identified for modeling using the JMX API. </li> |
2186 <li><a href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html" |
2186 <li><a href="http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html" |
2187 >Monitoring and Management Using JMX</a>: How to enable, configure, and |
2187 >Monitoring and Management Using JMX</a>: How to enable, configure, and |
2188 connect to the JVM JMX agent.</li> |
2188 connect to the JVM JMX agent.</li> |
2189 <li><a name="JConsole"><a |
2189 <li><a name="JConsole"><a |
2190 href="http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html" |
2190 href="http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html" |
2191 >Using JConsole</a>: JConsole is a JMX-Compliant monitoring tool which allows |
2191 >Using JConsole</a>: JConsole is a JMX-Compliant monitoring tool which allows |
2192 you to interact graphically with your own MBeans. |
2192 you to interact graphically with your own MBeans. |
2193 </li> |
2193 </li> |
2194 <li><a href="http://java.sun.com/javase/6/docs/technotes/guides/management/" |
2194 <li><a href="http://java.sun.com/javase/6/docs/technotes/guides/management/" |
2195 >Monitoring and Management for the Java Platform</a>: The Java Platform |
2195 >Monitoring and Management for the Java Platform</a>: The Java Platform |
2196 Standard Edition (Java SE) 6 provides comprehensive monitoring and |
2196 Standard Edition (Java SE) 6 provides comprehensive monitoring and |
2197 management support for the Java platform. </li> |
2197 management support for the Java platform. </li> |
2198 <li><a href="http://java.sun.com/products/JavaManagement/community/jmx_blogs.html" |
2198 <li><a href="http://java.sun.com/products/JavaManagement/community/jmx_blogs.html" |
2199 >List of JMX-related Blogs</a>: This page provides links to the |
2199 >List of JMX-related Blogs</a>: This page provides links to the |
2200 different web logs written by members of the Sun team working on the |
2200 different web logs written by members of the Sun team working on the |
2201 JMX API.</li> |
2201 JMX API.</li> |
2202 <li><a |
2202 <li><a |
2203 href="http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#HowSSLWorks" |
2203 href="http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#HowSSLWorks" |
2204 title="The JSSE Reference Guide" |
2204 title="The JSSE Reference Guide" |
2205 >Java<sup>TM</sup> Secure Socket Extension (JSSE) Reference Guide</a>: |
2205 >Java<sup>TM</sup> Secure Socket Extension (JSSE) Reference Guide</a>: |
2206 comprehensive documentation about the Java<sup>TM</sup> Secure Socket |
2206 comprehensive documentation about the Java<sup>TM</sup> Secure Socket |
2207 Extension (JSSE) |
2207 Extension (JSSE) |
2208 </li> |
2208 </li> |
2209 <li><a href="http://java.sun.com/javase/6/docs/" |
2209 <li><a href="http://java.sun.com/javase/6/docs/" |
2210 >Java SE 6 Documentation Index</a>: This document covers the |
2210 >Java SE 6 Documentation Index</a>: This document covers the |
2211 Java<sup>TM</sup> Platform, Standard Edition 6 JDK.</li> |
2211 Java<sup>TM</sup> Platform, Standard Edition 6 JDK.</li> |