5

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;
  }
}
sworded
  • 2,419
  • 4
  • 31
  • 48
  • is your implementation class in the same package as your inteface ? look at this link https://forums.oracle.com/forums/thread.jspa?messageID=4795137. – grepit Feb 18 '13 at 15:13
  • They are both in the same package. I didn't find any help in that link. – sworded Feb 18 '13 at 15:17
  • did you look at the "Posted: Sep 7, 2010 7:08 AM" it has some information about similar error you posted. The exception is the same but the main problem might be something else. I only can try to help without seeing the code it's kind of hard to debug. https://forums.oracle.com/forums/thread.jspa?messageID=4795137. – grepit Feb 18 '13 at 15:22
  • This is just a java app. – sworded Feb 18 '13 at 15:38
  • can you tell me if you are using jre6 or jre1.6.0_01 or some other version.try using an older jre instead of jre1.6.0_01 (previous version of jre ,jre6). hope this helps and resolves your problem – grepit Feb 18 '13 at 15:48
  • I am using JRE 1.7. What you are suggesting is more of a hack than a solution. – sworded Feb 18 '13 at 15:51

1 Answers1

10

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:

  • The actual registered MBean (which has a complex typed attribute) is called Foo and it's management interface is called FooMXBean.
  • The complex type (the attribute of Foo is called Bar and has a management interface called BarMBean. This guy cannot return any values that are not open types or other properly exposed complex types.

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:

  • JMSDestination implements JMSDestinationMXBean
  • JmsDestinationAttributes implements JmsDestinationAttributesMBean

...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:

JConsole view of the MXBean

The JConsole view of the MXBean's attributes looks like this:

JConsole view of the MXBean's Attributes

Make sense ?

Nicholas
  • 15,916
  • 4
  • 42
  • 66
  • Thanks! I was missing an interface for my custom type. – sworded Feb 18 '13 at 17:11
  • One may have to [activate JMX](http://stackoverflow.com/q/856881/1005481) to be able to access the custom MBean via jconsole. – barfuin Nov 22 '13 at 17:00
  • Be sure to follow Nicholas' example and define the getter method as `public JmsDestinationAttributes getAttributes();`, specifying the *implementation class* as return type. Using `public JmsDestinationAttributesMBean getAttributes();` would not work (using the *interface* as return type). Kinda weird, but hey. – barfuin Nov 22 '13 at 18:04
  • For benefit of others: I had similar requirement and Nicholas reply helped. But you have to add @ConstructorProperties({"name"}) just before constructor of JmsDestinationAttributes or you may get run-time error. Further I could even return arrays of objects from the custom type methods. – mvsagar Dec 05 '14 at 17:05