Java Dynamic Management Kit 5.1 Tutorial

18.3 Virtual SNMP Tables

This example shows how to implement virtual SNMP tables when instrumenting a MIB in Java DMK. It is based on the same MIB as the one used in the MBean Table Instrumentation example, so you should make sure you have run that example before running this one. However, the fundamental difference between this example and the SNMP Table Instrumentation example is that the tables implemented remain entirely virtual. The tables are calculated whenever they are needed by an SNMP request, rather than residing permanently in the SNMP session. The virtual table is also created with a limited period of validity. Once this period has expired, if the request for which the table was calculated has been executed, the table can be garbage-collected. There are thus two main advantages to operating with virtual tables rather than with tables that are permanently present.

The virtual SNMP table example is based on the classes in the examplesDir/current/Snmp/MBeanVirtualTable directory. It defines the MIB called JMX-MBEAN-SERVER-MIB that exposes the content of an MBean server through SNMP. This MIB is the same as the one defined in the previous example. To achieve this, JMX-MBEAN-SERVER-MIB defines the same two SNMP tables as before:

18.3.1 Classes Generated by mibgen

Before you can proceed with this example, you need to generate the JMX-MBEAN-SERVER-MIB and it's associated classes, by using the mibgen compiler supplied with Java DMK. For details of the mibgen compiler, see the Java Dynamic Management Kit 5.1 Tools Reference Guide.

To Generate the JMX-MBEAN-SERVER-MIB

The example MIB is contained in the configuration file JMX-MBEAN-SERVER-MIB.mib, which is found in examplesDir/current/Snmp/MBeanVirtualTable. You should run the example from within this directory.

  1. Ensure that your PATH environment variable knows where to find mibgen.

    In a default installation, mibgen is found in installDir/bin.

  2. Create a new directory, generated, inside examplesDir/current/Snmp/MBeanVirtualTable.


    $ mkdir generated
    

    This directory is where mibgen generates the classes associated with JMX-MBEAN-SERVER-MIB.mib.

  3. Run the mibgen compiler.


    $ mibgen -X:use-display-hint -X:no-table-access -X:abstract-mib \
               -d generated JMX-MBEAN-SERVER-MIB.mib
    

    The advanced mibgen option use-display-hint instructs mibgen to generate an attribute of type String for any object using a textual convention whose DISPLAY-HINT is 255a. This option is used because JMX-MBEAN-SERVER-MIB defines textual conventions (for example, JmxMBeanObjectNameTC) which must be translated into java.lang.String attributes, rather than the default Byte[] attributes.

    The -X:no-table-access option instructs mibgen not to generate a table accessor in the group MBean interfaces. The effect of this is that the accessors used to return the TableJmxMBeanTable and TableJmxMBeanAttrTable table objects are not created.

    The -X:abstract-mib option, as the name suggests, generates an abstract MIB. In this case, the MIB class is an abstract class, in which the MBean factory methods are also abstract.

    The -d generated option sends the output of mibgen to the newly created generated directory

    Using the first two options makes it possible to get rid of any references to the default JmxMBeanServer class, as well as to its associated Table* objects. These classes are still generated, but our customer implementation no longer references them.

The MIB used in this example is the same as the one used in the SNMP table instrumentation example. Consequently, mibgen generates the same files in the generated directory as were generated in the table instrumentation example. The differences between this example and the instrumentation example are found in the customized classes, that are used to extend the generated classes.

18.3.2 Customized Classes

The customized classes extend the functionality of the classes of the generated MIB. As was the case in the previous example, the JMX_MBEAN_SERVER_MIB_Impl extends the JMX-MBEAN-SERVER-MIB generated by mibgen, to instantiate the instrumented JmxMBeanServerImpl class. However, the extended behavior that the customized classes bring to the MIB in this example differs from that provided by the SNMP table instrumentation example. Most significantly, whereas the JmxMBeanServerImpl class was the principal author of the customized behavior of the MIB in the previous example, in this example the bulk of the work is done by JmxMBeanTableMetaImpl.

