Model MBeans use the descriptors to support additional metadata and policy for caching, persistence, and logging for the management interface defined in ModelMBeanInfo . Simply put, a descriptor is a set of unordered keyword= value pairs that can be accessed with the Descriptor interface. Copies of descriptors are retrieved from the management interface element with the DescriptorAccess interface. A different descriptor type is defined for and implemented by ModelMBeanOperationInfo , ModelMBeanConstructor- Info , ModelMBeanAttributeInfo , and ModelMBeanNotificationInfo . You can also retrieve and set descriptors from methods on ModelMBeanInfo . You can get and set descriptors by name or descriptor type ( mbean , attribute , operation , notification ): interface Descriptor { java.lang.Object clone(); java.lang.String[] getFieldNames(); java.lang.String[] getFields(); java.lang.Object getFieldValue(java.lang.String fieldName); java.lang.Object[] getFieldValues(java.lang.String[] fieldNames); boolean isValid(); void removeField(java.lang.String fieldName); void setField(java.lang.String fieldName, java.lang.Object fieldValue); void setFields(java.lang.String[] fieldNames, java.lang.Object[] fieldValues); } The Descriptor interface allows a variety of accesses . You can retrieve one descriptor field, a specific set of descriptor fields, or all descriptor fields. The Descriptor interface also provides a method that can be used to validate that the current value of the descriptor is valid for its descriptor type. A set of descriptor keywords are defined by the JMX specification to ensure standard and uniform functionality and treatment. We will cover these in detail later in this section. Note that you can set values for descriptors as well. You can replace an entire field value. In the setField() method the fieldValue parameter is copied into the descriptor. New keywords can be added by applications or adapters at any time (see Section 4.8.3). The Descriptor interface is implemented by the DescriptorSupport class. You can use this class to create descriptors in a variety of ways. Choose the one that's easiest for you because there is no difference in the net effect:
This style does support object values. The Descriptor interface also supports a clone() operation that is very convenient for creating new descriptors from existing ones as templates. The remove() and setField() methods make it very simple to selectively modify the descriptor. Sections 4.5.1 through 4.5.5 cover the standard descriptor keywords supported by all model MBeans. These descriptor keywords are defined in the JMX specification [13] as well. Section 4.6 then discusses caching and persistence behavior in the model MBean. 4.5.1 Model MBean DescriptorsDescriptors at the MBean level define default policies for the attributes, operations, and notifications for persistence, caching, and logging. Table 4.1 shows the descriptors that are valid for model MBeans. Table 4.1. Valid Model MBean Descriptors
Looking back at the Apache server example again, we can see an example of the model MBean descriptor. Here is another example for an Apache server that also defines a persistence policy: // Set MBean descriptor example Descriptor mmbDescription = new DescriptorSupport( new String[] { "name=apacheServerManager", // server MBean name "descriptorType=mbean", // MBean descriptor "displayName=apache server MBean", // screen name of MBean "log=T", // log all notifications "logFile=jmxmain.log", // log in jmxmain.log "currencyTimeLimit=10", // cache all attribute // values for 10 seconds "persistPolicy=noMoreOftenThan", // persist on change "persistPeriod=10", // no more often than // 10 seconds "persistLocation=jmxRepository", // save in jmxRepository // directory "persistName=serverMBean"}); // save in file called // serverMBean The descriptorType field is set to "mbean" to indicate that this is an MBean descriptor. The displayName field is set to "serverMBean". The line log=T indicates that all notifications will be logged into the file named in the logFile field: jmxmain.log . The line currencyTimeLimit=10 means that all attributes in this model MBean will be cached for up to 10 seconds. After a value is 10 seconds old, it will be retrieved from the managed resource again. The persistPolicy field is set to noMoreOftenThan with a persistPeriod value of 10 . This means that the attribute values will be saved to a directory called jmxRepository in a file called serverBean whenever they are updated, but no more often than every 10 seconds. This restriction prevents high rates of updates that are not meaningful. 4.5.2 Attribute DescriptorsThe model MBean attribute descriptor includes policy and configuration for managing its persistence, caching, protocol mapping, and handling of get and set requests . When the model MBean is created by the managed resource, the managed resource defines the operations that will be executed by the model MBean that will satisfy the get and set of the attribute. By defining operations, the actual methods called to satisfy getAttribute() and setAttribute() requests are allowed to vary and to be delegated to a wide range of objects at runtime. This flexibility enables management of distributed, dynamic applications. If an attribute has no operation associated with it, the values are maintained in the value descriptor field in the model MBean. Let's look at the implications of this a little more closely. If an attribute has no method signature associated with it, then no managed-resource method can be invoked to satisfy it. This means that for setAttribute() , the value is simply cached in the model MBean and any AttributeChangeNotification listeners are sent an attribute change notification ”that is, an AttributeChangeNotification instance. For getAttribute() , the currently cached value for the attribute in the model MBean itself is simply returned. In this case there is no delegation to a managed resource. This can be useful for static information and helps minimize the interruption of managed resources to retrieve static resource information. When attribute value caching is supported, if the data requested is current, then the model MBean returns its cached value and the managed resource is not interrupted with a data retrieval request. Because direct interaction with the managed resource is not required for each interaction with the management system, the impact of management activity on runtime application resources and performance is minimized. Table 4.2 shows the descriptors that are supported in the ModelMBeanAttributeInfo descriptor. This attribute descriptor example is based on the State attribute of the Apache model MBean example and illustrates most of the fields: // Set attribute descriptor examples ModelMBeanAttributeInfo[] aAttributes = new ModelMBeanAttributeInfo[3]; // State Descriptor stateDesc = new DescriptorSupport(); stateDesc.setField("name","State"); stateDesc.setField("descriptorType","attribute"); stateDesc.setField("displayName","Apache Server State"); stateDesc.setField("getMethod","getState"); stateDesc.setField("setMethod","setState"); stateDesc.setField("currencyTimeLimit","20"); aAttributes[0] = new ModelMBeanAttributeInfo("State", "java.lang.String", "State: state string.", true, true, false, stateDesc); Table 4.2. ModelMBeanAttributeInfo Descriptors
In this example the name of the attribute is State , but the displayed name will be "Apache Server State". The getMethod descriptor field defines getState() as the get method. The setMethod descriptor field defines setState() as the set method. The value 20 in the currencyTimeLimit field means that this attribute value will be cached for 20 seconds. In the following ModelMBeanAttributeInfo instance for total accesses to the Apache server, we have added an example for the use of default and protocolMap fields: // TotalAccesses Descriptor totalAccessesDesc = new DescriptorSupport(); totalAccessesDesc.setField("name","TotalAccesses"); totalAccessesDesc.setField("descriptorType", "attribute"); totalAccessesDesc.setField("default", "0"); totalAccessesDesc.setField("displayName", "Total Accesses on Server"); totalAccessesDesc.setField("getMethod","getTotalAccesses"); totalAccessesDesc.setField("setMethod","setTotalAccesses"); Descriptor TotalAccessesMap = new DescriptorSupport( new String[] { "SNMP=1.3.6.9.12.15.18.21.0", "CIM=ManagedResource.Version"}); totalAccessesDesc.setField("protocolMap",(TotalAccessesMap)); aAttributes[1] = new ModelMBeanAttributeInfo("TotalAccesses", "java.lang.Integer", "TotalAccesses: number of times the State string", true, false, false, totalAccessesDesc); A value of in the default field means that the default value for TotalAccesses , if it is not set, should be . The protocol map contains two hints to the protocol adapters. One is for an SNMP adapter indicating that when the MIB object ID (OID) 1.3.6.9.12.15.18.21.0 is requested, the value in TotalAccesses should be returned. The other is for a CIM adapter indicating that this same attribute and value is equivalent to the Version attribute in the CIM class ManagedResource . In the following example we are defining a static attribute, the maximum thread pool to be used in each JVM for an Apache server. The value field of the descriptor is set to 99 . The currencyTimeLimit descriptor field is set to “ 1 , which means that the value never becomes stale. Notice that no get or set methods have been defined: // MaxPool static value Descriptor maxPoolHardValueDesc = new DescriptorSupport(); maxPoolHardValueDesc.setField("name","maxPool"); maxPoolHardValueDesc.setField("descriptorType","attribute"); maxPoolHardValueDesc.setField("value", new Integer("99")); maxPoolHardValueDesc.setField("displayName", "maximum Thread Pool for Apache Server, a Hard Coded Value"); maxPoolHardValueDesc.setField("currencyTimeLimit","-1"); aAttributes[2] = new ModelMBeanAttributeInfo("maxPoolHardValue", "java.lang.Integer", "maxPool: static maximum thread pool value for the Apache server", true, false, false, maxPoolHardValueDesc); Just for the sake of completeness, if we needed to define a static value that contained a Date object, in this case the time that the Apache server was started, the setting of the descriptor would look like this: // StartDate as a static value Descriptor startDateDesc = new DescriptorSupport(); startDateDesc.setField("name","startDate"); startDateDesc.setField("descriptorType","attribute"); startDateDesc.setField("displayName","ApacheServerStartTime"); startDateDesc.setField("value", new Date()); startDateDesc.setField("currencyTimeLimit","-1"); And the setting of the ModelMBeanAttributeInfo object would look like this: // Set the attribute info aAttributes[3] = new ModelMBeanAttributeInfo("startDateHardValue", "java.util.Date", "startDate of ApacheServerHardValue: static Date value", true, false, false, startDateDesc); Here is how you would get these attributes using the model MBean myMMBean : // Retrieving these attributes using the model MBean myMMBean: RequiredModelMBean myMMBean = new RequiredModelMBean(); // Set ModelMBeanInfo and managedResource here String myState = (String) myMMBean.getAttribute("State"); String myAccesses = (String) myMMBean.getAttribute("TotalAccesses"); Integer myPool = (Integer) myMMBean.getAttribute("maxPool"); 4.5.3 Constructor DescriptorsEvery MBean must have a public constructor. It is also recommended that a default constructor ”that is, a constructor that accepts no parameters ”be provided. If you define constructors that require parameters, then you must define the constructor with an MBeanConstructorInfo instance. The ModelMBeanInfo descriptor for the constructor defines the constructor to be an operation with a method role of constructor, as opposed to operation, getter, or setter, examples of which we will see later. Constructor signatures are defined just like operation signatures (which are discussed in the next section): // Constructor descriptor example ModelMBeanConstructorInfo[] aConstructors = new ModelMBeanConstructorInfo[1]; Class apacheServerClass = null; try { apacheServerClass = Class.forName("jnjmx.ch4.ApacheServer"); } catch (Exception e) { System.out.println("Apache Server Class not found"); } Constructor[] constructors = apacheServerClass.getConstructors(); Descriptor apacheServerDesc = new DescriptorSupport(); apacheServerDesc.setField("name","ApacheServer"); apacheServerDesc.setField("descriptorType", "operation"); apacheServerDesc.setField("role","constructor"); aConstructors[0] = new ModelMBeanConstructorInfo( "ApacheServer(): Constructs an apache server query tool", constructors[0], apacheServerDesc); In this example we see that a default constructor has been defined for the model MBean. Table 4.3 gives the details of all the descriptors standardized for ModelMBeanConstructorInfo . 4.5.4 Operation DescriptorsFor operations, the method signature must be defined in ModelMBeanOperationInfo . For each operation defined, a target object must be identified on which to invoke the operations. This target object can be set for the model MBean as a whole (by the setManagedResource() method) or per operation in the targetObject descriptor field. You can even have different target objects for different operations. This flexibility allows distributed, component-based applications to be supported by the model MBean. It also supports management of applications that do not already have a management facade. Like attributes, the model MBean supports caching the last returned value of the operation. Caching can reduce the interruptions to the managed application. Table 4.4 lists the descriptors that are supported in ModelMBeanOperationInfo . Table 4.3. ModelMBeanConstructorInfo Descriptors
Table 4.4. ModelMBeanOperationInfo Descriptors
The following example illustrates a simple Integer start() operation. A value of 3 in the currencyTimeLimit descriptor field specifies that the value returned from the operation will be valid in the cache for three seconds. The value of jnjmx.ch4.ApacheServer for the class field defines what the class for the target object will be. Then we can see where we are creating an apacheServerInitiator instance. This object is set as the target object for just the start operation because it must use a command line to start the Apache process. The targetObjectType descriptor field must be set to objectReference . The stop()method is still invoked on the default target object for the model MBean . // Operation descriptor example ModelMBeanOperationInfo[] dOperations = new ModelMBeanOperationInfo[1]; MBeanParameterInfo[] params = null; Descriptor stopDesc = new DescriptorSupport(); stopDesc.setField("name","stop"); stopDesc.setField("descriptorType","operation"); stopDesc.setField("class","jnjmx.ch4.ApacheServer"); stopDesc.setField("role","operation"); dOperations[0] = new ModelMBeanOperationInfo("stop", "stop(): stop the apache server", params , "void", MBeanOperationInfo.ACTION, stopDesc); Descriptor startDesc = new DescriptorSupport( new String[] { "name=start", "class=jnjmx.ch4.ApacheServerInitiator", "descriptorType=operation", "role=operation", "currencyTimeLimit=3"}); // Create an instance of ApacheServerInitiator just for the // start operation ApacheServerInitiator asf = new ApacheServerInitiator("http://www.apache.org"); startDesc.setField("targetObject",asf); startDesc.setField("targetObjectType","objectReference"); aOperations[1] = new ModelMBeanOperationInfo("start", "start(): start the apache server", params, "java.lang.Integer", MBeanOperationInfo.INFO, startDesc); Here is how you would invoke the start operation on the model MBean myMMBean where it has no parameters: // invoking the operation Integer startRC = (Integer) apacheMMBean.invoke("start", null, null); 4.5.5 Notification DescriptorsThe model MBean notification descriptor defines a severity value, visibility value, and message ID for national language support, as well as whether the notification should be logged. A response operation may also be defined. Table 4.5 lists the descriptor keywords supported in the model MBean notification descriptor. Table 4.5. ModelMBeanNotificationInfo Descriptors
Here is a notification descriptor example from the Apache model MBean: // Declare an "Apache Server Down" notification ModelMBeanNotificationInfo[] apacheNotifications = new ModelMBeanNotificationInfo[1]; Descriptor apacheDownEventDesc = new DescriptorSupport( new String[] { "descriptorType=notification", "name=jmx.ModelMBean.General.Apache.Down", "severity=1", "MessageId=Apache001", "log=T", "logfile=jmx.apachelog" }); apacheNotifications[0] = new ModelMBeanNotificationInfo( new String[] {"jmx.ModelMBean.General.Apache.Down" }, "jmx.ModelMBean.General", "Apache Server is Down", apacheDownEventDesc); In this case the name of the notification is jmx.ModelMBean.General.Apache.Down . The severity of the notification is set to 1 , and the message ID is "Apache001". This notification will always be logged in the file jmx.apachelog . Here is how you would send this notification from the myMMBean model MBean: apacheMMBean.sendNotification("Apache Server is Down"); |