groovy.png

In my previous post, “Using JMX within a spring application“, I talked about monitoring your application with jmx. I discussed exposing beans with spring. At one of my current projects I am having problems exposing jmx through the default jmxrmi protocol. In his whitepaper about jmx, Allard mentiones another protocol, jmxmp. Spring has support for this remoting protocol as well. Therefore I wanted to try this out.

Another thing I wanted to experiment with is creating a groovy client. The technique with interfaces and proxies with spring as described in my previous post is  a lot of work when you are interested in a little bit of data. Therefore I wanted to see if using groovy is easier.

This blog post discusses these two topics with respect to JMX.

 

Exposing beans using jmxmp

To expose jmx beans, we need an mbeanserver. Spring makes it easy to obtain the the platform mbeanserver. By using the context namespace mbean-server bean, spring finds the platform MBeanServer. This server can than be used to register MBeans with and to register connection providers with. A connection provider is called a server connector. A server connector is  created using the spring provided factory bean

org.springframework.jmx.support.ConnectorServerFactoryBean

Using this factory bean we can configure the protocol used to expose the beans. Choosing the protocol is done using the ServiceUrl property. Other properties are available. You can start the connector in a separate thread and make this a daemon thread. The following code block gives you the complete configuration of jmx through jmxmp.

<context:mbean-server/>
<context:mbean-export registration="replaceExisting" server="mbeanServer"/>
<bean id="jmxServerConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean">
    <property name="threaded" value="true"/>
    <property name="daemon" value="true"/>
    <property name="server" ref="mbeanServer"/>
    <property name="serviceUrl" value="service:jmx:jmxmp://localhost:9998/"/>
</bean>

A few things in this code are important to notice. The serviceUrl that contains the jmxmp protocol definition as well as the port that clients can use to connect. Another thing to notice is the name of the server mbeanServer. This is  the default id of the MBeanServer. We need this id to provide the server to the connection factory and to the mbean exporter.

That is all there is to it. A last thing to remember is that you need an additional jar on your classpath to be able to use jmxmp. This does not come out of the box. I could not find a maven repository out there that has it. Therefore I added to to the maven repository myself. The download is available from the website of sun.

http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/download.jsp

I used the JMX Remote API 1.0.1_04 Reference Implementation, you will need the jmxremote_optional.jar. You can use the serviceUrl to connect from jconsole. Because we now use jmxmp, you have to tell jconsole to use jmxremote_optional.jar. Easiest way is to use the endorsed.dirs property. Start jconsole using the following command from the directory that contains the jmxremote_optional.jar:

jconsole ‘-J-Djava.endorsed.dirs=.’

Let us move on to creating a groovy client

Creating a groovy jmx client

Groovy makes it very easy to connect to a remote jmx service. All you need is the service url and a bit of knowledge of the beans that are exposed. The following lines of code show all you need from the groovy side:

import javax.management.remote.JMXServiceURL
import javax.management.remote.JMXConnectorFactory as JmxFactory

def serverUrl = 'service:jmx:jmxmp://localhost:9998/'
def server = JmxFactory.connect(new JMXServiceURL(serverUrl)).MBeanServerConnection
def serviceMonitor = new GroovyMBean(server,'nl.gridshore.monitoring.springannotation:name=contactServiceMonitorSpring,type=ContactServiceMonitorSpring')

println "${serviceMonitor.AmountOfContacts}"

The serviceUrl is the same as exposed by the spring configuration. Another important part is the domain, the name and the type of the bean to connect to. The result is a new GroovyMBean that acts as a proxy to the exposed MBean. Now you can just ask for the exposed attributes like AmountdOfContacts.

You could run this code as a groovy script. Spring comes with support for groovy. You can use groovy beans as real objects in your spring configuration. That way you can easily create jmx clients that you can expose through a web interface or something like that. Easiest way to do this is by implementing an interface that you can use to inject the groovy bean into another bean. The following line shows the spring configuration for a groovy bean.

    <lang:groovy id="jmxInfo"
                 script-source="file:///absolute/path/to/src/nl/gridshore/monitoring/groovy/JmxInfo.groovy"/>

Of course you need to put groovy on your classpath. Check the spring documentation to find out more about groovy support. The following code block shows the complete source code for the groovy class.

package nl.gridshore.monitoring.groovy

import javax.management.remote.JMXServiceURL
import javax.management.remote.JMXConnectorFactory as JmxFactory

class JmxInfo implements Info {
    public Map obtainParams() {
        Map params = new HashMap()
        def serverUrl = 'service:jmx:jmxmp://localhost:9998/'
        def server = JmxFactory.connect(new JMXServiceURL(serverUrl)).MBeanServerConnection
        def serviceMonitor = new GroovyMBean(server,'nl.gridshore.monitoring.springannotation:name=contactServiceMonitorSpring,type=ContactServiceMonitorSpring')

println "${serviceMonitor.AmountOfContacts}"

params.put("amountOfContacts",serviceMonitor.AmountOfContacts)
        return params
    }
}

Last part is to actually use the bean. Therefore I have created a very small runner with the main method as shown below.

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("nl/gridshore/monitoring/springannotation/spring-config.xml");
        ContactService service = context.getBean(ContactService.class);

        service.addContact(new Contact(20, "not me"));

        Info jmxInfo = (Info) context.getBean("jmxInfo");

        System.out.println("amount of contacts : " + jmxInfo.obtainParams().get("amountOfContacts"));
    }
Tagged on:         

2 thoughts on “Exposing jmx through jmxmp and reading the jmx data with groovy

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>