Tải bản đầy đủ - 0 (trang)
Example 3-4. Creating metadata classes to expose attributes and operations from Queue's parent class, Basic, through explicit superclass exposure

Example 3-4. Creating metadata classes to expose attributes and operations from Queue's parent class, Basic, through explicit superclass exposure

Tải bản đầy đủ - 0trang

new MBeanOperationInfo[numberOfParentOperations+3];

MBeanParameterInfo[] parms = new MBeanParameterInfo[0];

operationInfo[0] = new MBeanOperationInfo(

"suspend", "Suspends processing of the Queue.",

parms, Void.TYPE.getName(), MBeanOperationInfo.ACTION);

operationInfo[1] = new MBeanOperationInfo(

"resume", "Resumes processing of the Queue.",

parms, Void.TYPE.getName(), MBeanOperationInfo.ACTION);

operationInfo[2] = new MBeanOperationInfo(

"reset", "Resets the state of this MBean.",

parms, Void.TYPE.getName(), MBeanOperationInfo.ACTION);

operationInfo[3] = new MBeanOperationInfo(

"enableTracing", "Enables tracing.",

parms, Void.TYPE.getName(), MBeanOperationInfo.ACTION);

operationInfo[4] = new MBeanOperationInfo(

"disableTracing", "Disables tracing.",

parms, Void.TYPE.getName(), MBeanOperationInfo.ACTION);

// . . .

// Notifications

// no notifications for this MBean, also no parent notifications

MBeanNotificationInfo[] notificationInfo = new

MBeanNotificationInfo[0];

// . . .

// MBeanInfo

_MBeanInfo = new MBeanInfo(

"Queue",

"Queue MBean",

attributeInfo,

constructorInfo,

operationInfo,

notificationInfo

);

}

// . . .

}



As you can see from Example 3-4, creating the necessary metadata classes requires only

knowledge of the attributes and operations and extra code. Notice that we didn't create

metadata for the DebugOn attribute or the enableDebugging and disableDebugging

operations. This is just to show you that when you select explicit superclass exposure as

the management interface inheritance approach for your dynamic MBeans, you can pick

and choose which attributes and operations to expose from the parent class.

We must also make modifications to Queue's implementation of DynamicMBean, as

discussed in the next section.

3.3.1.1 getAttribute()



Implementing this method is a simple matter of adding the same number of else if

blocks as the number of attributes we're exposing from the parent class:

public class Queue extends Basic implements DynamicMBean {

// . . .



109



public Object getAttribute(String attributeName)

throws AttributeNotFoundException,

MBeanException,

ReflectionException {

Object ret = null;

if (attributeName.equals("QueueSize")) {

ret = new Integer(getQueueSize());

}

// . . .

else if (attributeName.equals("RemoveWaitTime")) {

ret = new Long(getRemoveWaitTime());

}

else if (attributeName.equals("NumberOfResets")) {

ret = new Integer(getNumberOfResets());

}

else if (attributeName.equals("TraceOn")) {

ret = new Boolean(isTraceOn());

}

else throw new AttributeNotFoundException(

"Queue.getAttribute(): ERROR: " +

"Cannot find " + attributeName + " attribute.");

}

return ret;



}

// . . .

}



We exposed two attributes from the parent class, so we write two else if blocks for

those attributes and delegate to the appropriate method. We know we can call this method

because of Java inheritance.

3.3.1.2 setAttribute()



There are no writable attributes on Basic, but if there were, the logic would be similar to

that of getAttribute(). Suppose, for the purposes of example, that TraceOn is a writable

attribute. In that case, the implementation of setAttribute() would look like this:

public class Queue extends Basic implements DynamicMBean {

// . . .

public void setAttribute(Attribute attribute)

throws AttributeNotFoundException,

InvalidAttributeValueException,

MBeanException,

ReflectionException {

String name = attribute.getName();

Object value = attribute.getValue();

// See if attribute is on parent class

if (name.equals("QueueSize")) {

setQueueSize(((Integer)value).intValue());

}

else if (name.equals("TraceOn")) {

setTraceOn(((Boolean)value).booleanValue());

}



110



else throw new AttributeNotFoundException(

"Queue.getAttribute(): ERROR: " +

"Cannot find " + attributeName + " attribute.");

}

// . . .

}



If the name of the attribute to set is "TraceOn," we simply invoke the setter for the

attribute.

3.3.1.3 invoke()



You are probably starting to see a pattern here. When you use explicit superclass

exposure as the management interface inheritance mechanism for your MBeans, you

simply include extra else if blocks for the attributes and, in this case, the operations that

are to be exposed.

The following example shows how to use this approach to modify invoke() to expose

Basic's management interface methods:

public class Queue extends Basic implements DynamicMBean {

// . . .

public Object invoke(String operationName,

Object params[],

String signature[])

throws MBeanException,

ReflectionException {

Object ret = Void.TYPE;

ret = Void.TYPE;

if (operationName.equals("suspend")) {

suspend();

}

else if (operationName.equals("resume")) {

resume();

}

else if (operationName.equals("enableTracing")) {

enableTracing();

}

else if (operationName.equals("disableTracing")) {

disableTracing();

}

else {

throw new ReflectionException(

new NoSuchMethodException(operationName),

"Queue.invoke(): ERROR: " +

"Cannot find the operation " + operationName + "!");

}

return ret;

}

// . . .

}



