How to expose methods of a class dynamically.. using Model Mbean?

Hi,

Would like to expose methods of my POJO's dynamically.

for ex : my POJO wil have few getter and setter methods like getName(), setName()

Another POJO wil have methods like getAccntDetails(), setAccntDetails().

so how do i write a common Mbean implementation to expose both of these by JMX..using Model Mbean.

i saw a few examples, but at everyplace we need to mention those methods.

what if i have to adda a new POJO later.

Is this possible?

Thanks

Athahar

[523 byte] By [CoolestAtha] at [2007-10-3 9:51:07]
# 1

Athahar,

As an alternative to Model MBeans, you could consider the approach described in <http://weblogs.java.net/blog/emcmanus/archive/2006/10/build_your_own.html>.

If you do want to use Model MBeans, the example code in the documentation of the package javax.management.modelmbean would be a good starting point <http://download.java.net/jdk6/docs/api/javax/management/modelmbean/package-summary.html>. But as you've probably noticed it's quite a lot of work to build a Model MBean.

Here's a class that makes a Model MBean based on the public getters in an object. It should be straightforward to generalize it to include setters too.

public class POJOMBeanFactory {

public static ModelMBean makeMBean(Object resource) {

try {

return makeMBean2(resource);

} catch (RuntimeException e) {

throw e;

} catch (Exception e) {

throw new RuntimeException(e);

}

}

private static ModelMBean makeMBean2(Object resource)

throws JMException, InvalidTargetObjectTypeException {

Method[] methods = resource.getClass().getMethods();

List<Method> getters = new ArrayList<Method>();

for (Method method : methods) {

if (method.getName().startsWith("get") &&

!method.getName().equals("get") &&

!method.getName().equals("getClass") &&

method.getParameterTypes().length == 0 &&

method.getReturnType() != void.class)

getters.add(method);

}

int ngetters = getters.size();

ModelMBeanAttributeInfo[] attrs = new ModelMBeanAttributeInfo[ngetters];

ModelMBeanOperationInfo[] ops = new ModelMBeanOperationInfo[ngetters];

for (int i = 0; i < ngetters; i++) {

Method getter = getters.get(i);

String attrName = getter.getName().substring(3);

Descriptor attrD =

new DescriptorSupport(new String[] {

"name=" + attrName,

"descriptorType=attribute",

"getMethod=" + getter.getName()

});

attrs[i] = new ModelMBeanAttributeInfo(attrName,

attrName,

getter,

null,

attrD);

ops[i] = new ModelMBeanOperationInfo(getter.getName(),

getter);

}

ModelMBeanInfo mmbi =

new ModelMBeanInfoSupport(resource.getClass().getName(),

resource.getClass().getName(),

attrs,

null, // constructors

ops,

null); // notifications

ModelMBean mmb = new RequiredModelMBean(mmbi);

mmb.setManagedResource(resource, "ObjectReference");

return mmb;

}

}

emcmanusa at 2007-7-15 5:08:25 > top of Java-index,Core,Monitoring & Management...
# 2

Hi Eamonn,

Thanks .. I could work on that, and i could get the getter working for the POJO's.. but i tried a lot on trying to expose the setter methods..

private static ModelMBean makeMBean2(Object resource)

