Tag Archives: @ManagedAttribute

JMX and MBean Support With Spring

The context of this post is simply about how to use the Spring Framework to export your Spring-managed pojos for management and monitoring via JMX. Later I’ll post on using Hyperic, in the cloud, etc. First things first – as this is an update from a similar post of mine from ’08 or early ’09.

Let’s start by adding the spring jmx dependency, which will be something like this, depending on the repos you are using:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.core</artifactId>
<version>${spring.framework.version}</version>
</dependency>

Service Pojo

Now let’s set up some java classes for management. I have a business service that I want to monitor and a pojo to instrument.

@BusinessService
@ManagedResource(objectName = "bean:name=inventoryManager", description = "Inventory Service",
        log = true, logFile = "oms.log", currencyTimeLimit = 15, persistPolicy = "OnUpdate", persistPeriod = 200,
        persistLocation = "foo", persistName = "bar")
public class InventoryServiceImpl implements InventoryService {

    @Autowired private InventoryDao inventoryDao;

    @ManagedOperation(description = "Add two numbers")
    @ManagedOperationParameters({
            @ManagedOperationParameter(name = "x", description = "The first number"),
            @ManagedOperationParameter(name = "y", description = "The second number")})
    public int add(int x, int y) {
        return x + y;
    }

    @ManagedOperation(description = "Get inventory levels")
    @ManagedOperationParameters({@ManagedOperationParameter(name = "product", description = "The Product)})
    public long getInventoryLevel(Product product) {
        return getInventoryLevel(product.getSkew());
    }
}

First, let’s peak into my @BusinessService annotation in case you are wondering:

@Transactional
@Service
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface BusinessService {
}

Annotating any of my service layer pojo’s makes them both transactional and with an instance created in the Spring context.

Entity Pojo

Now here is a simple pojo as an entity or javabean, what have you:

@ManagedResource(objectName = "bean:name=myPojoEntity", description = "My Managed Bean", log = true,
        logFile = "oms.log", currencyTimeLimit = 15, persistPolicy = "OnUpdate", persistPeriod = 200,
        persistLocation = "foo", persistName = "bar")
public class MyPojo {

    private long somethingToTuneInRuntime;

    /* Creates a writeable attribute for managing */
    @ManagedAttribute(description = "Tunable In Runtime Attribute",
            currencyTimeLimit = 20,
            defaultValue = "bar",
            persistPolicy = "OnUpdate")
    public void setSomethingToTuneInRuntime(long value) {
        this.somethingToTuneInRuntime = value;
    }

    @ManagedAttribute(defaultValue = "foo", persistPeriod = 300)
    public String getSomethingToTuneInRuntime() {
        return somethingToTuneInRuntime;
    }
}

Spring Config

Now let’s configure Spring to autoregister our pojos to export and manage/monitor:
Create a jmx-context.xml file in your WEB-INF/* dir

Add: <context:mbean-export/>

Activates default exporting of MBeans by detecting standard MBeans in the Spring
context as well as @ManagedResource annotations on Spring-defined beans.
Rather than defining an MBeanExporter bean, just provide this single element. I could walk you through a simple, simpler and simplest config of spring jmx but with annotational config in the simplest requirements, this is all you need to do to get up and running. If you need object naming in multiple vm situations, you can easily do that and other things too but, that’s out of scope for this post ;)

Share/Save

Annotational MBean Export with Spring and JMX

If you just want to easily export mbeans to jconsole or an external profiling tool this is pretty sweet:

I. Create a Spring schema config file for JMX

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<!-- This bean needs to be eagerly pre-instantiated in order for the exporting to occur: -->
<!-- ***************** Autodetects Annotated Beans JMX Exposure *********************** -->
<bean id="annotationalMbeanExporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="autodetect" value="true"/>
<property name="namingStrategy" ref="namingStrategy"/>
<property name="assembler" ref="assembler"/>
<!-- one of many optional config options -->
<property name="registrationBehaviorName" value="REGISTRATION_IGNORE_EXISTING"/>
</bean>
<bean id="attributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="attributeSource"/>
</bean>
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="attributeSource"/>
</bean>
</beans>

II. Annotate a component, bean, etc

@Service
@ManagedResource(objectName = "bean:name=applicationMonitor")
public class ClientMBeanService implements IClientMBeanService {

@ManagedOperation(description = "Monitor the JMS broker")
public BrokerStatistics exposeBroker() {
return new BrokerDelegate().exposeMBean();
}
}

@Component
@ManagedResource(objectName = "spring:name=broker", description = "ActimemMQ Broker")
public class BrokerStatistics {

private String brokerId;
private String brokerName;
private long totalMessages;
private long totalConsumers;
private long totalTopics;
private long totalQueues;
private List<Map> topics;
private List<Map> queues;

@ManagedAttribute
public String getBrokerId() {
return brokerId;
}
...etc
}

The annotational configuration in the mbean exporter allows automatic registration and mbean creation of beans. It’s that simple.

Share/Save