Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MBeanExporter - giving name to MBean

Tags:

spring

jmx

I'm trying to run a simple application with jmx-exported method. I do it like (spring-context and cglib for "@Configuration" are in classpath):

package com.sopovs.moradanen.jmx;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jmx.export.MBeanExporter;
import org.springframework.stereotype.Component;

@Component
@Configuration
public class SpringJmxTest {
public static void main(String[] args) {
    new AnnotationConfigApplicationContext("com.sopovs.moradanen.jmx");
    while (true) {
        Thread.yield();
    }
}

@Bean
public MBeanExporter createJmxExporter() {
    return new MBeanExporter();
}

public interface FooBarMBean {
    public String hello();
}

@Component
public static class FooBar implements FooBarMBean {
    @Override
    public String hello() {
        return "Hello";
    }
}
}

However when I run it I get:javax.management.MalformedObjectNameException: Key properties cannot be empty. I tried to debug and solved it with:

@Component
public static class FooBar implements FooBarMBean, SelfNaming {
    @Override
    public String hello() {
        return "Hello";
    }

    @Override
    public ObjectName getObjectName() throws MalformedObjectNameException {
        return new ObjectName("fooBar:name=" + getClass().getName());
    }
}

But is there a better way to supply a name for MBean?

like image 656
Ivan Sopov Avatar asked Nov 15 '11 14:11

Ivan Sopov


2 Answers

You can use the descriptions annotations provided by Spring Context @Managed* :

To do this, you must NOT implements the interface with "MBean" or "MXBean" suffix, neither SelfNaming. Then, the bean will be detected as a standard spring "managed bean" when MBeanExporter will registerBeanInstance(..), and will be converted to a ModelMBean using all spring annotations, including descriptions of attributes, operations, parameters, etc..

As a requirement, you should declare in your spring context the MBeanExporter with AnnotationJmxAttributeSource, MetadataNamingStrategy, and MetadataMBeanInfoAssembler attributes, which can be simplified like this (as described here):

<bean id="mbeanExporter"
     class="org.springframework.jmx.export.annotation.AnnotationMBeanExporter" />

or:

<context:mbean-export />

or, using programmatic approach:

@Configuration
@EnableMBeanExport
public class AppConfig {

}

And your managed bean should look like this :

@Component("myManagedBean")
@ManagedResource(objectName="your.domain.jmx:name=MyMBean",
                 description="My MBean goal")
public class AnnotationTestBean {

    private int age;

    @ManagedAttribute(description="The age attribute", currencyTimeLimit=15)
    public int getAge() {
        return age;
    }

    @ManagedOperation(description = "Check permissions for the given activity")
    @ManagedOperationParameters( {
        @ManagedOperationParameter(name = "activity",
                                   description = "The activity to check")
    })
    public boolean isAllowedTo(final String activity) {
        // impl
    }
}

Remember to not implements an MBean interface, which would be a StandardMBean, and SelfNaming interface, which would bypass Spring naming management !

like image 66
Donatello Avatar answered Sep 21 '22 15:09

Donatello


You can use KeyNamingStrategy to define all JMX-related properties inside XML configuration without adding any compile-time dependencies to Spring into the source code of your MBean:

<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
    <property name="namingStrategy" ref="namingStrategy"/>
</bean>
<bean id="namingStrategy"
        class="org.springframework.jmx.export.naming.KeyNamingStrategy">
    <property name="mappings">
        <props>
            <prop key="someSpringBean">desired.packageName:name=desiredBeanName</prop>
        </props>
    </property>
</bean>

If you can live with somewhat arbitrary object names, then you can use the IdentityNamingStrategy as a naming strategy for MBeanExporter and minimize the XML configuration event further:

<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
    <property name="namingStrategy" ref="namingStrategy"/>
</bean>
<bean id="namingStrategy"
        class="org.springframework.jmx.export.naming.IdentityNamingStrategy"/>
like image 26
Oleg Estekhin Avatar answered Sep 19 '22 15:09

Oleg Estekhin