springspring-integrationjmxspring-jmxjmxtrans

Spring integration with jmxtrans-agent to monitor bean


I am using Spring integration but want to use jmxtrans-agent to monitor my splitter. Like following simple example, I try to count the number of request arrive at splitter.

@ManagedResource
public class Splitter {
    private final AtomicInteger count = new AtomicInteger();

    @ManagedAttribute
    public int getCount(){
        return this.count.get();
    }

    public List<JsonNode> split(Message<ArrayNode> message) {
        count.incrementAndGet();
        ...
    }
}

// spring integration workflow
<int:gateway id="myGateway" service-interface="someGateway" default-request-channel="splitChannel" error-channel="errorChannel"  default-reply-channel="replyChannel" async-executor="MyThreadPoolTaskExecutor"/>

<int:splitter id="mySplitter" input-channel="splitChannel" output-channel="transformChannel" method="split">
    <bean class="Splitter" />
</int:splitter>

// in MBeanExporter, I added
<entry key="myApplication:type=Splitter,name=splitter" value-ref="mySplitter" />

// query
<query
    objectName='myApplication:type=Splitter,name=splitter'
    attribute='Count'
    resultAlias='myApplication.Splitter.count'/>
<collectIntervalInSeconds>20</collectIntervalInSeconds>

I cannot query the data, getting this error.

javax.management.AttributeNotFoundException: getAttribute failed: ModelMBeanAttributeInfo not found for number
    at javax.management.modelmbean.RequiredModelMBean.getAttribute(RequiredModelMBean.java:1524)
    at org.springframework.jmx.export.SpringModelMBean.getAttribute(SpringModelMBean.java:109)

Solution

  • Oh! Sorry for missing that. Now I see your code:

    <int:splitter id="mySplitter" input-channel="splitChannel" output-channel="transformChannel" method="split">
        <bean class="Splitter" />
    </int:splitter>
    

    So, that <bean class="Splitter" /> is inner bean and it isn't visible for any other environment.

    To make it working you should move that bean definition on the top level and reference it from the the <splitter>:

    <bean id="mySplitter" class="Splitter" />
    
    <int:splitter id="mySplitter" input-channel="splitChannel" output-channel="transformChannel" ref="mySplitter" method="split"/>
    

    You used the <splitter> component for JMX export which really doesn't expose inner beans, only its own managed attributes/operations.