I am trying to create an MXBean with a custom attribute, but I get javax.management.NotCompliantMBeanException IJmsDestinationMBean.getAttributes has parameter or return type that cannot be translated into an open type
I have read that MXBean attributes have to be OpenType compatible. How would I make my attribute work this way? All the classes below are in the same package.
class JmsDestinationMBean implements IJmsDestinationMBean{
protected JmsDestinationAttributes attributes = new JmsDestinationAttributes();
@Override
public JmsDestinationAttributes getAttributes() {
return this.attributes;
}
}
@MXBean
interface IJmsDestinationMBean {
JmsDestinationAttributes getAttributes()
}
class JmsDestinationAttributes {
protected String name
protected int messagesCurrentCount
protected int consumersCurrentCount
String getName() {
this.name;
}
int getMessagesCurrentCount() {
this.messagesCurrentCount;
}
int getConsumersCurrentCount() {
this.consumersCurrentCount;
}
}
The problem is the interface IJmsDestinationMBean. It returns a type JmsDestinationAttributes which is not an open type. Here's the rules-of-thumb I follow when doing this:
So (for this example) the "host" MBean needs to be an MXBean in order to support complex types , and the complex type needs to have an interface called <ClassName>MBean. Note that one has the MXBean interface, and the other has the MBean interface.
Here's my example:
...apologies for the loose case standard. It's an on the fly example.
Here the JMSDestination code, with a main to create and register. I am simply using the user name property to provide the name.:
public class JmsDestination implements JmsDestinationMXBean {
protected JmsDestinationAttributes attrs = new JmsDestinationAttributes(System.getProperty("user.name"));
public JmsDestinationAttributes getAttributes() {
return attrs;
}
public static void main(String[] args) {
JmsDestination impl = new JmsDestination();
try {
ManagementFactory.getPlatformMBeanServer().registerMBean(impl, new ObjectName("org.jms.impl.test:name=" + impl.attrs.getName()));
Thread.currentThread().join();
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
}
}
The JMSDestinationMXBean code:
public interface JmsDestinationMXBean {
public JmsDestinationAttributes getAttributes();
}
The JmsDestinationAttributes code which uses the same name and random numbers for the values:
public class JmsDestinationAttributes implements JmsDestinationAttributesMBean {
protected final String name;
protected final Random random = new Random(System.currentTimeMillis());
public JmsDestinationAttributes(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getMessagesCurrentCount() {
return Math.abs(random.nextInt(100));
}
public int getConsumersCurrentCount() {
return Math.abs(random.nextInt(10));
}
}
.... and the JmsDestinationAttributesMBean:
public interface JmsDestinationAttributesMBean {
public String getName();
public int getMessagesCurrentCount();
public int getConsumersCurrentCount();
}
The JConsole view looks like this:
The JConsole view of the MXBean's attributes looks like this:
Make sense ?