Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Same JMX Mbean class for many application at same server

I have more than 5 spring web application and all of them are utilizing another common library. This common library has its own MBeans. Because of mandatory unique objectName constraint, my applications could not be deployed on same server.

The way I am using MBeans are like this:

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

I would like to use same MBean class with different objectNames for all applications. What is the correct way to utilize it without duplicating my MBeans.

Thanks

like image 601
Cemo Avatar asked Jan 19 '23 23:01

Cemo


2 Answers

I ran into the same issue, and built off of Cemo's solution. Here is a sample implementation.

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);
    }
}

This allows setting up an mbean like:

package com.foo;

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

which will register an mbean with object name com.foo:name=myBean,type=MyBean,app=CustomAppName

like image 144
bostaunieux Avatar answered Jan 30 '23 04:01

bostaunieux


I have implemented ObjectNamingStrategy for custom behaviour.

   @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);
  }
like image 27
Cemo Avatar answered Jan 30 '23 04:01

Cemo