Java Dynamic Management Kit 3.2 Programming Guide | ||||
---|---|---|---|---|
![]() | ![]() | Chapter 14. M-Let, Bootstrap and Launcher Services | ![]() | ![]() |
The management applet or m-let service enables an agent to obtain m-beans from a remote .jar file. The agent does this by loading an m-let text file, which specifies information on the m-beans to be obtained. The information on each m-bean is specified in a single instance of a tag, called the MLET tag. The location of the m-let text file is specified by a URL. When an m-let text file is loaded, an instance of each m-bean specified in the file is created. The operation of the m-let service is illustrated in Figure 14-1.
Using the m-let services involves:
Writing an m-let text file containing MLET tags that specify the m-beans you want the agent to obtain
Creating .jar files that contain the code of the m-beans and any other resources that the m-beans require (for example, other Java classes, or native libraries)
If security is required:
Creating a signer with public and private keys and certificates using keytool
Signing the .jar file using the jarsigner tool
Creating a policy file using the policytool
Creating an instance of the m-let service in the agent
Loading the m-let text file
The MLET tag specifies an m-bean to be obtained. The syntax of the MLET tag is similar to the syntax of the APPLET HTML tag.
<MLET CODE=class | OBJECT=serfile ARCHIVE="archivelist" [CODEBASE=codebaseURL] [NAME=mbeanname] [PERSISTENT=true|false] [VERSION=version] > [paramlist] </MLET> |
CODE=class
This attribute specifies the full Java class name, including package name, of the m-bean to be obtained. The compiled .class file of the m-bean must be contained in one of the .jar files specified by the ARCHIVE attribute. Either CODE or OBJECT must be present.
OBJECT=serfile
This attribute specifies the.ser file that contains a serialized representation of the m-bean to be obtained. This file must be contained in one of the .jar files specified by the ARCHIVE attribute. If the .jar file contains a directory hierarchy, specify the path of the file within this hierarchy. Otherwise a match will not be found. Either CODE or OBJECT must be present.
ARCHIVE="archivelist"
This mandatory attribute specifies one or more .jar files containing m-beans or other resources used by the m-bean to be obtained. One of the .jar files must contain the file specified by the CODE or OBJECT attribute. If archivelist contains more than one file:
Each file must be separated from the one that follows it by a comma (,).
archivelist must be enclosed in double quote marks ("").
All .jar files in archivelist must be stored in the directory specified by the code base URL.
CODEBASE=codebaseURL
This optional attribute specifies the code base URL of the m-bean to be obtained. It identifies the directory that contains the .jar files specified by the ARCHIVE attribute. Specify this attribute only if the .jar files are not in the same directory as the m-let text file. If this attribute is not specified, the base URL of the m-let text file is used.
Note - Multiple MLET tags with the same code base URL share the same instance of the MLetClassLoader class.
NAME=mbeanname
This optional attribute specifies the object name to be assigned to the m-bean instance when the m-let service registers it. If mbeanname starts with the colon character (:), the domain part of the object name is the domain of the agent. The m-let service invokes the getDomain() method of the Framework class to obtain this information.
PERSISTENT=true | false
This optional attribute specifies whether the m-bean instance will be persistent. If the attribute is true, the m-bean will be persistent. If the attribute is false the m-bean will not be persistent. If this attribute is omitted, the m-bean will not be persistent.
VERSION=version
This optional attribute specifies the version number of the m-bean and associated .jar files to be obtained. This version number can be used to specify that the .jar files are loaded from the server to update those stored locally in the cache the next time the m-let text file is loaded. The version parameter must be one or more non-negative decimal integers each separated by a dot from the one that precedes it. For information on how to use version control with the m-let service, see Version Control Mechanism.
paramlist
This optional attribute specifies a list of one or more parameters for the m-bean to be instantiated. This list is passed as a modification list to the initCmf() method of the m-bean to be instantiated. Each parameter in paramlist corresponds to a modification in the modification list. Use the following syntax to specify each item in paramlist:
<PARAM NAME=propertyName VALUE=value> |
where:
propertyName is the name of the property in the modification
value is the value in the modification
The m-let service passes all the values in the modification list as String objects. Make sure that the initCmf() method of the m-bean includes the code required to cast each String object into an instance of the appropriate type. For example, if the property is an integer, you have to cast the String object passed by the m-let service into an int.
Example 14-1 shows an example of an MLET tag in an m-let text file. In this example, the m-bean Example.class is present in the file example1.jar. The file example2.jar contains other resources required by the m-bean Example.class. The .jar files are stored in the directory specified by the URL http://www.foo.com/jars. The domain part of the object name to be assigned to the m-bean instance is the domain of the agent. The m-let service invokes the getDomain() method of the Framework class to obtain this information. The text example.instance=1 makes up the remainder of the object name. Version 1.0 of the m-bean Example.class is to be obtained.
Example 14-1. Example MLET Tag
<MLET CODE=Example.class ARCHIVE="example1.jar, example2.jar" CODEBASE=http://www.foo.com/jars NAME=:example.instance=1 PERSISTENT=true VERSION=1.0 > </MLET> |
The m-let service derives security from tools provided as part of the JavaŽ 2 SDK, Standard Edition, version 1.2. Dynamically loaded code runs in a specific protection domain that is defined by a given codebase and signer or set of signers. Protection domains each have a set of permissions that are defined in a policy file. Use the policytool to write the policy file and the jarsigner tool to sign your .jar files. The policytool and jarsigner tools are supplied with the JavaŽ 2 SDK. For further information on policytool and policy files, see the JavaŽ 2 SDK product documentation.
When the policy file has been created, run the m-let service with the default security manager specifying the location of the policy file.
Before using the m-let service, you must add it to an agent. To add the m-let service, create an instance of one of these classes:
com.sun.jaw.impl.agent.services.mlet.MLetSrv if you do not want to apply version control
com.sun.jaw.impl.agent.services.mlet.MLetCacheVersionSrv if you want to apply version control (see Version Control Mechanism for more information)
Only one instance of the m-let service is allowed in a Java Dynamic Management agent. If there is already an instance of one of the above classes in an agent, it is not permitted to create an instance of the other class in the same agent.
Example 14-2 shows how to add the m-let service without version control to an agent. For an example of how to add the m-let service with version control, refer to Applying Version Control.
Example 14-2. Adding the M-Let Service (no Version Control)
// Add the simple m-let service // String mletName = "com.sun.jaw.impl.agent.services.mlet.MLetSrv"; MLetSrv mletSrv = (MLetSrv) cmf.newObject( mletName, domain + ":" + "com.sun.jaw.impl.agent.services.mlet.MLetSrvMO", null ); |
To load an m-let text file, an agent or manager application must invoke a load URL method of an instance of the m-let service. When the m-let text file is loaded, an instance of the m-bean specified in each MLET tag is created. By repeatedly invoking the load URL method, it is possible to populate a Java Dynamic Management agent while it is running. The m-let service provides methods for loading an m-let text file with or without error checking.
The m-let service provides different methods for loading a URL, depending on whether the method is to be invoked by an agent or a manager. Each of these methods has a different return value. To load an m-let text file with error checking, invoke one of these methods, depending on the type of application you are writing:
Application | Method | Returns |
---|---|---|
Agent | performLocalLoadURL() | A vector of object references to the m-beans instantiated. |
Manager | performRemoteLoadURL() | A vector of m-let tags that define the m-beans instantiated. |
By parsing the vector returned, it is possible to perform error checking when an m-let text file is loaded.
Example 14-3 shows code required to enable an agent to load an m-let text file.
Example 14-3. Loading an M-Let Text File
Vector beans = mlet.performLocalLoadURL( "http://www.foo.com/jars/test.htm" ); |
When the performLocalLoadURL() method is invoked by an agent, it returns a vector containing one entry per MLET tag in the m-let text file loaded. Each entry specifies either the reference of the m-bean instantiated, or a throwable object (that is, an error or an exception) if the m-bean cannot be instantiated. Parsing the vector returned by the performLocalLoadURL() method enables you to:
Verify whether each m-bean was instantiated as requested
Obtain object references required for registering m-beans
An example of parsing the vector returned by a load URL method invoked by an agent is shown in Example 14-4.
Example 14-4. Parsing the Vector Returned in an Agent
// Invoke load URL method of the m-let service (agent side) // try { System.out.println("Invoking load URL method on an agent..."); Vector beans = mlet.performLocalLoadURL("file:/home/mletdir/test.txt"); if (beans.isEmpty()) { System.out.println("Vector beans is empty"); } else { System.out.println("---> Start walking through Vector beans"); int id = 0; Object instance; ObjectName mybeanName; for (Enumeration e = beans.elements(); e.hasMoreElements(); ) { id = id + 1; instance = e.nextElement(); if (instance instanceof Throwable) { System.out.println("Error or exception, problem while creating m-bean --->"); System.out.println("The throwable object is: " + instance); } else { System.out.println("M-bean creation succeeded --->"); System.out.println("The object reference of the m-bean is: " + instance); // If the instance is not registered, do it now. mybeanName = new ObjectName(cmf.getDomain() + ":mybean.id=" + id); cmf.addObject(instance, mybeanName); } } System.out.println("---> Stop walking through Vector beans"); } } catch (ServiceNotFoundException e) { System.err.println("Got an exception !"); e.printStackTrace(); } |
When the performRemoteLoadURL() method is invoked by a manager, it returns a vector containing one entry per MLET tag in the m-let text file loaded. Each entry specifies either an m-let tag that defines the m-bean instantiated, or a throwable object (that is, an error or an exception) if the m-bean could not be instantiated. Parsing the vector returned by the performLocalLoadURL() method enables you to verify whether each m-bean was instantiated as requested.
An example of parsing the vector returned by a load URL method invoked by a manager is shown in Example 14-5.
Example 14-5. Parsing the Vector Returned in a Manager
// Invoke load URL method of the m-let service (manager side) // try { System.out.println("Invoking load URL method on a manager ..."); Vector beans = mletmo.performRemoteLoadURL("file:/home/mletdir/test.txt"); if (beans.isEmpty()) { System.out.println("Vector beans is empty"); } else { System.out.println("---> Start walking through Vector beans"); Object instance; for (Enumeration e = beans.elements(); e.hasMoreElements(); ) { instance = e.nextElement(); if (instance instanceof Throwable) { System.out.println("Error or exception, problem while creating m-bean --->"); System.out.println("The throwable object is: " + instance); } else { System.out.println("M-bean creation succeeded --->"); System.out.println("The MLET tag representation of this m-bean is: " + ((MLet)instance).toString()); } } System.out.println("---> Stop walking through Vector beans"); } } catch (ServiceNotFoundException e) { System.err.println("Got an exception !"); e.printStackTrace(); } |
To load an m-let text file without performing any error checking, invoke the performLoadURL() method of the m-let service. This method does not return, so no error checking is possible. It is allowed in the code of an agent or a manager. Therefore, use this method if you want to write code that can be used both for an agent and a manager. An example showing code for loading an m-let text file without performing any error checking is shown in Example 14-6.
Example 14-6. Loading an M-Let Text File Without Performing Any Error Checking
// Invoke load URL method (no error checking) // try { System.out.println("Invoking load URL method..."); mlet.performLoadURL("file:/home/mletdir/test.txt"); } catch (ServiceNotFoundException e) { System.err.println("Got an exception !"); e.printStackTrace(); } |
A load URL method throws an exception if any of the following are true:
The m-let text file does not contain an MLET tag.
The m-let text file is not found.
A mandatory attribute of the MLET tag is not specified.
The URL specified is null.
Before instantiating an m-bean specified in an MLET tag, the m-let service creates and registers a class loader. It does this to make sure that a class loader is available that will obtain classes from the correct location. The class loader is required to load the m-bean class and the Java classes in any .jar files specified in the MLET tag. The object name of the class loader is required by any manager that needs to load classes by using this class loader (for example, a manager that invokes the cb_newMO() method and specifies this class loader). The m-let service registers the class loader it creates with an object name of the form:
defaultDomain:JavaClass.codebase=baseURL |
where:
defaultDomain is the domain associated with the framework.
JavaClass is the full Java class name, including the package prefix, of the class loader used to create the m-bean. This is defined as the Java variable ServiceName.MLETLOADER.
baseURL specifies the location of the code of the m-bean. It is either the base URL of the m-let text file specified in the call to one of the load URL methods of the m-let service, or is the value of the CODEBASE attribute specified in the MLET tag.
When an m-bean specified in an MLET tag is instantiated, you can register it with the repository yourself or you can let the m-let service register the m-bean. The Java Dynamic Management Kit allows you to specify the object name of the m-bean in either of the following ways:
Using the NAME attribute of the MLET tag
Omitting the NAME attribute of the MLET tag
Use the NAME attribute of the MLET tag if an initCmf() method is defined for the m-bean and you want the NAME attribute to be passed as the object name parameter. You can also use the NAME attribute of the MLET tag for an m-bean that does not have an initCmf() method if you want the m-bean instance to be registered with the repository by the m-let service.
You can omit the NAME attribute of the MLET tag if an object name is specified in the initCmf() method. If an object name is specified in the initCmf() method, the m-bean will register with the repository using that object name. You can also omit the NAME attribute of the MLET tag for an m-bean that does not have an initCmf() method if you do not want the m-bean instance to register with the repository.
If you use the NAME attribute of the MLET tag to specify the object name of the m-bean instance, the instance is registered with this name. The method invoked to register the instance depends on how the m-bean is implemented:
If an initCmf() method is defined for the m-bean, it is invoked to register the instance.
If an initCmf() method is not defined for the m-bean, the addObject() or addDBObject() method of the Framework class is invoked to register the instance. The persistency of the m-bean is determined by the PERSISTENT attribute in the MLET tag.
If you omit the NAME attribute of the MLET tag, the method invoked to register the instance and the supplier of the object name depends on the implementation of the m-bean:
If an initCmf() method is defined for the m-bean, it is invoked to register the instance. The object name must be supplied by the initCmf() method.
If an initCmf() method is not defined for the m-bean, the instance will only be registered with the repository if the performLocalLoadURL() method is invoked by the agent. After the performLocalLoadURL() method is invoked, the agent must then invoke the addObject() or addDBObject() method of the Framework class to register the instance.
The m-let service enables you to use the initCmf() method of an m-bean that it loads to instantiate other m-beans. To do this, add code to the initCmf() method for:
Adding a named m-bean to the framework
Instantiating and registering an instance of the m-bean
Obtaining the object name of the m-let service class loader
This is shown in Example 14-7.
Example 14-7. Instantiating an M-Bean From Another M-Bean
public void initCmf(Framework cmf, ObjectName name) throws IllegalAccessException, ServiceNotFoundException, InstanceAlreadyExistException { // Add this m-bean under the control of the framework. // cmf.addObject(this, name); // Instantiate and register an instance of the m-bean MyBean. // NOTE: // By adding the m-bean in this way to the framework, // the initCmf method IS NOT called. // ObjectName mbNameA = new ObjectName(cmf.getDomain()+":MyBean.id=A"); MyBean mbA = new MyBean(); cmf.addObject(mbA, mbNameA); // Retrieve the codebase of the MLetClassLoader that loaded this class, // and compose the MLetClassLoader object name. String codebase = ((MLetClassLoader)this.getClass().getClassLoader()) .getCodeBase().toString(); ObjectName mletloader = new ObjectName(cmf.getDomain()+":"+ServiceName.MLETLOADER+" .codebase="+codebase); // Instantiate and register a new m-bean in the agent. ObjectName mbNameB = new ObjectName(cmf.getDomain()+":MyBean.id=B"); MyBean mbB = (MyBean) cmf.newObject("MyBean", mbNameB, mletloader, null); } |
If you want an m-bean which has been instantiated using the m-let service to start automatically as soon as it is instantiated, make sure that the m-bean implements the java.lang.Runnable interface. When the m-let service instantiates the m-bean, it creates a new thread and invokes the run() method of the m-bean.
Applying version control to an m-bean enables the m-let service to reduce network traffic by not loading .jar files from a server unless it is necessary. When you apply version control, .jar files are stored locally in the cache. Unless the m-let text file specifies that new versions must be loaded from the server, .jar files are loaded from the cache. For more information, see Cache Directories. If you do not apply version control to an m-bean, the .jar files are always loaded from the server when an m-let text file is loaded.
Applying version control to an m-bean loaded by the m-let service involves:
Specifying the VERSION attribute of the MLET tag
Creating an instance of the com.sun.jaw.impl.agent.services.mlet.MLetCacheVersionSrv class
Invoking a load URL method of the instance to load the m-let text file
The directory in which cache files are stored by default depends on the environment:
Operating Environment | Default Cache Directory |
---|---|
Solaris | installDir/SUNWconn/jaw/var/mletcache |
Windows NT | installDir\SUNWconn\jaw\var\mletcache |
To change the default cache directory, invoke the setCacheDirectory() method of the m-let service instance. The setCacheDirectory() method does not create the directory that you specify, the directory must already exist. Example 14-8 shows how to add the m-let service with version control and change the cache directory.
Example 14-8. M-Let Service with Version Control
// Add the MLetCacheVersionSrv // String mletName = "com.sun.jaw.impl.agent.services.mlet.MLetCacheVersionSrv"; MLetCacheVersionSrv mletSrv = (MLetCacheVersionSrv) cmf.newObject(mletName, domain + ":" + "com.sun.jaw.impl.agent.services.mlet.MLetCacheVersionSrvMO", null); // Set the directory for caching if you want. mletSrv.setCacheDirectory("/home/foo"); |
When the m-let text file is loaded, the m-let service compares the version number specified in the MLET tag with the current version number of the m-bean, which is stored locally. If the version number specified in the MLET tag is greater than the current version number, the .jar files are loaded from the server to replace those stored locally in the cache. The current version number is updated to the value specified in the MLET tag. If the version number specified in the MLET tag is less than or equal to the current version number, the .jar files in the cache are used.
To implement your own version control mechanism, create a Java class that extends the com.sun.jaw.impl.agent.services.mlet.MLetCacheVersionSrv class. In your Java class, override the check() method of the com.sun.jaw.impl.agent.services.mlet.MLetCacheVersionSrv class.
![]() | ![]() | ![]() |
M-Let, Bootstrap and Launcher Services | ![]() | Bootstrap Service |