The following sections examine each of the customized classes, describing their purpose, and where necessary, highlighting their differences with the corresponding classes in the SNMP table instrumentation example.

18.3.2.1 JmxMBeanServerImpl

JmxMBeanServerImpl instruments the jmxMBeanServer group defined in the MIB. It implements the JmxMBeanServerMBean interface that is generated by mibgen, but unlike the previous example, it does not extend the generated JmxMBeanServer skeleton. As a result of not extending the JmxMBeanServer object, and also because the MIB was generated with the -X:no-table-access option, the generated TableJmxMBeanTable and TableJmxMBeanAttrTable objects are not instantiated. Although they are still generated by mibgen, these classes are not used in this example.

The jmxMBeanTable and jmxMBeanAttrTable tables are implemented as virtual tables. They are computed on the fly when an SNMP request needs to access them. Furthermore, the jmxMBeanTable and jmxMBeanAttrTable tables are managed by their respective customized JmxMBeanTableMetaImpl and JmxMBeanAttrTableMetaImpl meta objects. In the table instrumentation example, the tables were managed by the JmxMBeanServerImpl object.

18.3.2.2 JmxMBeanServerMetaImpl

JmxMBeanServerMetaImpl extends the generated JmxMBeanServerMeta class, that is used to represent SNMP metadata for the JmxMBeanServer group.

JmxMBeanServerMetaImpl overrides the table-meta factory methods in order to instantiate customized implementations of the JmxMBeanTableMeta and JmxMBeanAttrTableMeta meta classes. These meta classes are customized in the JmxMBeanTableMetaImpl and JmxMBeanAttrTableMetaImpl meta classes, that are shown in 18.3.2.3 JmxMBeanTableMetaImpl and 18.3.2.4 JmxMBeanAttrTableMetaImpl respectively.

18.3.2.3 JmxMBeanTableMetaImpl

JmxMBeanTableMetaImpl extends the generated JmxMBeanTableMeta class, and overrides the following JmxMBeanTableMeta methods.

In addition to overriding the above methods, it is the JmxMBeanTableMetaImpl class that implements the caching mechanism. An SnmpUserData factory is used to create a transient request-contextual cache, that will remain active for the duration of the incoming request. After the request has completed, the contextual-cache is garbage-collected.

JmxMBeanTableMetaImpl defines the following subclasses, that implement the caching mechanism.

18.3.2.4 JmxMBeanAttrTableMetaImpl

JmxMBeanAttrTableMetaImpl extends the generated JmxMBeanAttrTableMeta class, and overrides the following methods.

The methods createNewEntry(SnmpMibSubRequest req, SnmpOid rowOid, int depth), and removeTableRow(SnmpMibSubRequest req, SnmpOid rowOid, int depth) are not overriden. The table is read-only, so these methods will never be called.

This class does not use any specific caching mechanism. Since the jmxMBeanAttrTable is an extension of the jmxMBeanTable it simply relies on the cache established for the jmxMBeanTable. The list of attributes pertaining to a specific MBean is cached, if necessary, in the corresponding JmxMBeanEntryImpl object, which can be reclaimed at the end of the request. Note that attribute values are not cached, but rather they are obtained when they are needed.

18.3.2.5 JmxMBeanContextFactory

JmxMBeanContextFactory implements the com.sun.management.snmp.agent.SnmpUserDataFactory interface. The userData allocated by this factory is a java.util.Map that serves as a request-contextual cache. When the MIB instrumentation needs to access a piece of data, it proceeds as follows.

This mechanism ensures the coherency of the data returned in the response. Once a piece of data has been loaded into the request-contextual cache, it is consistently reused for the whole duration of the request. This makes sure that the same snapshot is always used during the request, even if the underlying managed object constantly changes its value.

18.3.2.6 JmxMBeanEntryImpl

