Один и тот же класс JMX Mbean для нескольких приложений на одном сервере - PullRequest
4 голосов
/ 16 августа 2011

У меня более 5 весенних веб-приложений, и все они используют другую общую библиотеку.Эта общая библиотека имеет свои собственные MBeans.Из-за обязательного ограничения уникального objectName мои приложения не могут быть развернуты на одном сервере.

То, как я использую MBeans, выглядит следующим образом:

@ManagedResource(objectName = "com.org.city:name=City", description = "City related operations")

Я хотел бы использовать один и тот же класс MBean с разными objectNames для всех приложений.Как правильно использовать его, не дублируя мои MBeans.

Спасибо

Ответы [ 5 ]

5 голосов
/ 18 октября 2013

Я столкнулся с той же проблемой и создал решение Cemo . Вот пример реализации.

context.xml

<!-- Set up jmx bean auto scanning -->
<!-- Note: we're not using <context:mbean-export /> because we need to provide our own naming strategy -->
<bean id="mbeanExporter" class="org.springframework.jmx.export.annotation.AnnotationMBeanExporter">
    <property name="namingStrategy">
        <bean class="com.foo.MultiAppMetadataNamingStrategy">
            <property name="applicationName" value="${application.name}" />
        </bean>
    </property>
</bean>

MultiAppMetadataNamingStrategy.java

public class MultiAppMetadataNamingStrategy implements ObjectNamingStrategy, InitializingBean {

    private String applicationName;

    public MultiAppMetadataNamingStrategy() {
    }

    public MultiAppMetadataNamingStrategy(String applicationName) {
        this.applicationName = Preconditions.checkNotNull(applicationName, "applicationName must not be null");
    }

    public void setApplicationName(String applicationName) {
        this.applicationName = Preconditions.checkNotNull(applicationName, "applicationName must not be null");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (applicationName == null) {
            throw new IllegalArgumentException("Property 'applicationName' is required");
        }
    }

    @Override
    public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException {
        Class managedClass = AopUtils.getTargetClass(managedBean);
        String domain = ClassUtils.getPackageName(managedClass);

        Hashtable<String, String> properties = new Hashtable<>();
        properties.put("type", ClassUtils.getShortName(managedClass));
        properties.put("name", beanKey);
        // ensure the application name is included as a property in the object name
        properties.put("app", applicationName);
        return ObjectNameManager.getInstance(domain, properties);
    }
}

Это позволяет настроить mbean, например:

package com.foo;

@ManagedResource(description = "Bean description")
public class MyBean {
    ...
}

, который зарегистрирует mbean с именем объекта com.foo:name=myBean,type=MyBean,app=CustomAppName

4 голосов
/ 18 августа 2011

Я реализовал ObjectNamingStrategy для пользовательского поведения.

   @Override
  public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException {
     Class managedClass = AopUtils.getTargetClass(managedBean);
     Hashtable<String, String> properties = new Hashtable<String, String>();
     properties.put("type",ClassUtils.getPackageName(managedClass).concat(".").concat(ClassUtils.getShortName(managedClass)));
     properties.put("name", beanKey);
     return ObjectNameManager.getInstance(domain, properties);
  }
0 голосов
/ 07 декабря 2017

Эти ответы помогли направить меня в правильном направлении, но для установки на основе аннотаций не хватало нескольких элементов (однако я не использую Spring Boot)

Spring Docs по этому вопросу скажем:

Если вы предпочитаете использовать подход, основанный на аннотациях, для определения ваших интерфейсов управления, то доступен вспомогательный подкласс MBeanExporter: AnnotationMBeanExporter.При определении экземпляра этого подкласса конфигурация namingStrategy, ассемблер и attributeSource больше не требуется, поскольку она всегда будет использовать стандартные метаданные на основе аннотаций Java (автоопределение также всегда включено).Фактически, вместо определения bean-компонента MBeanExporter, аннотация @EnableMBeanExport @Configuration поддерживается даже более простым синтаксисом.

Но использование @EnableMBeanExport лишает вас возможности определять свой собственный NamingStrategy

Итак, вместо того, чтобы просто установить @Bean метод, который возвращает мой MBeanExporter с пользовательской стратегией именования, использующей контекстный путь.

@Configuration
public class JmxUtil {

    @Value("#{servletContext.contextPath}")
    private String contextPath;
    private String domain = "foo.bar";

    @Bean
    public MBeanExporter mbeanExporter() {
        AnnotationMBeanExporter exporter = new AnnotationMBeanExporter();
        exporter.setNamingStrategy((managedBean, beanKey) -> {
            return ObjectNameManager.getInstance(domain, new Hashtable<>(ImmutableMap.of(
                "name", beanKey,
                "instance", contextPath
            )));
        });
        exporter.setDefaultDomain(domain);
        return exporter;
    }
}
0 голосов
/ 06 апреля 2016

Вы можете определить простую стратегию именования на основе свойств, используя заполнитель (и).
Каждая война будет иметь свою собственную копию app.properties
Э.Г.

С файлом свойств: app.properties

appName=MyApp1 #Every app will have it own value e.g,MyApp2,MyApp3,MyApp4,MyApp5

и PropertiesPlaceHolder

<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     <property name="placeholderPrefix" value="$app{" />    
     <property name="location" value="classpath:app.properties"/>
</bean>

Определение objectName

@ManagedResource(objectName=com.mycompany:name=$app{appName}-MyBean")
public class MyBean {}

Ваш боб будет назван

com.mycompany
    +MyApp1-MyBean
    +MyApp2-MyBean
    +MyApp3-MyBean
    +MyApp4-MyBean
    +MyApp5-MyBean

Вы можете использовать более одного заполнителя объекта.
Работает с Spring 4.0.2

0 голосов
/ 16 августа 2011

Вам необходимо изменить поведение регистрации экспортера mbean:

<property name="registrationBehaviorName" value="REGISTRATION_REPLACE_EXISTING"/>

Но это все равно будет означать, что только одно приложение регистрирует компонент. И вы не можете логически иметь более одного mbean с одним именем из нескольких приложений. Как будет определено, какое приложение вызывать? Используйте имя приложения в качестве префикса имени mbean.

...