The "Dynamic" in Java Dynamic Management Kit not only stands for dynamic loading, it also stands for dynamic downloading. The agent service that provides this functionality is the m-let class loader. M-let stands for management applet, an HTML-style tag that tells the class loader how to retrieve the desired class. Using this information, the m-let loader can retrieve an MBean class from a remote location given as a URL (uniform resource locator) and create it in the agent.
The m-let resides in a separate text file which acts as a loading manifest. The contents of the m-let file let you specify any number of classes to load, possibly a different source for each, arguments for the class constructor, and the object name for the instantiated MBean. Since this mechanism is sometimes too heavy, the m-let loader can also be used to load classes directly and create MBeans in the agent.
The m-let loader is a service implemented as an MBean, so it can be called either directly by the agent or remotely by a management application. It can also be managed remotely, which allows a manager to effectively "push" MBeans to an agent: the manager instantiates the m-let loader in an agent and instructs it to load classes from a predetermined location.
Class loading is significantly different between Java 2 and JDK 1.1.x, and this leads to different implementations of the m-let loader. We cover these in separate sections. The example code in the MLetAgent and MLetClient directories of the main examplesDir corresponds to the Java version which you specified during installation (see "Directories and Classpath" in the preface).
Contents:
In an agent application, we might need to load MBeans from remote hosts during the initialization. Or we might have local threads which need to load MBeans in the agent. In this example we demonstrate how to create the m-let loader service and use it to dynamically load new MBean classes.
In an installation of the Java Dynamic Management Kit for the JDK 1.1.x, the m-let loader is the MLetSrv class in the javax.management.loading package. It is an MBean which needs to be registered in the MBean server before we can use it to load classes.
MBeanServer server = MBeanServerFactory.createMBeanServer(); // Get the domain name from the MBeanServer. String domain = server.getDefaultDomain(); // Create a new MLetSrv MBean and add it to the MBeanServer. String mletClass = "javax.management.loading.MLetSrv"; ObjectName mletName = new ObjectName(domain + ":name=" + mletClass); server.createMBean(mletClass, mletName); |
There is no special initialization that needs to be done for the m-let loader.
In order to download an MBean, we must first have its corresponding m-let definition in an HTML file. In our example, we define the following file with three MLET tags:
<HTML> <MLET CODE=Square.class ARCHIVE=Square.jar NAME=MLetExample:name=Square,id=1 > <ARG TYPE=java.lang.Integer VALUE=10> </MLET> <MLET CODE=EquilateralTriangle.class ARCHIVE=EquilateralTriangle.jar NAME=MLetExample:name=EquilateralTriangle,id=1 > <ARG TYPE=java.lang.Integer VALUE=8> </MLET> <MLET CODE=EquilateralTriangle.class ARCHIVE=EquilateralTriangle.jar NAME=MLetExample:name=EquilateralTriangle,id=2 > <ARG TYPE=java.lang.Integer VALUE=15> </MLET> </HTML> |
This file tells the m-let loader to create three MBeans with the given object names, using the given classes in the jar files. The ARG tag gives a parameter to be passed to the class' constructor. The number and type of ARG tags specified must match one of the public constructors for the class
The jar files must be located in the same directory as this file, regardless of whether the directory is on a local or remote host. The MLET tag may also specify a CODEBASE, which is an alternate location for the jar file. This m-let loader relies on the definition of MLET tag given by the JMX specification.
Now we are ready to call the performLoadURL method of our m-let loader. In parsing the result vector, we use our knowledge of the class names that we wrote in the m-let file.
ObjectName squareMLetClassLoader = null; ObjectName triangleMLetClassLoader = null; // The url string is read from the command line Object mletParams[] = {url}; String mletSignature[] = {"java.lang.String"}; Vector mbeanList = (Vector) server.invoke( mletName, "performLoadURL", mletParams, mletSignature); for (Enumeration enum = mbeanList.elements(); enum.hasMoreElements(); ) { Object element = enum.nextElement(); if (element instanceof Vector) { // Success, we retrieve the new object name Vector v = (Vector) element; ObjectInstance objectInstance = (ObjectInstance) v.elementAt(0); ObjectName classLoaderObjectName = (ObjectName) v.elementAt(1); if (objectInstance.getClassName().equals("Square")) { // Retrieve MBean that loaded the class Square squareMLetClassLoader = classLoaderObjectName; } else if (objectInstance.getClassName().equals( "EquilateralTriangle")) { // Retrieve MBean that loaded the class EquilateralTriangle triangleMLetClassLoader = classLoaderObjectName; } println("\tOBJECT NAME = " + objectInstance.getObjectName()); } else { // Failure, find out why println("\tEXCEPTION = " + ((Throwable)element).getMessage()); } } |
The result of the call to performLoadURL is a Vector object containing as many elements as there are MLET tags in the file designated by the URL. Each element is either a vector containing the object instance of the new MBean and the object name of its class loader, or a Throwable object containing the exception or error that prevented the MBean from being loaded. The order of the elements may differ from the order of the tags in the file.
In the result, we obtain the object name of the MBeans that were created from the downloaded classes. The management architecture specified by JMX is designed so that objects are manipulated through the MBean server, not by direct reference. Therefore, downloaded classes are directly registered in the MBean server by the m-let loader, and the caller never receives a direct reference to the new object.
The object names of the class loaders are references to the internal class loader objects used by the m-let service to actually fetch the classes. We save them because they can be used if we ever need to instantiate these classes again. We will see how in the next section.
Loading MBeans from a URL requires some preparation and additional files. In some cases, we don't have the ability to create files ahead of time or modify them when we need different classes. In these cases, we would just like to load a class from a jar file and create its MBean.
The MLetSrv is not a class loader, we only ask it to load a class from a URL and it instantiates its private class loader for doing this. Even though the internal class loader object used by the m-let loader is a public type, it should not be instantiated to act as a class loader. The m-let loader stores internal information about its private class loaders, and it won't be able to handle one outside of its control.
Instead, use the class loader name that is returned when an MBean is successfully loaded. You can specify this class loader name when creating a class through the MBean server. You will be able to create new MBeans from the same class or from other classes in the associated archive (jar file).
This implies that you must first call the performLoadURL with a known URL and a known m-let file. The m-let loader will create one class loader for each code-base specified in the file, and one for the code-base of the file itself. For example, the class loader name returned with the "Square" MBean name is the one used to load its class from the Square.jar file in the same directory as the HTML file. We can create other instances of that MBean now just through the MBean server, without needing to call the m-let loader.
The following code sample uses the object name references that were declared and assigned in Example 6-3.
// Create a new Square MBean from its class in the Square.jar file String squareClass = "Square"; ObjectName squareName = new ObjectName( "MLetExample:name=" + squareClass + ",id=2"); Object squareParams[] = {new Integer(12)}; String squareSignature[] = {"java.lang.Integer"}; server.createMBean(squareClass, squareName, squareMLetClassLoader, squareParams, squareSignature); // Create a new EquilateralTriangle MBean from its class in the // EquilateralTriangle.jar file String triangleClass = "EquilateralTriangle"; ObjectName triangleName = new ObjectName( "MLetExample:name=" + triangleClass + ",id=3"); Object triangleParams[] = {new Integer(20)}; String triangleSignature[] = {"java.lang.Integer"}; server.createMBean(triangleClass, triangleName, triangleMLetClassLoader, triangleParams, triangleSignature); |
To run the m-let agent example for the JDK 1.1.x, you must have installed the Java Dynamic Management Kit for 1.1, and set your classpath accordingly. This example is located in the examplesDir/MLetAgent/ directory, see "Directories and Classpath" in the preface for details.
In our example, we have two MBeans representing geometrical shapes. Before running the example, we compile them and create a jar file for each. We also compile the agent application at the same time.
$ cd examplesDir/MLetAgent/ $ javac -classpath classpath *.java $ jar cf Square.jar Square.class SquareMBean.class $ rm Square.class SquareMBean.class $ jar cf EquilateralTriangle.jar EquilateralTriangle.class \ EquilateralTriangleMBean.class $ rm EquilateralTriangle.class EquilateralTriangleMBean.class |
Since the MBean classes are only found in the jar files now, they cannot be found in our usual classpath, even if it includes the current directory (.). However, these jar files are given as the archive in the MLET tags of the HTML file, so the m-let loader should find them.
The agent requires you to specify the URL of the m-let file on command line. We have left this file in the examples directory, but you could place it and the jar files on a remote machine. With the Korn shell on the Solaris platform, you would type the following command:
$ java -classpath classpath Agent file:${PWD}/GeometricShapes.html |
In the output of the agent, you can see it create the m-let service MBean, and then load the HTML file which specifies the three MBeans to be loaded. Once these have been loaded, we can see the two MBeans that were loaded directly through the class loader shortcut.
This agent uses the tracing mechanism, and you can select to receive the messages from the m-let loader by specifying the -DINFO_MLET property on the command line. The tracing mechanism is covered in the Java Dynamic Management Kit 4.0 Tools Reference guide and in the Javadoc API of the Trace class.
The agent then launches an HTML adaptor so that we can easily view the new MBeans. In them we can see that the values contained in the ARG tags of the m-let file were used to initialize the MBeans. Point your web browser to the following URL and click on the MBeans in the MLetExample domain:http://localhost:8082/. When you are done, type "Control-C" in the window where you launched the agent.
Like the other agent services of the Java Dynamic Management Kit, the m-let loader is an MBean and fully manageable from a remote manager. A manager application might want an agent to load a new MBean to represent a new resource or provide a new management service. In this example, we show a manager which interacts with the m-let loader of an agent to load exactly the same MBeans as in the previous example.
The agent that we will manage only contains an RMI connector and an HTML adaptor when it is launched. We will use the RMI connector to access the agent and perform all of our management operations. You can then view the new MBeans through the HTML adaptor.
The manager is just a simple application which creates its connector client, does its management operations and exits. Here is the code of its main method and the constructor that it calls.
public Client() { // Enable the trace mechanism [...] // Connect a new RMI connector client to the agent connectorClient = new RmiConnectorClient(); // Use the default address (localhost) RmiConnectorAddress address = new RmiConnectorAddress(); try { connectorClient.connect(address); } catch (Exception e) { println("Could not connect to the agent!"); e.printStackTrace(); System.exit(1); } } public static void main(String[] args) { // Parse command line arguments. [...] // Call the constructor to establish the connection Client client = new Client(); // Run the MLet example (see below) client.runMLetExample(); // Disconnect connector client from the connector server. client.connectorClient.disconnect(); System.exit(0); } |
Now that the manager is connected to the client, we can "push" classes to it. We do this by first creating an m-let loader service, then having that loader create MBeans from the classes designated by our HTML file. The following code is taken from manager's runMLetExample method. The code is identical to the code of the agent example, except that we now go through the RemoteMBeanServer interface of the connector client instead of directly through the MBean server.
// Get the domain name from the Agent String domain = connectorClient.getDefaultDomain(); // Create a new MLetSrv MBean and add it to the Agent String mletClass = "javax.management.loading.MLetSrv"; ObjectName mletName = new ObjectName(domain + ":name=" + mletClass); connectorClient.createMBean(mletClass, mletName); [...] // Create and register new Square and EquilateralTriangle MBeans // by means of an HTML document containing MLET tags // The url string is read from the command line ObjectName squareMLetClassLoader = null; ObjectName triangleMLetClassLoader = null; Object mletParams[] = {url}; String mletSignature[] = {"java.lang.String"}; Vector mbeanList = (Vector) connectorClient.invoke( mletName, "performLoadURL", mletParams, mletSignature); for (Enumeration enum = mbeanList.elements(); enum.hasMoreElements(); ) { Object element = enum.nextElement(); if (element instanceof Vector) { // Success, we retrieve the new object name Vector v = (Vector) element; ObjectInstance objectInstance = (ObjectInstance) v.elementAt(0); ObjectName classLoaderObjectName = (ObjectName) v.elementAt(1); if (objectInstance.getClassName().equals("Square")) { // Retrieve the MBean that loaded the Square squareMLetClassLoader = classLoaderObjectName; } else if (objectInstance.getClassName().equals( "EquilateralTriangle")) { // Retrieve the MBean that loaded the EquilateralTriangle triangleMLetClassLoader = classLoaderObjectName; } println("\tOBJECT NAME = " + objectInstance.getObjectName()); } else { // Failure, find out why println("\tEXCEPTION = " + ((Throwable)element).getMessage()); } } |
As in the agent application, we may need a shortcut for instantiating other MBeans without specifying an m-let file. Again, we can use an existing class loader from a previously loaded class to download the same classes again. We use the createMBean method of the connector client which lets us specify a class loader name. The following code is the rest of the manager's runMLetExample method, and it is also nearly identical to the agent's code.
// Create a new Square MBean from its class in the Square.jar file. String squareClass = "Square"; ObjectName squareName = new ObjectName( "MLetExample:name=" + squareClass + ",id=2"); Object squareParams[] = {new Integer(12)}; String squareSignature[] = {"java.lang.Integer"}; connectorClient.createMBean(squareClass, squareName, squareMLetClassLoader, squareParams, squareSignature); // Create a new EquilateralTriangle MBean from its class in the // EquilateralTriangle.jar file. String triangleClass = "EquilateralTriangle"; ObjectName triangleName = new ObjectName( "MLetExample:name=" + triangleClass + ",id=3"); Object triangleParams[] = {new Integer(20)}; String triangleSignature[] = {"java.lang.Integer"}; connectorClient.createMBean(triangleClass, triangleName, triangleMLetClassLoader, triangleParams, triangleSignature); |
Simulating a "push" of the MBeans in this way is plausible, since the management application can specify a URL where it controls the contents of the HTML file and knows which classes are available.
The MBeans in the agent and manager (client) examples are identical, and we will set up the example in exactly the same manner.
$ cd examplesDir/MLetClient/ $ javac -classpath classpath *.java $ jar cf Square.jar Square.class SquareMBean.class $ rm Square.class SquareMBean.class $ jar cf EquilateralTriangle.jar EquilateralTriangle.class \ EquilateralTriangleMBean.class $ rm EquilateralTriangle.class EquilateralTriangleMBean.class |
The manager is written to be run on the same host as the agent application. If you wish to run it on a different host, you will need to modify the code for the Client class constructor where the agent address is specified (see Example 6-5). You could place the jar files and the m-let file on a remote machine and specify its new URL as the parameter to the manager application; we run the example with this file in the current directory.
Before launching the manager, you must launch the agent. Here we give commands for launching the applications from the same terminal window running the Korn shell. On the Windows NT platform, you will have to launch each application in a separate window.
$ java -classpath classpath Agent & $ java -classpath classpath Client file:${PWD}/GeometricShapes.html |
In the output of the manager, you can see it create the m-let service MBean, and then ask it to load the HTML file. Finally, we can see the two MBeans that were loaded directly through the class loader shortcut. If you connect to the agent in a web browser at the following URL: http://localhost:8082/ and reload its agent view every time the manager pauses, you can see the MBeans as they are created.
The agent terminates after it disconnects its connector client. When you are done viewing the agent, type the following commands to stop the agent application:
$ fg java [...] Agent <Control-C> ^C$ |
In the version of the Java Dynamic Management Kit for Java 2, the m-let loader is itself a class loader object. It extends the URLClassLoader class of the java.net package to simplify the downloading service it provides.
The m-let loader service is an instance of the MLet class in the javax.management.loading package. It is also an MBean that can be accessed remotely. It provides m-let file loading and the shortcut method seen in the version for the JDK 1.1. In addition, it inherits the behavior which lets it be used directly as a class loader, without requiring an m-let file.
We will start by demonstrating the usage of the m-let service as it would be used in an agent or in an MBean. In our example, the agent application creates an MBean server and then the m-let loader.
// Parse debug properties and command line arguments. [...] // Instantiate the MBean server MBeanServer server = MBeanServerFactory.createMBeanServer(); String domain = server.getDefaultDomain(); // Create a new MLet MBean and add it to the MBeanServer. String mletClass = "javax.management.loading.MLet"; ObjectName mletName = new ObjectName(domain + ":name=" + mletClass); server.createMBean(mletClass, mletName); |
There is no special initialization that needs to be done before loading classes through an m-let file.
In this example we will only load EquilateralTriangle MBeans through the m-let file. We use the same m-let file which is shown in Example 6-2, but without the tags for the Square MBeans.
The code for downloading the MBeans specified in the m-let file is also similar. In the Java 2 version of the m-let loader, only the name of the method to call and the format of its return value is different. In this code we call the getMBeansFromURL method and analyze the result:
// the url_2 string is read from the command line println("\tURL = " + url_2); Object mletParams_2[] = {url_2}; String mletSignature_2[] = {"java.lang.String"}; Set mbeanSet = (Set) server.invoke(mletName, "getMBeansFromURL", mletParams_2, mletSignature_2); for (Iterator i = mbeanSet.iterator(); i.hasNext(); ) { Object element = i.next(); if (element instanceof ObjectInstance) { // Success, we display the new MBean's name println("\tOBJECT NAME = " + ((ObjectInstance)element).getObjectName()); } else { // Failure, we display why println("\tEXCEPTION = " + ((Throwable)element).getMessage()); } } |
The structure of the returned set is much simpler than in the case of the JDK 1.1 loader. In the JDK 1.1 version, the m-let loader handles separate class loader objects, one for each code-base it has accessed. In the Java 2 version, the m-let loader is the class loader, and it handles just a list of code-bases that it has accessed directly. You can view this list by calling the getURLs method of the m-let loader MBean.
This behavior means that the getMBeansFromURL method does not need to return the object names of class loaders it has used. Instead it just returns either the object instance of the downloaded and registered MBean or a Throwable object in case or an error or an exception. These are returned in a Set object containing as many elements as there are MLET tags in the target m-let file.
This behavior also simplifies any repeated loading of the classes after they have been loaded from an m-let file. Because the m-let loader has already used the code-base of the MBean, it is available to be used again. All you need to do is specify the object name of the m-let loader as the class loader when creating the MBean.
You can also load other MBeans in the same code-base, once the code-base has been accessed by a call to the getMBeansFromURL method. In our example we will just download another MBean of the EquilateralTriangle class.
// Create another EquilateralTriangle MBean from its class // in the EquilateralTriangle.jar file. String triangleClass = "EquilateralTriangle"; ObjectName triangleName = new ObjectName( "MLetExample:name=" + triangleClass + ",id=3"); Object triangleParams[] = {new Integer(20)}; String triangleSignature[] = {"java.lang.Integer"}; server.createMBean(triangleClass, triangleName, mletName, triangleParams, triangleSignature); |
Since the m-let loader object is a class loader, you can use it to load classes directly, without needing to define an m-let file. This is the main advantage of the Java 2 version of the m-let loader service.
Before you can load an MBean directly, you need to add the URL of its code-base to the m-let loader's internal list. Then we just use the m-let loader's object name as the class loader name when creating the MBean. Here is the code to do this in the agent example:
// Add a new URL to the MLet class loader // The url_1 string is read from the command line Object mletParams_1[] = {url_1}; String mletSignature_1[] = {"java.lang.String"}; server.invoke(mletName, "addURL", mletParams_1, mletSignature_1); // Create a Square MBean from its class in the Square.jar file. String squareClass = "Square"; ObjectName squareName = new ObjectName( "MLetExample:name=" + squareClass); Object squareParams[] = {new Integer(10)}; String squareSignature[] = {"java.lang.Integer"}; server.createMBean(squareClass, squareName, mletName, squareParams, squareSignature); |
You only need to add the URL to the m-let loader the first time you want to download a class. Once it is added, we can load it as many times as necessary by calling createMBean directly.
Since this loading mechanism doesn't use the MLET tag, the programmer must insure that either the downloaded class provides its own object name or, as in the example above, the agent provides one.
The fact that the m-let loader is also a class loader into which you can load multiple URLs brings up the issue of name spaces. If there exists two classes with the same name within the code-bases defined by the set of all URLs, the m-let loader will load one of them non-deterministically. In order to specify one of them precisely, you shouldn't add the URL of the second code-base to the m-let loader. Instead, you will have to create a second m-let loader MBean to which you can add the URL for the second version of the class. In this case, you will have one m-let MBean that can load one version of the class and another m-let MBean that can load the other.
To run the m-let agent example for Java 2, you must have installed the Java Dynamic Management Kit for 1.2, and set your classpath accordingly. This example is located in the examplesDir/MLetAgent/ directory, see "Directories and Classpath" in the preface for details.
In our example, we have two MBeans representing geometrical shapes. Before running the example, we compile them and create a jar file for each. We also compile the agent application at the same time.
$ cd examplesDir/MLetAgent/ $ javac -classpath classpath *.java $ jar cf Square.jar Square.class SquareMBean.class $ rm Square.class SquareMBean.class $ jar cf EquilateralTriangle.jar EquilateralTriangle.class \ EquilateralTriangleMBean.class $ rm EquilateralTriangle.class EquilateralTriangleMBean.class |
The agent command line requires you to specify first the URL of a jar file for directly loading the Square class, then the URL of the m-let file. We have left these files in the examples directory, but you could place them on a remote machine. With the Korn shell on the Solaris platform, you would type the following command:
$ java -classpath classpath Agent \ file:${PWD}/Square.jar file:${PWD}/GeometricShapes.html |
In the output of the agent, you can see it create the m-let loader MBean, and then download classes to create MBeans. It starts with the direct loading of the Square class, and then loads from the HTML file which specifies two EquilateralTriangle MBeans to be loaded. Once these have been loaded, we can see the third one that is loaded through the class loader shortcut.
This agent uses the tracing mechanism, and you can select to receive the messages from the m-let loader by specifying the -DINFO_MLET property on the command line. The tracing mechanism is covered in the Java Dynamic Management Kit 4.0 Tools Reference guide and in the Javadoc API of the Trace class.
The agent then launches an HTML adaptor so that we can easily view the new MBeans. In them we can see that the values contained in the ARG tags of the m-let file were used to initialize the MBeans. Point your web browser to the following URL and click on the MBeans in the MLetExample domain: http://localhost:8082/. When you are done, type "Control-C" in the window where you launched the agent.
Since the MLet class is an MBean, the m-let loader service is fully manageable from a remote manager. This lets a manager create an m-let loader in an agent, add URLs to its list of code-bases, and create MBeans whose classes must be downloaded first.
Using the Java 2 m-let class loader, we can again implement a "push" mechanism originating from a management application. In fact, it is even easier due to the direct class loading that the MLet MBean allows.
In the example, our manager will create an m-let loader in an agent and have it load new MBean classes. Launched with only an RMI connector and an HTML adaptor, we can see at the end that the agent contains all of the new MBeans loaded from jar files, along with the m-let loader MBean. The initialization of manager is very simple:
public Client() { // Enable the trace mechanism [...] // Connect a new RMI connector client to the agent connectorClient = new RmiConnectorClient(); // Use the default address (localhost) RmiConnectorAddress address = new RmiConnectorAddress(); try { connectorClient.connect(address); } catch (Exception e) { println("Could not connect to the agent!"); e.printStackTrace(); System.exit(1); } } public static void main(String[] args) { // Parse command line arguments. [...] // Call the constructor to establish the connection Client client = new Client(); // Run the MLet example (see below) client.runMLetExample(); // Disconnect connector client from the connector server. client.connectorClient.disconnect(); System.exit(0); } |
Now that the manager is connected to the client, we can ask it to load classes. First we have it create an m-let loader MBean that we can use to download classes. Then we demonstrate the various ways of loading classes:
Through an m-let file, which has the advantage of loading many MBeans at once
Directly, from a code-base that was used in an m-let file
Directly, after specifying a URL for the code-base
The following code is taken from manager's runMLetExample method. The code is identical to the code of the agent example, except that we now go through the RemoteMBeanServer interface of the connector client instead of directly through the MBean server.
// Get the domain name from the MBeanServer. String domain = connectorClient.getDefaultDomain(); // Create a new MLet MBean and add it to the MBeanServer String mletClass = "javax.management.loading.MLet"; ObjectName mletName = new ObjectName(domain + ":name=" + mletClass); connectorClient.createMBean(mletClass, mletName); [...] // Create new EquilateralTriangle MBeans through MLET tags // The url_2 string is read from the command line Object mletParams_2[] = {url_2}; String mletSignature_2[] = {"java.lang.String"}; Set mbeanSet = (Set) connectorClient.invoke( mletName, "getMBeansFromURL", mletParams_2, mletSignature_2); for (Iterator i = mbeanSet.iterator(); i.hasNext(); ) { Object element = i.next(); if (element instanceof ObjectInstance) { // Success println("OBJECT NAME = " + ((ObjectInstance)element).getObjectName()); } else { // Failure println("EXCEPTION = " + ((Throwable)element).getMessage()); } } |
Now that the class loader has used the code-base of the jar file, we can create more of the MBeans from the same jar file. We invoke the createMBean method of the server with the object name of the class loader.
// Create another EquilateralTriangle MBean from the same jar file // used in the MLET file String triangleClass = "EquilateralTriangle"; ObjectName triangleName = new ObjectName( "MLetExample:name=" + triangleClass + ",id=3"); Object triangleParams[] = {new Integer(20)}; String triangleSignature[] = {"java.lang.Integer"}; connectorClient.createMBean(triangleClass, triangleName, mletName, triangleParams, triangleSignature); |
Finally, if we have a different code-base not associated with an m-let file, we can give its URL directly to the loader. This allows us to ask the agent to create almost any MBean, imitating a class "push" mechanism.
// Add a new URL to the MLet MBean to look for classes // The url_1 string is read from the command line Object mletParams_1[] = {url_1}; String mletSignature_1[] = {"java.lang.String"}; connectorClient.invoke(mletName, "addURL", mletParams_1, mletSignature_1); // Create a new Square MBean from its class in the Square.jar file String squareClass = "Square"; ObjectName squareName = new ObjectName( "MLetExample:name=" + squareClass); Object squareParams[] = {new Integer(10)}; String squareSignature[] = {"java.lang.Integer"}; connectorClient.createMBean(squareClass, squareName, mletName, squareParams, squareSignature); |
In this way, the manager can make code available on the network, and it can direct its agents to load the classes to create new MBeans ready for management. This mechanism can be used to distribute new resources, provide new services,or update applications, all under the control of the manager.
The MBeans in the agent and manager (client) examples are identical, and we will set up the example in exactly the same manner.
$ cd examplesDir/MLetClient/ $ javac -classpath classpath *.java $ jar cf Square.jar Square.class SquareMBean.class $ rm Square.class SquareMBean.class $ jar cf EquilateralTriangle.jar EquilateralTriangle.class \ EquilateralTriangleMBean.class $ rm EquilateralTriangle.class EquilateralTriangleMBean.class |
The manager is written to be run on the same host as the agent application. If you wish to run it on a different host, you will need to modify the code for the Client class constructor where the agent address is specified (see Example 6-12). You could place the jar files and the m-let file on a remote machine and specify its new URL as the parameter to the manager application; we run the example with this file in the current directory.
Before launching the manager, you must launch the agent. Here we give commands for launching the applications from the same terminal window running the Korn shell. On the Windows NT platform, you will have to launch each application in a separate window.
$ java -classpath classpath Agent & $ java -classpath classpath Client \ file:${PWD}/Square.jar file:${PWD}/GeometricShapes.html |
In the output of the manager, you can see it create the m-let service MBean, and then load all of the MBeans from different sources. If you connect to the agent in a web browser at the following URL: http://localhost:8082/ and reload its agent view every time the manager pauses, you can see the MBeans as they are created.
The agent terminates after it disconnects it connector client. When you are done viewing the agent, type the following commands to stop the agent application:
$ fg java [...] Agent <Control-C> ^C$ |