JmxMBeanEntryImpl extends theJmxMBeanEntry skeleton that is generated by mibgen, and adds instrumentation to the entries of the jmxMBeanTable table defined in the MIB. Each JmxMBeanEntry represents an MBean registered in the exposed MBean server. The JmxMBeanEntry objects are created on the fly when needed. They are temporary objects which are created when an SNMP request needs access to the instrumented MBean. Once created, JmxMBeanEntry objects are put in the request-contextual cache, where they remain until the request completes.

18.3.2.7 JmxMBeanAttrEntryImpl

JmxMBeanAttrEntryImpl extends theJmxMBeanAttrEntry skeleton that is generated by mibgen, and adds instrumentation to the entries of the jmxMBeanAttrTable table defined in the MIB. Like JmxMBeanEntry objects, JmxMBeanAttrEntry objects are created on the fly when an SNMP request needs access to the instrumented MBean attributed.

JmxMBeanAttrEntry objects are stored in their corresponding JmxMBeanEntryImpl objects, which are themselves cached in the request-contextual cache and in the JmxMBeanTableCache.

18.3.3 Running the SNMP Virtual Tables Example

After you have run mibgen to generate JMX_MBEAN_SERVER_MIB and its associated classes, as explained in 18.2.1 Classes Generated by mibgen, you can run the example.

To Run the SNMP Virtual Tables Example

Run the example from the examplesDir/current/Snmp/MBeanVirtualTable directory.

  1. Compile the Java classes in the generated directory.


    $ cd generated
    $ javac -d .. *.java
    

    This creates the compiled *.class files into the examplesDir/current/Snmp/MBeanVirtualTable directory, rather than in generated, so that they are accessible to the other classes used in the example.

  2. Compile the Java classes in the examplesDir/current/Snmp/MBeanVirtualTable directory.


    $ cd ..
    $ javac -d . *.java
    
  3. Start the Agent.

    You have several options when starting the Agent class.

    • To start the Agent on the default SNMP port, 16161:


      $ java  Agent service:jmx:jmxmp://
      
    • To start the Agent on a port of your choice:


      $ java  -Dsnmp.port=port_number Agent service:jmx:jmxmp://
      
    • To start the Agent with a connector of your choosing, you can specify a different service URL and connector port. For example:


      $ java  Agent JMX_service_URL
      

    In any of the above cases, you see confirmation of the SNMP port used, confirmation of the creation of the connector and then the alternating registration and deregistration of sets of five MBeans.

  4. You can now perform management operations on the Agent.

    Use a JMX management console of your choice to examine the content of the MBean server through a JMXMP connector.

    Use the SNMP management application, easymanager, that is supplied with Java DMK to examine the JMX-MBEAN-SERVER-MIB through SNMP. You can find the easymanager application in the installDir/contributions/easymanager directory.

To Examine JMX-MBEAN-SERVER-MIB Using easymanager
  1. Add the JMX-MBEAN-SERVER-MIBOidTable.class to your classpath.

    Type the following command if you are using a UNIX platform:


    $ export CLASSPATH=$CLASSPATH:examplesDir/current/Snmp/MBeanVirtualTable/

    Type the following command if you are using a Windows platform:


    set classpath=%classpath%;examplesDir/current/Snmp/MBeanVirtualTable/
  2. Open installDir/contributions/easymanager/bin

  3. Start easymanager.

    If the SNMP agent has been started with the default example port, type the following command.


    $ easymanager.sh -port 16161 

    You can now use easymanager to perform the following operations.

    • Pop up a MIB discovery window.


      discovermib -p JDMK_STD_V2_profile
      
    • Create a new MBean.


      set:2 -w private :<<jmxMBeanObjectName.998,4,Test:name=test1>,
      <jmxMBeanClassName.998,4,Agent$Simple>,
      <jmxMBeanRowStatus.998,2,4>>
      
    • Click on resynch in the MIB discovery window to observer the changes in the MIB.

    • Destroy the MBean you created.


      set:2 -w private :<<jmxMBeanRowStatus.998,2,6>>