I'm trying to use GMBAL in our DropWizard application to simplify our JMX
integration.
Things are mostly working happily. I've got MBeans I can tweak and play
with via hawtio/jconsole. But, internally within our application, we'd
like to use typed proxies to access the MBeans.
For many attributes/operations, the proxy works. But, if I try to run a
ManagedOperation with no parameters, I get a NullPointerException:
java.lang.NullPointerException
at java.util.Arrays$ArrayList.<init>(Arrays.java:2842)
at java.util.Arrays.asList(Arrays.java:2828)
at org.glassfish.gmbal.impl.MBeanSkeleton.invoke(MBeanSkeleton.java:646)
at org.glassfish.gmbal.impl.MBeanImpl.invoke(MBeanImpl.java:403)
at
com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at
com.sun.jmx.mbeanserver.MXBeanProxy$InvokeHandler.invoke(MXBeanProxy.java:150)
at com.sun.jmx.mbeanserver.MXBeanProxy.invoke(MXBeanProxy.java:167)
at
javax.management.MBeanServerInvocationHandler.invoke(MBeanServerInvocationHandler.java:252)
at com.sun.proxy.$Proxy49.opWithoutArgs(Unknown Source)
at [redacted].GmbalTest.verifyProxyOpWithoutArgs(GmbalTest.java:94)
It seems like there should be code in MBeanSkeleton.invoke() that guards
against the null params array. InvocationHandler.invoke() specifies that
args will be null if the interface method takes no arguments.
The interface:
@ManagedObject
@Description("This is a child test!")
public interface TestChild {
@ManagedAttribute
@Description("The first attribute")
String getAttr1();
@ManagedAttribute
void setAttr1(String val);
@ManagedAttribute
@Description("The second attribute (read-only via the MBean interface)")
Integer getAttr2();
@ManagedOperation
void opWithoutArgsOrReturnType();
@ManagedOperation
String opWithoutArgs();
@ManagedOperation
String opWithArgAndReturn(String valToReturn);
}
The impl:
public class TestChildImpl extends BaseGmbalNode implements TestChild {
private String attr1 = "attr1";
private final Integer attr2;
public interface IFactory {
TestChildImpl create(String name, Integer attr2Val);
}
@Inject
public TestChildImpl(TestRoot parent, @Assisted String name, @Assisted
Integer attr2Val) {
super(parent, name);
attr2 = attr2Val;
}
@Override
public String getAttr1() {
return attr1;
}
@Override
public void setAttr1(String val) {
attr1 = val;
}
@Override
public Integer getAttr2() {
return attr2;
}
@Override
public void opWithoutArgsOrReturnType() {
logger.debug("intentionally No-op");
}
@Override
public String opWithoutArgs() {
return name;
}
@Override
public String opWithArgAndReturn(String valToReturn) {
return valToReturn;
}
}
The proxy is created via:
childProxy = JMX.newMXBeanProxy(
<server>,
<objName, retrieved from the ManagedObjectManager>,
TestChild.class,
true);
String val = childProxy.opWithoutArgs()
NOTE: I'm not using Glassfish or AMX. I found some references to AMXProxy,
but little documentation w/ regard to using AMX outside of Glassfish.