users@gmbal.java.net

NullPointerException when running operation without parameters via Proxy

From: steve christensen <stevec1973_at_gmail.com>
Date: Mon, 15 Sep 2014 15:43:28 -0600

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.