Tools
Prev | Chapter 7. MX4J Examples | Next

## Tools

### Using XDoclet

#### Introduction

MX4J provides a way to generate source code of MBean interfaces and descriptions using some custom javadoc comments in source code. This source generation is done with the help of XDoclet. It is recommended to look at the example included in the distribution for getting started with this feature.

#### Preparing Ant

In order to generate the source code, XDoclet must be copied into the directory where all libraries are. This is usually the lib subdirectory of the project which will be referred as the Ant variable ${lib} from now on. A path must be defined for the Ant task. An example is given below:

Example 7.6. Defining the xdoclet classpath and Ant task.

    <path id="xdoclet">
       <pathelement location="${lib.dir}/xjavadoc.jar"/>
       <pathelement location="${lib.dir}/xdoclet.jar"/>
       <pathelement location="${lib.dir}/xdoclet-jmx-module.jar"/>
       <pathelement location="${lib.dir}/xdoclet-mx4j-module.jar"/>
       <pathelement location="${lib}/log4j.jar"/>
       <pathelement location="${ANT_HOME}/lib/ant.jar"/>
       <pathelement location="${build}"/>
    </path>
    <taskdef name="jmxdoclet" classname="xdoclet.jmx.JMXDocletTask">
       <classpath refid="xdoclet"/>
    </taskdef>

Let's suppose now that the Ant compilation target is called compilation. The easiest way to generate the source code of the MBean interface and description is to make the compilation depending on the target generateJMX defined by:

Example 7.7.

    <target name="generate-jmx" depends="init">
       <!-- Generate the MBean interfaces and descriptions -->
       <jmxdoclet sourcepath="${src}" destdir="${src}" classpathref="xdoclet" force="yes">
          <fileset dir="${src}">
             <include name="com/xtremejava/webos/**" />
          </fileset>
          <!-- Create the {0}MBean interface for the MBean -->
          <mbeaninterface/>
          <!-- Create the MX4J specific description adaptor class for the MBean -->
          <mx4jdescription />
          <!-- Generate the mlet file -->
          <mlet destinationFile="mbeans.mlet" destdir="conf"/>
       </jmxdoclet>
    </target>

#### Basic usage

A few javadoc tags can be used in order to specify how to generate the interface and the description of your MBean.

Table 7.1. List of Javadoc tags

Javadoc Tag Name | Meaning
--- | ---
@jmx:mbean | Tag used in order to define the name of the MBean and its description. Must be defined at class level.
@jmx:managed-constructor | Tag used in order to define the name of the constructor and its description. Must be defined at constructor level.
@jmx:managed-constructor-parameter | Tag used in order to define the name of a constructor attribute, it's index, and its description. Must be defined at constructor level.
@jmx:managed-operation | Tag used in order to define the name of an operation and its description. Must be defined at method level.
@jmx:managed-operation-parameter | Tag used in order to define the name of an operation attribute, it's index, and its description. Must be defined at method level.
@jmx:managed-attribute | Tag used in order to define the description of an attribute. Must be defined at method level. Note: the getter description has priority over the setter description.
@jmx:mlet-entry | Tag used in order to generate the mlets file. All classes having this tags will have the result merge in one file. Must be defined at class level.

### FilePersister example

#### Introduction

This example will cover the usage of the FilePersister with MLets. It will give a good overview of how to use MLets into the bargain :-). What we will do is create two MBeans the one extends FilePersister, so that it can load and store Objects. The other is a standard MBean which will ask the FilePersisterMBean to store it, The interesting thing about this example is that the two mbeans are loaded by two differnet MLets from two different jar files. One note of importance any object to be stored must implement the interface Serializable. Let us begin.

#### Writing the code

We are going to write an MBean which extends FilePersister and pass any calls made to it to its parent class.

Example 7.8. MBeanOne implementation

    public class MBeanOne extends FilePersister implements Serializable
    {
       public MBeanOne(String location, String name) throws MBeanException
           {
          super(location, name);
           }

       public void store(Object mbean)throws MBeanException, InstanceNotFoundException
       {
          store(mbean);
       }

       public Object load()throws MBeanException, RuntimeOperationsException, InstanceNotFoundException
       {
          return load();
       }
    }

Now to do the mbean that will ask the MBeanOne to store it.

Example 7.9. MBeanTwo implementation

    public class MBeanTwo implements MBeanTwoMBean, Serializable
    {
       // constructor... see example
       //we are now going to invoke MBeanOne through the MBeanServer
       public void storeIt(MBeanServer server, ObjectName name)
       {
          server.invoke(name, "store", new Object[]{this}, new String[]{"java.lang.Object"});
       }

       public Object loadIt(MBeanServer server, ObjectName name)
       {
          Object me = null;
          try
          {
             me = (MBeanTwo)server.invoke(name, "load", new Object[0], new String[0]);
          }
          catch (Exception ex)
          {
             ex.printStackTrace();
          }
          return me;
       }
    }

#### The Agent MLet implementation

The "main" class will now create and register two MLets, each MLet will load its own MBean from separate jar files

Example 7.10. The FilePersisterAgent

    // Create the MBeanServer
    // Build the ObjectNames for the MLets
    // Register the MLets
    MLet mlet1 = new MLet();
    m_server.registerMBean(mlet1, mName1);
    mlet1.addURL(jarOneUrl);

    MLet mlet2 = new MLet();
    m_server.registerMBean(mlet2, mName2);
    mlet2.addURL(jarTwoUrl);

    // We now have access to the MBeans, so instantiate them
    m_server.createMBean(mbeanClassName, mbeanObjectName, mLetObjectName, params, signature);

    // As above but the other mbean is now registered using the othe MLet object name as the third parameter
    m_server.createMBean(.....);

    // Now invoke the storage of one MBean by the other
    m_server.invoke(mbeanName2, "storeIt", new Object[] {m_server, mbeanName1},
                 new String[]{"javax.management.MBeanServer", "javax.management.ObjectName"});

    // Now load it
    Object a = m_server.invoke(mbeanName2, "loadIt", new Object[] {m_server, mbeanName1},
               new String[]{"javax.management.MBeanServer", "javax.management.ObjectName"});

    // And finally a test to see that the objects are equal
    if(a.getClass().getName() == mbeanClass2) System.out.println("Objects are equal and the same");

#### Steps for Running the Example

Once you have the files and compiled them you will need to build the jars holding the mbeans start a command prompt (windows) cd to the examples/classes directory and type in the following commands:

Example 7.11.

    jar cvf one.jar examples/tools/persister/MBeanOne.class
    // and then
    jar cvf two.jar examples/tools/persister/MBeanTwo.class examples/tools/persister/MBeanTwoMBean.class

Now delete the MBeanOne.class and MBeanTwo.class (we do not want them in the classpath :-). Once this is done add four application parameters

- 1) path to jar one.jar eg:file:C:/dev/mx4j/one.jar
- 2) path to jar two.jar eg: file:C:/dev/two.jar
- 3) path where to store the file eg: C:/temp
- 4) name of the file eg: test.ser

You are now ready to start the agent! Have fun !!

Prev | Home | Next
MBeans | Up | Chapter 8. FAQ