throws JMException, InvalidTargetObjectTypeException {

Method[] methods = resource.getClass().getMethods();

List<Method> operations = new ArrayList<Method>();

List<Method> getters = new ArrayList<Method>();

List<Method> setters = new ArrayList<Method>();

for (Method method : methods) {

if (method.getName().startsWith("get") &&

!method.getName().equals("get") &&

!method.getName().equals("getClass") &&

method.getParameterTypes().length == 0 &&

method.getReturnType() != void.class)

{

operations.add(method);

getters.add(method);

}

if (method.getName().startsWith("set") &&

!method.getName().equals("set"))

{

operations.add(method);

setters.add(method);

}

}

int opsSize = operations.size();

int ngetters = getters.size();

ModelMBeanAttributeInfo[] attrs = new ModelMBeanAttributeInfo[opsSize];

ModelMBeanOperationInfo[] ops = new ModelMBeanOperationInfo[opsSize];

for (int i = 0; i < ngetters; i++) {

Method getter = getters.get(i);

Method setter = setters.get(i);

String attrName = getter.getName().substring(3);

Descriptor attrD =

new DescriptorSupport(new String[] {

"name=" + attrName,

"descriptorType=attribute",

"getMethod=" + getter.getName()

});

attrs[i] = new ModelMBeanAttributeInfo(attrName,

attrName,

getter,

setter,

attrD);

ops[i] = new ModelMBeanOperationInfo(getter.getName(),

getter);

ops[ngetters+i] = new ModelMBeanOperationInfo(setter.getName(),

setter);

}

ModelMBeanInfo mmbi =

new ModelMBeanInfoSupport(resource.getClass().getName(),

resource.getClass().getName(),

attrs,

null, // constructors

ops,

null); // notifications

ModelMBean mmb = new RequiredModelMBean(mmbi);

mmb.setManagedResource(resource, "ObjectReference");

return mmb;

}

Can u please tell me where i'm going wrong?

Exception in thread "main" java.lang.RuntimeException: javax.management.IntrospectionException: bad getter arg count

at POJOMBeanFactory.makeMBean(POJOMBeanFactory.java:27)

at POJOMbeanAgent.<init>(POJOMbeanAgent.java:34)

at POJOMbeanAgent.main(POJOMbeanAgent.java:69)

Caused by: javax.management.IntrospectionException: bad getter arg count

at javax.management.MBeanAttributeInfo.attributeType(MBeanAttributeInfo.java:236)

at javax.management.MBeanAttributeInfo.<init>(MBeanAttributeInfo.java:122)

at javax.management.modelmbean.ModelMBeanAttributeInfo.<init>(ModelMBeanAttributeInfo.java:200)

at POJOMBeanFactory.makeMBean2(POJOMBeanFactory.java:68)

at POJOMBeanFactory.makeMBean(POJOMBeanFactory.java:23)

Thanks

Athahar

CoolestAtha at 2007-7-15 5:08:25 > top of Java-index,Core,Monitoring & Management...
# 3
Hi Athahar,I guess your setter methods want an argument and have a void return type. I think line 27 is operations.add(method);for setter methodsHope this helps,Michele
michele81a at 2007-7-15 5:08:25 > top of Java-index,Core,Monitoring & Management...
# 4

Hi Athahar,

The logic that builds up the ModelMBeanAttributeInfo[] is wrong.

1) There's no guarantee that there will be as many getters as setters - in other

words, in the general case, getters.size() != setters.size()

2) There's no guarantee that getters.get(i) and setters.set(i) relates to the same

attribute: getters.get(i) could be the method <i>getFoo()</i> and setters.get(i)

could be the method <i>setBar()</i>

You can't do everything in a single loop, you need 3 loops:

What you would need to do is:

0) Allocate an array list to contain a yet unknown number of ModelMBeanAttributeInfo

1) loop over getters:

1.1) for each getter extract the attribute name

1.2) from the attribute name, construct the name of the corresponding setter method.

1.3) see whether you find a setter method by that name in setters

1.4) remove the setter method from the setters list.

1.5) construct the ModelMBeanAttributeInfo for that attribute, add it to the list

2) At this point, the setters list should only contain setters for which there was no

getter (will be empty unless there was a setFoo() without a getFoo() - which

usually won't happen). But just in case you will need to loop over the remaining

setters:

2.1) for each getter extract the attribute name

2.2) from the attribute name, construct the name of the corresponding setter method.

2.3) construct the ModelMBeanAttributeInfo for that attribute, add it to the list

3) Convert the ArrayList<ModelMBeanAttributeInfo> into an array (use

toArray())

4) Now loop over operations

4.1) for each operations construct a ModelMBeanOperationInfo object.

Hope this helps,

-- daniel

http://blogs.sun.com/jmxetc

dfuchsa at 2007-7-15 5:08:25 > top of Java-index,Core,Monitoring & Management...