Java Dynamic Management Kit 3.2 Programming Guide | ||||
---|---|---|---|---|
![]() | ![]() | Chapter 10. Base Services - Customizing the Framework | ![]() | ![]() |
The repository service stores m-beans as normal Java objects. For each m-bean, the repository service stores and retrieves:
The components of the object name: domain, class and optional search key
The association between the m-bean and its object name
M-beans can be managed only if they are registered with an object name (see Object Name in Chapter 4) in the repository. Each time an m-bean is registered with the framework, the framework calls the repository service to store the object name of the m-bean. When querying the repository, agents and managers identify an m-bean by the various components of its object name.
You have to add the repository service to an agent before the agent is operational. An agent can be associated with only one repository service at a time. It is not possible to change the repository service with which an agent is associated while the agent is running.
A repository service implements the com.sun.jaw.reference.agent.services.MoRepSrvIf Java interface.
The Java Dynamic Management Kit provides the following types of repository implementations:
Volatile repository - all m-beans are stored in memory
Persistent repository - contains a mixture of m-beans stored in memory and in persistent storage
All m-bean information in memory is lost when an agent is stopped, whether intentionally or accidentally. Information in persistent storage will already be saved when the agent is stopped. When the agent is restarted, it has to reload the saved information into the repository. The reloaded information will reflect the state of m-beans prior to the interruption in the agent.
The Java Dynamic Management Kit provides an implementation of persistent storage based on a flat-file database.
If you need to store large volumes of data or you require absolute data integrity, you should implement a persistent repository using a database. The Java Dynamic Management Kit provides an example repository based on a relational database using the JDBC driver.
The volatile repository supplied with the Java Dynamic Management Kit is implemented by the com.sun.jaw.impl.agent.services.light.RepositorySrv class. This is also the default repository when instantiating the framework.
If you wish to specify this volatile repository explicitly, you must first create an instance of this class. Then pass a reference to this new object to the appropriate framework constructor.
Note - You must specify the volatile repository explicitly if you wish to specify a different thread allocator service because there is no constructor allowing a custom thread allocator and a default repository.
No configuration is necessary for the volatile repository supplied with the Java Dynamic Management Kit. Neither are there any special considerations needed to use the volatile repository, it can store any m-bean with a valid object name.
The persistent repository supplied with the Java Dynamic Management Kit stores all of an agent's persistent m-beans in a flat-file database. Each m-bean is stored as a serialized Java object. For each m-bean, the repository stores:
The object name of the m-bean
The serialized m-bean
The object name of the class loader that loaded the m-bean when it was instantiated
The repository stores the object name of the class loader to enable it to locate the class loader when an agent deserializes the m-bean. The repository needs to locate this class loader to obtain the Java byte codes of the m-bean class, which are required for deserializing the m-bean. An agent deserializes an m-bean when it needs to load it from persistent storage into memory (for example, when an agent is restarted after it has been stopped).
To add a persistent repository to an agent, you must customize the framework when creating it:
Create an instance of the com.sun.jaw.impl.agent.services.persistent.PersistentRepSrv class
Pass the reference to this new object to the appropriate framework constructor
Before trying to register any m-beans with a persistent repository, use the setConfig method to configure the repository and start the database. The configuration parameters are as follows and must be specified in the order given:
The base directory of the database. By default it is the current working directory of the agent.
The name of the database. The repository creates a directory with this name in the base directory. The file that contains the database is written to the directory created. The default name of the database is default.db. The suffix .db is appended to the name if you do not specify it explicitly.
When you invoke the setConfig method, you have to specify each configuration parameter as an element in a vector. Example 10-1 shows code for configuring a flat-file repository. In this example, the base directory is the working directory of the agent. The name of the database is persist.db.
Example 10-1. Configuring a Persistent Repository
//Create vector that contains the configuration parameters Vector params = new Vector(); params.addElement(null); // The same directory as agent params.addElement("persist"); // Call the database "persist.db" //Invoke setConfig with this vector to configure the repository ffpersrep.setConfig (params); |
Any m-bean that you want to be persistent must be serializable. When you write an m-bean that you want to be serializable it can implement either the java.io.Serializable or java.io.Externalizable interface.
For classes that implement java.io.Serializable, you do not have to write any methods to make sure that the object is stored properly. Java provides a default mechanism to automatically write the contents of an object to a stream and to automatically read them back from a stream.
The class of a serializable object must:
Implement the java.io.Serializable interface
Use the transient keyword to denote non-serializable fields
Be able to access the no-argument constructor of its first nonserializable superclass
For each instance of a class that implements the java.io.Serializable interface, Java writes:
The class and superclass metadata, that is, the class name of the class and its superclasses
The serialVersionUID
Field metadata and contents, that is, the name and type of each field in the class and superclasses as well as the values of the fields
The classes of a serializable object can also implement the writeObject() method or the readObject() method for customization (overriding the default mechanism).
The writeObject() method is used to control the information that is saved for the class (not the superclasses), or to append additional information
The readObject() method is used so that the class can read the information written by the writeObject() method or to update the state of the object after it has been restored
The default read and write of superclass metadata and their field metadata is still carried out automatically.
The java.io.Externalizable interface extends java.io.Serializable. Using the java.io.Externalizable interface requires more work to implement and all the benefits of the default mechanism are lost. Externalization allows a class to specify the methods to be used to write the object's contents to a stream and to read them back from a stream. The java.io.Externalizable interface's writeExternal and readExternal methods are implemented by a class to give complete control over the format and contents of the stream for an object and its superclasses. These methods must explicitly coordinate with the superclasses to save its state. When an externalizable object is reconstructed, an instance is created using the public no-argument constructor and the readExternal() method is called. Serializable objects are restored by reading them from an ObjectInputStream.
The class of an externalizable object must:
Implement the java.io.Externalizable interface.
Implement the writeExternal() method to save the state of the object to the stream. It must explicitly coordinate with its superclasses to save their states.
Implement the readExternal() method to read the data written by the writeExternal() method from the stream and restore the state of the object. It must explicitly coordinate with its superclasses to restore their states.
Have a no-argument constructor.
For each instance of a class that implements the java.io.Externalizable interface, Java writes:
The class metadata, that is, the class name of the class (the class name of the superclasses is not written)
The serialVersionUID
Data (whatever the writeExternal() method writes)
Superclass metadata or their field metadata are not written automatically.
When using java.io.Serializable, you can design your classes for more compact storage by storing only the fields needed to reconstruct a class.
Transient fields assume the default value for their specific type after deserialization. Transient variables are instantiated, but their static initializations are never applied during deserialization.
For example.
transient int count = 10; |
After deserialization, count assumes the value zero, which is the default value for type int.
transient String protocol = "http"; |
After deserialization, protocol assumes the value null, which is the default value for type object.
Use the readObject() method to restore the state of transient fields, to be initialized to a non-default value, after the object has been restored.
Note - Do not apply the transient modifier to fields that reference the framework. Although the framework is not serializable, the repository ensures that all m-beans that reference the framework will stay synchronized.
An agent deserializes an m-bean when it needs to load it from persistent storage into memory (for example, when an agent is restarted). When an m-bean is deserialized, the Java byte codes of its class are required. To enable an agent to obtain the Java byte codes of the class from the correct source, the repository service must be able to locate the class loader that loaded the m-bean when it was instantiated.
To enable the repository service to locate a class loader, make sure that the class loader provides the getter method getLoaderName() to retrieve its object name. If you want the class loader to be persistent, make sure that it implements the java.io.Externalizable interface. If the class loader is not persistent, make sure it is present when the m-bean is deserialized.
If the repository service cannot locate the class loader that loaded the m-bean when it was instantiated, the agent uses the default class loader.
You specify whether an m-bean in the persistent repository is stored in memory or in persistent storage by choosing the method of the framework invoked to register the m-bean:
To store an m-bean in: | Invoke: |
---|---|
Memory |
|
Persistent storage |
|
For more information on how to use these methods, refer to Chapter 4.
The repository service must implement the com.sun.jaw.reference.agent.services.MoRepSrvIf Java interface. When you implement a repository, you must specify whether it uses volatile or persistent storage.
![]() | ![]() | ![]() |
Initializing the Framework | ![]() | Activation Interface |