111



One drawback of using explicit superclass exposure is that the child class must have

explicit knowledge of the parent class's management interface. Also, this approach is

more susceptible to errors when code changes to the parent class are necessary. However,

you must weigh these risks against the benefits of being able to selectively expose

attributes and operations from the parent class's management interface on the child class

and base your decision of whether or not to use this approach on that information.

3.3.2 Superclass Delegation

This is the more generic of the two approaches to dynamic MBean management interface

inheritance. With superclass delegation, when figuring out which attribute to get/set or

operation to invoke, the child class first looks at its own management interface and then,

if the attribute or operation is not found, delegates to its parent class (which may delegate

to its parent class, and so on). This requires changes to how the metadata is created for

the child class. Let's look at an example from the application.

Queue inherits from Basic, and Basic implements the DynamicMBean interface for its

attributes (TraceOn, DebugOn, and NumberOfResets) and its operations (enableTracing,



disableTracing, enableDebugging, and disableDebugging). Recall from Example 3-4

how we created all of the metadata classes for Queue's management interface in Queue's

constructor. If we are going to augment Queue's management interface with attributes and

operations from Basic's management interface, we must expose those attributes and

operations on the MBeanInfo instance that is returned from Queue's getMBeanInfo()

method. Thus, we must create the metadata classes for these attributes and operations in

Queue's constructor. Example 3-5 shows how to do this, showing enough of Example 3-4

to provide you some context.

Example 3-5. Creating metadata classes to expose attributes and operations from Queue's

parent class, Basic, through superclass delegation

public class Queue extends Basic implements DynamicMBean {

// . . .

private MBeanInfo _MBeanInfo;

// . . .

public Queue(int queueSize) {

MBeanInfo parentInfo = super.getMBeanInfo();

// . . .

// Attributes

MBeanAttributeInfo[] parentAttributes = parentInfo.getAttributes();

int numberOfParentAttributes = parentAttributes.length;

MBeanAttributeInfo[] attributeInfo =

new MBeanAttributeInfo[numberOfParentAttributes + 10];

System.arraycopy(parentAttributes,0,attributeInfo,0,numberOfParentAttri

butes);

attributeInfo[numParentAtts+0] = new MBeanAttributeInfo(

"QueueSize", Integer.TYPE.getName(),

"Maximum number of items the queue may contain at one time.",

true, true, false);

attributeInfo[numParentAtts+1] = new MBeanAttributeInfo(



112



"NumberOfConsumers", Integer.TYPE.getName(),

"The number of consumers pulling from this Queue.",

true, false, false);

// . . .

// Constructors

// . . .

// Operations

MBeanOperationInfo[] parentOperations = parentInfo.getOperations();

int numberOfParentOperations = parentOperations.length;

MBeanOperationInfo[] operationInfo =

new MBeanOperationInfo[numberOfParentOperations+2];

System.arraycopy(parentOperations,0,operationInfo,0,numberOfParentOpera

tions);

MBeanParameterInfo[] parms = new MBeanParameterInfo[0];

operationInfo[numParentOps+0] = new MBeanOperationInfo(

"suspend", "Suspends processing of the Queue.",

parms, Void.TYPE.getName(), MBeanOperationInfo.ACTION);

operationInfo[numParentOps+1] = new MBeanOperationInfo(

"resume", "Resumes processing of the Queue.",

parms, Void.TYPE.getName(), MBeanOperationInfo.ACTION);

// . . .

// Notifications

MBeanNotificationInfo[] parentNotifications =

parentInfo.getNotifications();

int numberOfParentNotifications = parentNotifications.length;

// no notifications for this MBean, use parent notifications

MBeanNotificationInfo[] notificationInfo =

new MBeanNotificationInfo[numberOfParentNotifications+0];

System.arraycopy(parentNotifications,0,notificationInfo,0,

numberOfParentNotifications);

// . . .

// MBeanInfo

_MBeanInfo = new MBeanInfo(

"Queue",

"Queue MBean",

attributeInfo,

constructorInfo,

operationInfo,

notificationInfo

);

}

// . . .

}



The highlighted lines in Example 3-5 are the lines that must be added to create the

necessary metadata classes. Actually, we're only making a copy of the reference to the

metadata classes that were created by the parent class. We could instead have chosen to

clone() the instances, but this approach seemed a reasonable one for the purpose at hand.

Once we get the MBeanInfo instance that contains the metadata for the parent class, it is a

simple matter of making sure the attribute, operation, and notification arrays are large

enough to accommodate the attributes, operations, and notifications for both the Queue

class and its parent class. That's it; it's pretty straightforward.



113



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Example 3-4. Creating metadata classes to expose attributes and operations from Queue's parent class, Basic, through explicit superclass exposure

Tải bản đầy đủ ngay(0 tr)

×