Contained WithinFind More DocumentationFeatured Support Resources | Download this book in PDF (1891 KB)
Part II Agent ApplicationsThe agent is the central component of the Java Management Extensions (JMX) management architecture. An agent contains MBeans and hides their implementation behind a standardized management interface, lets management applications connect and interact with all MBeans, and provides filtering for handling large numbers of MBeans. JMX agents are dynamic because resources can be added and removed, connections can be closed and reopened with a different protocol, and services can be added and removed as management needs evolve. In Part I, we saw how to represent resources as MBeans. However, MBeans can represent any object whose functionality you need to manage. In particular, management services and remote connectivity are handled by objects that are also MBeans. This creates a homogeneous model where an agent is a framework containing different kinds of MBeans and enabling them to interact. The main component of an agent is the MBean server. It registers all MBeans in the agent and exposes them for management. The role of the MBean server is to be the liaison between any object available to be managed and any object with a management request. Usually resource MBeans are managed either by remote applications through connectivity MBeans or by local management service MBeans. This model allows a management service itself to be managed. Connectors and services can also be created, modified, or removed dynamically. This part focuses on the functionality of the MBean server and the Java objects which are needed to create a simple agent. Details about programming managers and about using connectors and services will be covered in Part III. This part contains the following chapters:
Chapter 5 Base AgentAn agent application is a program written in the Java language that contains an MBean server and a means of accessing its functionality. The base agent demonstrates the programming details of writing an agent application. We will cover the MBean server classes, how to reference MBeans, how to access the MBean server, use it to create MBeans, and then interact with those MBeans. Interacting programmatically with the MBean server gives you more flexibility in your agent application. This chapter presents the MBean server and covers the three main ways to use it to create MBeans, how to interact with these MBeans, and how to unregister them. The program listings in this tutorial show only functional code: comments and output statements have been modified or removed to conserve space. However, all management functionality has been retained for the various demonstrations. The complete source code is available in the BaseAgent and StandardMBean example directories located in examplesDir/current (see Directories and Classpath in the Preface). This chapter covers the following topics:
5.1 MBean Server ClassesBefore writing an agent application, it is important to understand the functionality of the MBean server. It is actually an interface and a factory object defined by the agent specification level of the JMX specification. The Java DMK provides an implementation of this interface and factory. The factory object finds or creates the MBean server instance, making it possible to substitute different implementations of the MBean server. 5.1.1 MBeanServer InterfaceThe MBeanServer interface is an extension of the MBeanServerConnection interface, and represents the agent-side interface for interacting with MBeans. The specification of the interface defines all operations that can be applied to resources and other agent objects through the MBean server. Its methods can be divided into three main groups:
5.1.2 MBean Server Implementation, Builder and FactoryThe MBeanServer implementation class in Java DMK implements the JdmkMBeanServer and MBServerInt interfaces if the property javax.management.builder.initial has been set to use com.sun.jdmk.JdmkMBeanServerBuilder. This implementation of MBeanServer wraps the JMX MBean server. The older MBeanServerInt interface and the MBeanServerImpl class are still implemented for reasons of backwards compatibility, but in Java DMK 5.1, JdmkMBeanServer is the prefered interface. The MBeanServerFactory makes the agent application independent of the MBean server implementation, and thus allows applications to provide custom MBeanServer implementations. It resides in the Java virtual machine and centralizes all MBean server instantiation. The MBeanServerFactory class provides two static methods:
You must use the MBeanServerFactory classes to create an MBean server so that other objects can obtain its reference by calling the findMBeanServer method. This method enables dynamically loaded objects to find the MBean server in an agent that has already been started. 5.2 Referencing MBeansMost agent applications interact with MBeans through the MBean server. It is possible for an object to instantiate an MBean class itself, which it can then register in the MBean server. In this case, it keeps a programmatic reference to the MBean instance. All other objects can only interact with the MBean through its management interface exposed by the MBean server. In particular, service MBeans and connectivity MBeans rely solely on the MBean server to access resources. The MBean server centralizes the access to all MBeans. It unburdens all other objects from having to keep numerous object references. To ensure this function, the MBean server relies on object names to identify MBean instances uniquely. 5.2.1 Object NamesEach MBean object registered in the MBean server is identified by an object name. The same MBean class can have multiple instances, but each must have a unique name. The ObjectName class encapsulates an object name composed of a domain name and a set of key properties. The object name can be represented as a string in the following format:
The DomainName, the property and value can be any alphanumeric string, as long as it does not contain any of the following characters: : , = * ?. All elements of the object name are treated as literal strings, meaning that they are case sensitive. 5.2.1.1 MBean DomainsA domain is an abstract category that can be used to group MBeans arbitrarily. The MBean server lets you search easily for all MBeans with the same domain. For example, all connectivity MBeans in the minimal server could have been registered into a domain called Communications. Since all object names must have a domain, the MBeans in an MBean server necessarily define at least one domain. When the domain name is not important, the MBean server provides a default domain name that you can use. By default, it is called the DefaultDomain, but you can specify a different default domain name when creating the MBean server from its factory. 5.2.1.2 Key PropertiesA key is a property-value pair that can also have any meaning that you assign to it. An object name must have at least one key. Keys and their values are independent of the MBean's attributes. The object name is a static identifier that identifies the MBean, whereas attributes are the exposed, runtime values of the corresponding resource. Keys are not positional and can be given in any order to identify an MBean. Keys provide the specificity for identifying a unique MBean instance. For example, an object name for the HTML protocol adaptor MBean might be: Communications:protocol=html,port=8082, assuming the port will not change. 5.2.1.3 Usage of Object NamesAll MBeans must be given an object name that is unique. It can be assigned by the MBean's preregistration method, if the MBean supports preregistration (see the Javadoc API of the MBeanRegistration interface). Or it can be assigned by the object that creates or registers the MBean, which overrides the one given during preregistration. However, if neither of these assign an object name, the MBean server will not create the MBean and will raise an exception. Once an MBean is instantiated and registered, its assigned object name cannot be modified. You can encode any meaning into the domain and key strings. The MBean server handles them as literal strings. The contents of the object name should be determined by your management needs. Keys can be meaningless serial numbers if MBeans are always handled programmatically. On the other hand, the keys can be human-readable to simplify their translation to the graphical user interface of a management application. With the HTML protocol adaptor, object names are displayed directly to the user. 5.2.2 ObjectInstance of an MBeanAn object instance represents the complete reference of an MBean in the MBean server. It contains the MBean's object name and its Java class name. Object instances are returned by the MBean server when an MBean is created or in response to queries about MBeans. Since the object name and class name cannot change over the life of a given MBean, its returned object instance will always have the same value. You cannot modify the class or object name in an object instance. This information is read-only. The object name is used to refer to the MBean instance in any management operation through the MBean server. The class name can be used to instantiate similar MBeans or introspect characteristics of the class. 5.3 Agent ApplicationThe base agent is a standalone application with a main method, but it also has a constructor so that it can be instantiated dynamically by another class. Example 5–1 Constructor for the Base Agent
The MBean server is created through the static MBeanServerFactory object, and we store its object reference. Its true type is hidden by the factory object, that casts the returned object as an MBeanServer interface. The MBean server is the only functional class referenced directly in this application. After the MBean server is initialized, we will create three communication MBeans. 5.4 Creating an MBean Using the registerMBean MethodThe methods of the MBean server enable you to create an MBean in three different ways. The base agent demonstrates all three ways, and we will discuss the advantages of each. One way of creating an MBean consists of first instantiating its class and then registering this instance in the MBean server. Registration is the internal process of the MBean server that takes a manageable resource's MBean instance and exposes it for management. Bold text in Example 5–2 and the following code samples highlights the important statements that vary between the three methods. Example 5–2 Creating an MBean Using the registerMBean Method
In this first case, we instantiate the HtmlAdaptorServer class and keep a reference to this object. We then pass it to the registerMBean method of the MBean server to make our instance manageable in the agent. During the registration, the instance can also obtain a reference to the MBean server, something it requires to function as a protocol adaptor. The HTML adaptor gives itself a default name in the default domain. Its Javadoc API confirms this, so we can safely let it provide a default name. We print the object name in the object instance returned by the registration to confirm that the default was used. Once the MBean is registered, we can perform management operations on it. Because we kept a reference to the instance, we do not need to go through the MBean server to manage this MBean. This enables us to call the start and getStateString methods directly. The fact that these methods are publicly exposed is particular to the implementation. The HTML adaptor is a dynamic MBean, so without any prior knowledge of the class, we would have to go through its DynamicMBean interface. In a standard MBean you would call the implementation of its management interface directly. Because the HTML adaptor is a dynamic MBean, the start method is just a shortcut for the start operation. For example, we could start the adaptor and get its StateString attribute with the following calls: htmlAdaptor.invoke("start", new Object[0], new String[0]);
echo("STATE = " + (String)htmlAdaptor.getAttribute("StateString"));
This type of shortcut is not specified by the Java Management Extensions (JMX) specification, nor is its functionality necessarily identical to that of the start operation exposed for management. In the case of the HTML adaptor, its Javadoc API confirms that it is identical, and in other cases, it is up to the MBean programmer to guarantee this functionality if it is offered. 5.5 Creating an MBean Using the createMBean MethodA second way to create an MBean is the single createMBean method of the MBean server. In this case, the MBean server instantiates the class and registers it all at once. As a result, the caller never has a direct reference to the new object. This is not demonstrated in the BaseAgent example, but the advantage of this method for creating MBeans is that the instantiation and registration are done in one call. In addition, if we have registered any class loaders in the MBean server, they will automatically be used if the class is not available locally. See Chapter 12, M-Let Class Loader for more information on class loading. The major difference is that we no longer have a reference to our MBean instance. The object instance that was only used for display purposes in the previous example now gives us the only reference we have on the MBean: its object name. One disadvantage of this method is that all management of the new MBean must now be done through the MBean server. For the attributes of the MBean, we need to call the generic getter and setter of the MBean server, and for the operations we need to call the invoke method. When the agent needs to access the MBean, having to go through the MBean server adds some complexity to the code. However, it does not rely on any shortcuts provided by the MBean, making the code more portable and reusable. The createMBean method is ideal for quickly starting new MBeans that the agent application does not need to manipulate. In just one call, the new objects are instantiated and exposed for management. 5.6 Creating an MBean Using the instantiate MethodThe last way of creating an MBean relies on the instantiate method of the MBean server. In addition, we can use a nondefault constructor to instantiate the class with a different behavior. This method is not demonstrated in the BaseAgent example, but as in Example 5–2, we instantiate and register the MBean in separate steps. First, you instantiate the class using the instantiate method of the MBean server. This method lets you specify the constructor you want use when instantiating. Note that we could also have specified a constructor to the createMBean method in the previous example. To specify a constructor, you must give an array of objects for the parameters and an array of strings that defines the signature. If these arrays are empty or null, the MBean server will try to use the default no-parameter constructor. If the class does not have a public no-parameter constructor, you must specify the parameters and signature of a valid public constructor. One advantage of this creation method is that the instantiate method of the MBean server also supports class loaders. If any are registered in the MBean server, they will automatically be used if the class is not available locally. See Chapter 12, M-Let Class Loader for more information on class loading. The main advantage of this method is that, like the first method of MBean creation, we retain a direct reference to the new object. The direct reference again enables us to use the MBean's shortcut methods explicitly. 5.7 Managing MBeansIn 5.5 Creating an MBean Using the createMBean Method, you rely totally on the MBean server to create and access an MBean. You get attributes and invoke operations through the MBean server. Here we will concentrate on the usage of MBean metadata classes when accessing MBeans that represent resources. We will rely on the StandardAgent and DynamicAgent classes presented in Part I. As mentioned in 2.3.1 Comparison With the SimpleStandard Example, the two are nearly identical. The same code works for any registered MBean, whether standard or dynamic. We examine the method for displaying MBean metadata that is common to both. Example 5–3 Processing MBean Information
The getMBeanInfo method of the MBean server gets the metadata of an MBean's management interface and hides the MBean's implementation. This method returns an MBeanInfo object that contains the MBean's description. We can then get the lists of attributes, operations, constructors, and notifications to display their descriptions. Recall that the dynamic MBean provides its own meaningful descriptions and that the standard MBean descriptions are default strings provided by the introspection mechanism of the MBean server. 5.8 Filtering MBeans With the Base AgentThe base agent does very little filtering because it does very little management. Usually, filters are applied programmatically to get a list of MBeans to which some operations apply. There are no management operations in the MBean server that apply to a list of MBeans. You must loop through your list and apply the desired operation to each MBean. Before exiting the agent application, we do a query of all MBeans so that we can unregister them properly. MBeans should be unregistered before being destroyed because they might need to perform some actions before or after being unregistered. See the Javadoc API of the MBeanRegistration interface for more information. Example 5–4 Unregistering MBeans
We use the queryNames method because we only need the object names to operate on MBeans. The null object name as a filter gives us all MBeans in the MBean server. We then iterate through the resulting set and unregister each one, except for the MBean server delegate. As we shall see in 6.1.2 MBean Server Delegate, the delegate is also an MBean and so it will be returned by the query. However, if we unregister it, the MBean server can no longer function and cannot remove the rest of our MBeans. We recognized the delegate by its standard name which is given by the static field ServiceName.DELEGATE. The ServiceName class provides standard names and other default properties for communications and service MBeans. It also provides the version strings that are exposed by the delegate MBean. Note that, because the delegate is the only MBean created directly by the MBean server, it is the only one whose name cannot be overridden during its registration. The delegate object name is always the same, so we are always sure to detect it. 5.9 Running the Base Agent ExampleThe examplesDir/current/BaseAgent/ directory contains the source file of the BaseAgent application. To Run the Base Agent Example
5.9.1 Agent OutputThis agent displays output for the MBean created. When the connection MBeans have been created, it is possible to connect to the agent through the HTML adaptor. When you have finished, press Enter to remove all MBeans from the agent and exit the agent application. Chapter 6 HTML Protocol AdaptorThe HTML protocol adaptor provides a view of the agent and its registered MBeans through a basic interface on any web browser. It is the easiest way to access an agent since no further coding is necessary. For this reason, it can be useful for testing and debugging your MBeans. In this chapter, we will use your browser to “manage” the base agent and its MBeans. The HTML protocol adaptor outputs HTML pages that represent the agent and its MBeans. The adaptor also interprets the commands sent back by the buttons and fields appearing in your browser. It then interacts with the agent's MBean server to get information about the MBeans that it has registered and to operate on them. The HTML adaptor relies mostly on plain HTML. The only JavaScriptTM that the generated pages contain are pop-up windows for displaying information. Browsers that are not enabled for JavaScript might give an incompatibility message and will not be able to display the information. Otherwise, the generated pages contain no further scripting (JavaScript, Visual Basic or other), no frames and no images that might slow down loading. This chapter relies on the base agent that you will need to start first, as explained in Chapter 5, Base Agent. Once you can connect to the HTML protocol adaptor in the base agent, you are ready to begin these topics:
6.1 Agent ViewThe first page displayed by the HTML adaptor is always the agent view. It initially contains a list of all registered MBeans. The following figure shows the agent view for the base agent. It contains four MBeans: three communication MBeans, one of which is the HTML adaptor, and the MBean server delegate. The delegate is a special MBean explained in 6.1.2 MBean Server Delegate. Figure 6–1 Initial Agent View of the Agent
The text field for filtering by object name enables you to modify the list of displayed MBeans. The filter string is initially *:*, which displays all registered MBeans. 6.3.2 Filtering MBeans describes how to use the filter. The agent's registered domain indicates the name of the default domain in this agent. The number of MBeans on this page is the count of those listed beneath the separator line. The Admin button links to the agent administration page (see 6.3 Agent Administration). 6.1.1 MBean ListThe MBean list contains all MBeans whose object name matches the filter string. Object names can be filtered by their domain name and list of key-value pairs. In this list, MBeans are sorted and grouped by domain name. Each MBean name listed is an active link to the page of the corresponding MBean view. After its initialization, the contents of an agent are dynamic. New MBeans can be created and registered into new or existing domains and old MBeans can be removed. These changes can also affect the functionality of the agent. New agent services can be registered (or removed) as well. We will demonstrate examples of dynamic management in 6.3.1 Instantiating and Managing MBeans. 6.1.2 MBean Server DelegateThe MBean server delegate is an MBean that is automatically instantiated and registered by the MBean server when it is created. It provides information about the version of the Java Dynamic Management Kit (Java DMK) that is running, and it represents the MBean server when sending notifications. Notifications are events sent by MBeans. They are covered in detail in Chapter 8, Notification Mechanism. Because the MBean server instance is not an MBean object, it relies on its delegate MBean to send notifications. The MBean server delegate sends notifications to inform interested listeners about such events as MBean registrations and unregistrations. The exposed attributes of the delegate MBean provide vendor and version information about the MBean server. This can let a remote management application know which agent version is running and which version of the Java runtime environment it is using. The delegate MBean also provides a unique identification string for its MBean server. To View the MBean Server Delegate Information
6.2 MBean ViewThe MBean view has two functions: it presents the management interface of the MBean and it enables you to interact with its instance. The management interface of an MBean is given through the name of the attributes, the operation signatures, and a self-description. You can interact with the MBean by reloading its attribute values, setting new values, or invoking an operation. To Display the MBean View
6.2.1 Header and DescriptionAs shown in Figure 6–2, the top part of the page contains the description of the MBean and some controls for managing it. Figure 6–2 Description in the MBean View
The first two lines give the object instance (object name and class name) for this MBean. The MBean name is the full object name of this MBean instance, including the domain. The key-property pairs might or might not identify the MBean to a human reader, depending on the agent developer's intention. The MBean Java class is the full class name for the Java object of which this MBean is an instance. The reload controls include a text field for entering a reload period and a manual Reload button. Initially, the reload period is set to zero indicating that the contents of the MBean view are not automatically refreshed. Clicking the Reload button forces the page to reload, thereby updating all of the attribute values displayed. If you have entered a reload period, clicking the button will begin automatic reloading with the given period. The reload period must be at least five seconds. Note – Use the Reload button of the MBean view instead of the browser's reload page button. After some operations, such as applying changes to attribute values, the browser's button will repost the form data, inadvertently performing the same operation again. To avoid undesirable side effects, always use the Reload button provided in the MBean view. To Set the Reload Period
The reload period is reset to zero every time you open an MBean view. The Unregister button is a shortcut for removing this MBean from the agent. Unregistering is covered in 6.3.1 Instantiating and Managing MBeans. The MBean description text provides some information about the MBean. Because standard MBeans are statically defined, they cannot describe themselves and the MBean server provides a generic text. Dynamic MBeans are required to provide their own description string at runtime according to the JMX specification. Except for the class name, this is the only way to tell standard and dynamic MBeans apart in the MBean view. 6.2.2 Table of AttributesThe second part of the MBean view is a table containing all attributes exposed by the MBean. For each attribute, this table lists its name, its Java type, its read-write access, and a string representation of its current value. While MBean attributes can be of any type, not all types can be displayed in the MBean view. The HTML adaptor is limited to basic data types that can be displayed and entered as strings. Read-only attributes whose type supports the toString method are also displayed. Enumerated types that are concrete subclasses of com.sun.jdmk.Enumerated are displayed as a menu with a pop-up selection list. Boolean attributes are represented as true-false radio buttons. Finally, attributes with array types are represented by a link to a page that displays the array values in a table. If the attribute is writable, you can enter values for the array elements to set them. For the complete list of supported types, see the Javadoc API of the HtmlAdaptorServer class. If an attribute type is not supported, this is indicated in place of its value. If there was an error when reading an attribute's value, the table shows the name of the exception that was raised and the message it contains. The name of each attribute is a link that displays a window containing the description for this attribute. Like the MBean description, attribute descriptions can only be provided by dynamic MBeans. The MBean server inserts a generic description for standard MBean attributes. Figure 6–3 shows the attributes of the HTML adaptor with a description of the Active attribute. Figure 6–3 MBean Attributes With a Description Window
To View an Attribute Description
Writable attributes have a text field for entering new values. To set the value of a writable attribute, type or replace its current value in the text field and click the Apply button at the bottom of the attributes table. Note – Do not try to modify the attributes of the HTML protocol adaptor here. See 6.3.1 Instantiating and Managing MBeans. Because there is only one Apply button for all the attributes, this systematically invokes the setter for all writable attributes, whether or not their fields have actually been modified. This might affect the MBean if setters have side effects, such as counting the number of modifications, as in the SimpleStandard and SimpleDynamic examples given in Part I The HTML adaptor detects attributes of the ObjectName type and provides a link to the view of the corresponding MBean. This link is labeled view and is located just under the displayed value of the object name. Because MBeans often need to reference other MBeans, this provides a quick way of navigating through MBean hierarchies. 6.2.3 List of OperationsThe last part of the MBean view contains all the operations exposed by the MBean. Each operation in the list is presented like a method signature. There is a return type, then a button with the operation name, and if applicable, a list of parameters, each with their type as well. As with the table of attributes, the list of operations contains only those involving types that can be represented as strings. The return type must support the toString method and the type of each parameter must be one of basic data types supported by the HTML adaptor. For the complete list, see the Javadoc API of the HtmlAdaptorServer class. Above each operation name is a link to its description. Parameter names are also active links that display a window with a description. Again, descriptions are only meaningful when provided by dynamic MBeans. The following figure shows some of the operations exposed by the HTML adaptor MBean and a description of the Start operation. Figure 6–4 MBean Operations With a Description Window (Partial View)
We will not perform any operations on this MBean until after a brief explanation in 6.3.1 Instantiating and Managing MBeans. To perform an operation, fill in any and all parameter values in the corresponding text fields and click the operation's button. The HTML adaptor displays a page with the result of the operation, either the return value if successful or the reason why the operation was unsuccessful. 6.3 Agent AdministrationThe agent administration page contains a form for entering MBean information when creating or unregistering MBeans. You can also instantiate an MBean through one of its public constructors. In order to instantiate an MBean, its class must be available in the agent application's classpath. Optionally, you can specify a different class loader if the agent contains other class loader MBeans. To Display the Agent Administration Page
The first two fields, Domain and Keys are mandatory for all administrative actions. The Domain field initially contains the string representing the agent's default domain. Together, these two fields define the object name, whether for a new MBean to be created or for an existing MBean to unregister. The Java class is the full class name of the object to be instantiated as a new MBean. This field is ignored when unregistering an MBean. Using the pull-down menu, you can choose one of three actions:
When you click the Send Request button, the HTML adaptor processes the action and updates the bottom of the page with the action results. You might have to scroll down to see the result. The text fields are not cleared after a request, enabling you to perform multiple operations. Clicking the Reset button returns the fields to their last posted value after you have modified them. 6.3.1 Instantiating and Managing MBeansSometimes, starting an MBean requires several steps, especially for agent services that require some sort of configuration. For example, you can instantiate another HTML adaptor for connecting to a different port. Usually, this is done programmatically in the agent application, but we must do it through the browser for the agent. To Create a New HTML Adaptor MBean
Through this new connection, you can stop, modify or remove the HTML adaptor MBean using port 8082. In that case, your original browser will also have to use http://localhost:8088/ to connect. Instead, we will manage the agent from the second host. To Instantiate MBeans With Constructors
The browser on the second host is no longer needed and we can remove the HTML adaptor on port 8088. To Unregister an MBean
6.3.2 Filtering MBeansBecause an agent can manage hundreds of MBeans, the agent view provides a filtering mechanism for the list that is displayed. An object name with wildcard characters is used as the filter, and only those MBeans that match are counted and displayed. Filters restrict the set of MBeans listed in the agent view. This might not be particularly useful for our small agent, but it can help you find MBeans among hundreds in a complex agent. In addition, management applications use the same filter syntax when requesting an agent's MBeans through the programmatic interface of a connector. The filtering enables managers to either get lists of MBean names or find a particular MBean instance. Filters are typed as partial object names with wildcard characters or as a full object name for which to search, using the syntax domain:key. Here are the basic substitution rules for filtering.
To Filter MBeans
Chapter 7 MBean Server InterceptorsAn MBean server forwards requests it receives to its default interceptor. A feature of the Java Dynamic Management Kit (Java DMK) enables you to modify this behavior of the MBean server and replace the default interceptor by another object implementing the same interface. The example provided demonstrates how you can use the concept of MBean server interceptors to forward requests to a specific interceptor, and to support “virtual” MBeans. The code samples in this chapter are from the files in the MBeanServerInterceptor example directory located in the main examplesDir/current directory (see “Directories and Classpath” in the Preface). This chapter covers the following topics: 7.1 Overview of MBean Server InterceptorsThe concept of interceptors exploits the proxy design pattern to enable you to modify the behavior of the MBean server. By default, the MBean server appears from the outside like a hollow shell that simply forwards every operation to the default interceptor. You can replace this default interceptor by another object implementing the same interface, to change the semantics of the MBean server. In most cases, you would use this other object to forward most or all operations to the default interceptor after doing some processing. However, you can also use it to forward some operations to other handlers instead, for instance depending on the object names involved. Figure 7–1 shows schematically how you can insert an interceptor between the MBean server and the default interceptor. Figure 7–1 Inserting a User Interceptor Between the MBean Server and the Default Interceptor
Some examples of the uses of interceptors are as follows:
Interceptors can be composed. When an interceptor is added, it is usually inserted between the MBean server shell and the current interceptor. Initially, the current interceptor is the default one. But if another interceptor has already been inserted, this other interceptor is the current one. Hence, a request could pass through several interceptors on its way to the default interceptor, for example a security checker and a logger. 7.2 Specifying the Behavior of an MBean Server InterceptorThe behavior to be implemented by an interceptor is specified by means of the MBeanServerInterceptor interface. An MBean server interceptor has essentially the same interface as an MBean server. An MBean server forwards received requests to its default interceptor, which might handle them itself or forward them to other interceptors. 7.3 Changing the Default InterceptorThe default interceptor can be changed by using the setMBeanServerInterceptor method of the JdmkMBeanServer interface. The JdmkMBeanServer interface provides methods for getting and setting the default MBeanServerInterceptor used for request treatment. By default, the MBeanServer implementation returned by the MBeanServerFactory is not a JdmkMBeanServer, and does not support MBeanServerInterceptors. To use interceptor you have to set the javax.management.builder.initial System property to com.sun.jdmk.JdmkMBeanServerBuilder before obtaining an MBean server from the MBeanServerFactory. How to set this system property is shown in Step 2. Note – Particular care must be taken when replacing the default MBean server interceptor with a user interceptor. The MBean server implemented in the Java DMK 5.1 passes requests to its default interceptor without checking the result returned, or the exceptions thrown by the interceptor. Consequently, user interceptors, which implement most of the methods defined in the MBeanServer interface, must behave as specified for the corresponding MBeanServer methods in the JMX specification. In particular, a method in an MBean server interceptor must not throw any exceptions apart from the following:
If an MBean server interceptor does not respect this condition, and, for example, throws a NullPointerException exception, this might have unexpected effects on calling code, which might not be protected against such behavior. 7.4 Running the MBean Server Interceptor ExampleThe MBean server interceptor example in the examples directory shows you two of the main functions of MBean server interceptors, forwarding requests to a specific MBean server interceptor, and creating virtual MBeans. The examplesDir/current/MBeanServerInterceptor directory contains the following source files:
To Run the MBean Server Interceptor Example
Chapter 8 Notification MechanismThis chapter presents the mechanisms for sending and receiving notifications by demonstrating them locally on the agent-side. MBeans for either resources or services are the source of notifications, called broadcasters. Other MBeans or objects that want to receive the notifications register with one or more broadcasters, and they are called listeners. Notification mechanisms are demonstrated through two sample broadcasters. The MBean server delegate that notifies listeners of MBean creation and unregistration, and an MBean that sends attribute change notifications. The code samples are from the files in the examplesDir/current/Notification example directory located in the main examplesDir (see Directories and Classpath in the Preface). This chapter covers the following topics:
8.1 Overview of NotificationsThe ability for resources and other entities to signal an event to their managing applications is a key functionality of management architectures. As defined in the Java Management Extensions (JMX) specification, notifications in the Java Dynamic Management Kit (Java DMK) provide a generic event mechanism whereby a listener can receive all events sent by a broadcaster. All notifications in the Java DMK rely on the Notification class that itself inherits from Java event classes. A string called the notification type inside a Notification object gives the nature of the event, and other fields provide additional information to the recipient. This ensures that all MBeans, the MBean server, and remote applications can send and receive Notification objects and its subclasses, regardless of their inner type. You can define new notification objects only by subclassing the Notification class. This ensures that the custom notifications will be compatible with the notification mechanism. New notification classes can be used to convey additional information to custom listeners, and generic listeners will still be able to access the standard Notification fields. However, because there are already fields provided for user data, subclassing is discouraged in the JMX architecture so that notification objects remain as universal as possible. Listeners usually interact with notification broadcasters indirectly through the MBean server. The interface of the MBean server enables you to associate a listener with any broadcaster MBean, thereby giving you dynamic access to any of the broadcasters that are registered. In addition, the MBean metadata provided through the MBean server contains the list of notification types that the MBean broadcasts. Figure 8–1 summarizes how listeners register with broadcasters and then receive notifications, in an agent application. Figure 8–1 Listener Registration and Notification Propagation
8.2 MBean Server Delegate NotificationsThe MBean server delegate object is an MBean that is automatically created and registered when an MBean server is started. It preserves the management model by serving as the management interface for the MBean server. The delegate exposes read-only information such as the vendor and version number of the MBean server. More importantly for this chapter, it sends the notifications that relate to events in the MBean server: all MBean registrations and unregistrations generate a notification. 8.2.1 NotificationEmitter InterfaceA class must implement the NotificationEmitter interface to be recognized as a source of notifications in the JMX architecture. This interface provides the methods for adding or removing a notification listener to or from the emitter. When the emitter sends a notification, it must send it to all listeners that are currently registered through this interface. This interface also specifies a method that returns information about all notifications that might be sent by the emitter. This method returns an array of MBeanNotificationInfo objects, each of which provides a name, a description string, and the type string of the notification. As detailed in the Javadoc API, the MBeanServerDelegate class implements the NotificationEmitter interface. We know from the JMX specification that it sends notifications of the following types:
Note – Although emitter objects are almost always MBeans, they should not expose the methods of the NotificationEmitter interface. That is, the MBean interface of a standard MBean should never extend the NotificationEmitter interface. As we shall see in Chapter 22, Notification Forwarding in Legacy Connectors, the remote connector clients provide the methods needed to register for and receive notifications remotely. The NotificationEmitter should be used in preference to the old NotificationBroadcaster class. 8.2.2 NotificationListener InterfaceListeners must implement the NotificationListener interface, and they are registered in the notification broadcasters to receive the notifications. The listener interface defines a handler method that receives all notifications of the broadcaster where the listener is registered. We say that a listener is registered when it has been added to the broadcaster's list of notification recipients. This is completely independent of any registration of either object in the MBean server. Like the broadcaster, the listener is generic, meaning that it can handle any number of different notifications. Its algorithm usually involves determining the type of the notification and taking the appropriate action. A listener can even be registered with several broadcasters and handle all of the notifications that are sent. Note – The handler is a callback method that the broadcaster calls with the notification object it wants to send. As such, it runs in the broadcaster's thread and should therefore run rapidly and return promptly. The code of the handler should rely on other threads to execute long computations or blocking operations. In our example, the listener is a trivial class that has a constructor and the handler method. Our handler simply prints out the nature of the notification and the name of the MBean to which it applied. Other listeners on the agent side might themselves be MBeans that process the event and update the state of their resource or the quality of their service in response. For example, the relation service must know when any MBeans participating in relations are unregistered. It does this by listening to MBean server delegate notifications. Example 8–1 Listener for MBean Server Delegate Notifications
In most cases, the notification object passed to the handler method is an instance of the Notification class. This class provides the notification type as well as a time-stamp, a sequence number, a message string, and user data of any type. All of these are provided by the broadcaster to pass any needed information to its listeners. Because listeners are usually registered through the MBean server, they only know the broadcaster by its object name, given by the getSource method of the notification object. Note – The notification model does not assume that notifications will be received in the same order that they are sent. If notification order is critical to your application, your broadcaster should set the sequence numbers appropriately, and your listeners should sort the received notifications. The MBean server delegate sends MBeanServerNotification objects that are subclasses of the Notification class. This subclass provides two constants to identify the notification types sent by the delegate and a method that gives the object name of the MBean that was registered or unregistered. Our notification handler uses these to print out the type of operation and the object name to which the operation applies. 8.2.3 Adding a Listener Through the MBean ServerNow that we have identified the objects involved, we need to add the listener to the notification broadcaster. Our example does this in the main method of the agent application. Example 8–2 Registering for MBean Server Delegate Notifications
In Example 8–2, the agent application adds the AgentListener instance to the delegate MBean, which is known to be a broadcaster. The object name of the MBean server delegate is given by the DELEGATE constant in the ServiceName class. The listener is added through the addNotificationListener method of the MBean server. This method preserves the management architecture by adding listeners to MBeans while referring only to the MBean object names. If an MBean implements the listener interface and needs to receive certain notifications, it can add itself to a broadcaster. For example, an MBean could use its preregistration method in order to add itself as a notification listener or it could expose a method that takes the object name of the notification broadcaster MBean. In both cases, its notification handler method must be designed to process all expected notification types. The last two parameters of the addNotificationListener methods of both the MBeanServer and the NotificationBroadcaster interfaces define a filter and a handback object, respectively. Filter objects are defined by the NotificationFilter interface and provide a callback method that the broadcaster calls before calling the notification handler. If the filter is defined by the entity that adds the listener, it prevents the handler from receiving unwanted notifications. Handback objects are added to a broadcaster along with a listener and are returned to the designated handler with every notification. The handback object is completely untouched by the broadcaster and can be used to transmit context information from the entity that adds the listener to the handler method. The functionality of filters and handback objects is beyond the scope of this tutorial; refer to the JMX specification for their full description. 8.3 Attribute Change NotificationsIn this second part of the notification example, we demonstrate attribute change notifications that can be sent by MBeans. An MBean designer can choose to send notifications whenever the value of an attribute changes or is changed. The designer can implement this mechanism in any manner, according to the level of consistency required by the management solution. The JMX specification only provides a subclass of notifications to use to represent the attribute change events: the AttributeChangeNotification class. 8.3.1 NotificationBroadcasterSupport ClassThe broadcaster in our example is a very simple MBean. The reset method triggers a notification whenever it is called. This policy is specific to our example. You might want to design an MBean that sends an attribute change every time the setter is called, regardless of whether or not the value is modified. Your management needs might vary. Example 8–3 shows the code for our SimpleStandard MBean class (the code for its MBean interface has been omitted). Example 8–3 Broadcaster for Attribute Change Notifications
This MBean sends its notifications and it implements the NotificationBroadcaster interface by extension of the NotificationBroadcasterSupport class, in order to provide all the mechanisms for adding and removing listeners and sending notifications. It manages an internal list of listeners and their handback objects and updates this list whenever listeners are added or removed. In addition, the NotificationBroadcasterSupport class provides the sendNotification method to send a notification to all listeners currently on its list. By extending this object, our MBean inherits all of this behavior. Subclassing NotificationBroadcasterSupport is a quick and convenient way to implement notification broadcasters. We do not even have to call a superclass constructor because it has a default constructor. We only need to override the getNotificationInfo method to provide details about all of the notifications that might be sent. 8.3.2 Attribute Change ListenerLike our listener for MBean server notifications, our listener for attribute change notifications is a trivial class consisting of just the handler method. Example 8–4 Listener for Attribute Change Notifications
Again, we are handling a subclass of the Notification class, this one specific to attribute change notifications. The AttributeChangeNotification class provides methods for extracting the information about the attribute, notably its name, its type and its values before and after the modification. Our handler does nothing more than display these to the user. If this handler were part of an MBean in a larger management solution, it would probably take some action, depending upon the change in value of the attribute. As demonstrated by the broadcaster's code (see Example 8–3), the subclass can easily be instantiated and sent instead of a Notification object. Its constructor provides parameters for initializing all of the attribute-related values. In our example, we do not use significant values for the sequenceNumber and timeStamp parameters because our listener has no need for them. One great advantage of Java DMK is that you only need to implement the level of functionality that you require for your management solution. 8.3.3 Adding a Listener Directly to an MBeanThere is nothing that statically indicates that our MBean sends attribute change notifications. In our case it is a design decision, meaning that we know that the listener will receive attribute change notifications because we wrote the MBean that way. At runtime, the MBean server exposes the list of notifications in this MBean's metadata object, allowing a manager that is interested in attribute changes to register the appropriate listener. Being confined to the agent, our example is much simpler. First we instantiate and register our simple MBean with the agent's MBean server. Then, because we have designed them to work together, we can add our listener for attribute changes to our MBean by calling the addNotificationListener method on the MBean server. Example 8–5 Registering for Attribute Change Notifications
There are two major implications when adding listeners directly rather than doing so using the MBean server:
The rest of the agent object's code performs the setup of the agent's MBean server and various input and output for running the example. Similar agents are presented in detail earlier in Part II. 8.4 Running the Agent Notification ExampleNow that we have seen all of our notification broadcaster objects and all of our listener handlers, we are ready to run the example. The examplesDir/current/Notification directory contains all of the files for the simple MBean, the listener objects, and the agent. When started, the agent application adds the MBean server delegate listener first, so that a notification can be seen for the creation of the SimpleStandard MBean. Attribute change notifications are triggered by invoking methods using the HTML adaptor. To Run the Agent Notification Example
|
||||||||||||||||||||||||||||||||||||||||