在Java中创建MBean

16

我正在尝试让一个类实现MBean接口,这样我就可以在运行时查询它的属性。我要查询的类如下:

public class ProfileCache implements ProfileCacheInterfaceMBean{

    private Logger logger = Logger.getLogger(ProfileCache.class);
    private ConcurrentMap<String, Profile> cache;


    public ProfileCache(ConcurrentMap<String, Profile> cache){
        this.cache = cache;     
    }

    /**
     * Update the cache entry for a given user id
     * @param userid the user id to update for 
     * @param profile the new profile to store
     * @return true if the cache update
     */
    public boolean updateCache(String userid, Profile profile) {
        if (cache == null || cache.size() == 0) {
            throw new RuntimeException("Unable to update the cache");
        }
        if (cache.containsKey(userid)) {
            if (profile != null) {
                cache.put(userid, profile);
                logger.info("Updated the cache for user: "
                            + userid + "  profile: " + profile);
                return true;
            }
        }
        return false;
    }

    @Override
    public ConcurrentMap<String, Profile> getCache() {
        if(cache == null){
            cache = new ConcurrentHashMap<String, Profile>();
        }
        return cache;
    }


}

界面看起来像这样

import com.vimba.profile.Profile;

public interface ProfileCacheInterfaceMBean {

    ConcurrentMap<String, Profile> getCache();

}

我这样开始启动MBean

        cacheImpl = new ProfileCache(factory.createCacheFromDB());
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        ObjectName profileCache = new ObjectName("org.javalobby.tnt.jmx:type=ProfileCacheInterfaceMBean");  
        mbs.registerMBean(cacheImpl, profileCache);

然而,我一直收到以下异常,我不确定我需要改变什么。

javax.management.NotCompliantMBeanException: MBean class com.vimba.cache.ProfileCache does not implement DynamicMBean, and neither follows the Standard MBean conventions (javax.management.NotCompliantMBeanException: Class com.vimba.cache.ProfileCache is not a JMX compliant Standard MBean) nor the MXBean conventions (javax.management.NotCompliantMBeanException: com.vimba.cache.ProfileCache: Class com.vimba.cache.ProfileCache is not a JMX compliant MXBean)

我认为可能是因为它返回一个Map?


谢谢你如此有帮助的评论,如果我理解了它的意思,我就不会在这里发帖了。毫无疑问,你的讽刺语气应该能帮你获得更多的积分 - 做得好。 - Biscuit128
那是一个真正的问题。无论如何,您不理解异常的哪个部分?首先,“不实现”--> 表示您的类需要实现该接口。 - TJ-
1
这是我困惑的根源,因为我遵循的教程没有实现这个接口 - 也许我应该去看一下官方文档。 - Biscuit128
将托管Bean类名称重命名为“YourClassNameMXBean”对我有用。 - Rajesh Balan
8个回答

34

刚刚遇到了这个异常,并查看了当前的答案以及https://blogs.oracle.com/jmxetc/entry/javax_management_standardmbean_when_and,我觉得强调和澄清以下已经阐明的内容可能会有所帮助:

  1. NotCompliantMBeanException是由于未能遵循“ConcreteClassName”实现“ConcreteClassNameMBean”的约定之一而引起的。

  2. 我通过将mbean接口的原始名称从“OrignalNameMBean”更新为“OriginalNameMXBean”来解决了这个问题,使得mbean可以在不遵循约定的情况下注册。

  3. 另一个解决方案是遵循约定。


2
链接已失效。 - Sameer
但解决方案仍然有效 :) - Davut Gürbüz

13

我曾遇到同样的问题(“没有实现DynamicMBean,也没有遵循标准MBean约定”),这篇文章帮助我解决了问题(请参见Using StandardMBean部分:https://blogs.oracle.com/jmxetc/entry/javax_management_standardmbean_when_and)。

I have to explicitly construct a

StandardMBean mbean = new StandardMBean(mBeanImpl, MBeanInterface.class);

then register the mbean:

mbServer.registerMBean(mbean, mBeanName);

It works.

When I register the mBeanImpl with the mbServer, I got the above exception.


最适合我的答案 - Saad Benbouzid

8

实现mbean类可以声明任意数量的方法,这些方法在mbeans接口中未定义... 实现类不必只能实现接口方法。

在许多情况下,这个问题是由于mbean接口和实现类不在同一个包中引起的!


1
确实是这样,谢谢!将接口移动到与实现相同的包中,为我解决了错误。 - JayPatel
1
我遇到了同样的问题,因为接口和实现在同一 ear 的不同构件中,而且重构没有考虑到 api 构件中的包结构。在将实现构件中的包结构解决成与 api 构件相同之后,错误消失了。 - SeriousITGuy

3

您可以将接口名称从SomethingMBean更改为SomethingMXBean,例如将HelloMBean更改为HelloMXBean,从jdk的源代码中我看到了这个:

public static boolean isMXBeanInterface(Class<?> interfaceClass) {
    if (!interfaceClass.isInterface())
        return false;
    if (!Modifier.isPublic(interfaceClass.getModifiers()) &&
        !Introspector.ALLOW_NONPUBLIC_MBEAN) {
        return false;
    }
    MXBean a = interfaceClass.getAnnotation(MXBean.class);
    if (a != null)
        return a.value();
    return interfaceClass.getName().endsWith("MXBean");
}

如果不以 "MXBean" 结尾,它将返回 false,然后导致抛出 IllegalArgumentException 异常。
JDK 版本:1.8.0_25。
类名为 "JMX",位于第 376 行。

2

只需将接口后缀从"MBean"更改为"MXBean"即可。

这对我有效。


1

只需将您的实现类名称从ProfileCache更改为ProfileCacheInterface即可。现在应该可以正常工作。此外,您的实现类可以拥有任意数量的其自身方法,并且这些方法无需在MBean接口中提到。

JMX的标准MBean命名约定如下:

    public interface SomeBeanNameMBean{
    ...
    }

    public class SomeBeanName implements SomeBeanNameMBean{
    ...
    //implements all the methods of SomeBeanNameMBean
    ...
    //implement other class's own methods if needed
    }

1

我遇到了与“Exception in thread" main" javax.management.NotCompliantMBeanException”类似的问题,在我的情况下,我将MBean接口和实现类分别放在不同的包中。为解决该问题,我将MBean接口和实现类都移动到同一个包中。


0
在我看过的所有MBean实现的示例中,我从未见过一个类定义了一个在接口中没有定义的方法。例如,ProfileCache有一个名为updateCache的方法,但是ProfileCacheInterfaceMBean中并没有定义这个方法。尝试将ProfileCache中的updateCache方法移除,然后看看是否能正常工作。

两个对象都有getCache方法吗? - Biscuit128
尝试将ProfileCache中的updateCache方法注释掉,看看是否仍会抛出异常。 - jdb1015
为什么那会有任何区别呢?! - Biscuit128
因为似乎 MBean 实现要求只实现接口方法;在 ProfileCache 中不应该实现任何额外的方法。此时,如果您在尝试注释掉 updateCache 之前发布另一条评论,那么您就是在刷声望。 - jdb1015
1
下面的答案是正确的。在MBean实现中添加额外的方法不是问题。 - Martin Asenov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接