Monday, May 18, 2009

JMX is my favorite rapper!

JMX rules! Some of his best songs: Where the Enterprise at, Xml Gon Give it to 'Ya, Ruff Ryders MBean Anthem, Can't Stop Being Greedy.

The biggie commerce (big e-commerce) project I've been working on is now dev complete and we are working on some production readiness tasks. My job today was instrumenting the most important pages of the application with JMX so we can get statistics on requests/sec, responses/sec, and successes and failures on a per page basis. Word.

I'm new to JMX and it took me some time to get it working in Jetty and Tomcat with Spring. Here are a few of the snags I ran into and what I was doing wrong.

  1. Getting Jetty's MBean server to start when we are using the builtin jetty Ant task. There isn't lots of documentation out there about getting Jetty and JMX working when you are starting Jetty via the builtin Ant task. Here is what I did. I added the jettyXml attribute to the jetty tag like this:
    <jetty ... jettyXml="web/target/main/webapp/WEB-INF/jetty.xml"> ... </jetty>
    My jetty.xml file contains the following:
    <Configure id="Server" class="org.mortbay.jetty.Server">

    <Call id="MBeanServer"
    class="java.lang.management.ManagementFactory"
    name="getPlatformMBeanServer"/>

    <Get id="Container" name="container">
    <Call name="addEventListener">
    <Arg>
    <New class="org.mortbay.management.MBeanContainer">
    <Arg>
    <Ref id="MBeanServer"/>
    </Arg>
    <Call name="start"/>
    </New>
    </Arg>
    </Call>
    </Get>

    </Configure>

    The jetty.xml tells Jetty to start an MBean Server and adding the jettyXml attribute will let Jetty know where to find the jetty.xml file. It seems obvious, but I had to really scour the web to figure that one out. The tricky 'ah-ha' bit is the fact that you can define your jmx stuff in jetty.xml rather than in jetty-jmx.xml, because of course the jetty ant task doesn't have an attribute for jetty-jmx

  2. Spring was silently ignoring my JMX annotations, thus none of my MBeans were being exposed. This took me hours to figure out. Here is the explanation I found buried in the spring JMX docs.
    Do not use interface-based AOP proxies in combination with autodetection of JMX annotations in your bean classes. Interface-based proxies 'hide' the target class, which also hides the JMX managed resource annotations. Hence, use target-class proxies in that case: through setting the 'proxy-target-class' flag on , , etc. Otherwise, your JMX beans might be silently ignored at startup...
    The nub of it is I don't get to use spring's fancy 'ManagedResource' annotations to define and name my MBeans. Instead I have to describe each one in XML. Not a huge deal, but unfortunate. Stupid AOP stuff!
  3. Jconsole, which is the default tool Java gives you for connecting to JMX enabled systems, doesn't work in Ubuntu. Man oh man. If I could have the time back that I wasted before I realized that. You just get a blank window when you connect to your server with Jconsole in Ubuntu. I think the compiz desktop effects are probably the culprit here. Lame.
I spent most of the day dealing with my configuration woes, so I didn't get to work on the interesting part yet which is instrumenting the controllers. I'll post about that if it turns out to be interesting. This post is mostly a "what not to do" post. Hope it helps someone.

1 comment:

Amey Joshi said...

Hi Shlomo,

Can you please post your spring config files? I'm also stuck with this issue of registering MBeans with aop.

I put proxy-target-class="true" with and but no luck. It would really help if you can publish your spring config files.

Thanks,
Amey