Создание MBean в Java

Я пытаюсь заставить класс реализовать интерфейс 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)

Я думаю, что потенциально это потому, что он возвращает карту?

Ответ 1

Только столкнувшись с этим исключением и посмотрев на текущие ответы, а также https://blogs.oracle.com/jmxetc/entry/javax_management_standardmbean_when_and, я подумал, что это может помочь подчеркнуть и прояснить следующее, что уже выяснено:

  • NotCompliantMBeanException вызван, помимо прочего, несоблюдением этого соглашения "ConcreteClassName" реализует "ConcreteClassNameMBean"

  • Я решил это, обновив исходное имя моего интерфейса mbean от "OrignalNameMBean" до "OriginalNameMXBean", разрешив регистрировать mbean без соблюдения соглашения

  • Другим решением было бы следовать соглашению.

Ответ 2

У меня была такая же проблема ( "не реализует DynamicMBean и не следует стандартным соглашениям MBean" ), и эта статья помогла мне решить проблему (см. раздел "Стандартная версия": https://blogs.oracle.com/jmxetc/entry/javax_management_standardmbean_when_and).

Мне нужно явно построить

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

затем зарегистрируйте mbean:

mbServer.registerMBean(mbean, mBeanName);

Он работает.

Когда я регистрирую mBeanImpl с помощью mbServer, я получил вышеописанное исключение.

Ответ 3

Класс реализации mbean может объявлять столько методов, сколько им нравится, которые не определены в интерфейсе mbeans... Нет требования, чтобы класс реализации/должен только реализовывать методы интерфейса.

Во многих случаях эта проблема вызвана тем, что интерфейс mbean и класс реализации не находятся в одном пакете!

Ответ 4

Вы можете изменить имя интерфейса с SomethingMBean на SomethingM X Bean, например 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");
}

if not endsWith "MXBean", он вернет false, а затем вызовет throw IllegalArgumentException

jdk версия: 1.8.0_25

класс - это "JMX", строка 376

Ответ 5

Просто измените имя класса реализации из ProfileCache на ProfileCacheInterface. Теперь он должен работать. Кроме того, ваш класс реализации может иметь любое количество собственных методов, и эти методы не должны упоминаться в интерфейсе MBean.

Стандартное обозначение именования JMX стандартно выглядит как

    public interface SomeBeanNameMBean{
    ...
    }

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

Ответ 6

Во всех примерах, которые я видел для реализаций MBean, я никогда не видел, чтобы класс определял метод, который не был определен в интерфейсе. Например, ProfileCache имеет метод updateCache, а ProfileCacheInterfaceMBean - нет. Попробуйте удалить метод updateCache из ProfileCache и посмотрите, будет ли он работать.

Ответ 7

Я столкнулся с той же проблемой, что и "Исключение в потоке" main "javax.management.NotCompliantMBeanException", в моем случае я сохранил интерфейс MBean и классы реализации в пакете difnet. Чтобы решить эту проблему, я переместил интерфейс MBean и класс реализации в один и тот же пакет.

Ответ 8

Просто измените суффикс интерфейса с "MBean" на "MXBean". Это работает для меня.