One of the pleasant surprises in the wonderful world for J2EE (and J2SE since the Tiger Release) is JMX. It may sound complex: a not so easy acronym, targeted at management, nothing to do with web development – JMX did not fly from the very beginning (J2EE 1.4, JSR-3). However, gradually, with JMX support in J2SE, MBean support in Spring and more ideas about how to make use of JMX, its popularity was increasing.
One of the sessions I visited today was on JMX, and while I already had some understanding of what it is, the session put a smile on my face. Not in the least because of the very pleasant presenters by the way, from Sun’s Grenoble office: Eamonn McManus and Jean-François Denise.
Half of the audience confessed to be ‘deeply involved’ with JMX. For the rest of us, the introduction was useful. One of the most visible and widely spread usages of JMX is the JVM instrumentation that is available since J2SE 5 as part of Sun’s JVM. This basically means that the JVM publishes a lot of information about its internal management of memory, threads, classloading, garbage collection etc. in the form of MBeans – the information carriers in JMX. These MBeans can be "consumed" by JMX clients, such as JConsole – a desktop client shipped with J2SE. JConsole connects to the MBeans in the JVMs running on the same machine. JConsole can connect to any running Java process.
In JConsole, the available MBeans can be inspected directly, for example at java.lang.ClassLoading. JConsole also has several prettier UI pages that turn the raw information from the JVM MBeans into charts and other easier-to-the-eye displays.
The JVM is an example of an application that does not itself have a User Interface: for such applications, MBeans are an alternative way of making information available to external clients. Note that this does not have be "management" information, if you have a use case for it, it could also be information about business events taking place in the applications. A JMX consumer could suck such events into an EBS infrastructure for example. Or publish them as an RSS feed. Also applications that do have a UI can still benefit from JMX for information not available through the user interface. Web Applications can use JMX for example to publish information from the Business Tier. Also note that MBeans do not only publish information. MBeans can have:
– properties (can be read only as well as open for modification)
– operations (to be invoked)
– notifications (to be produced for specific situations)
Via JConsole, we can inspect and interact with our own MBeans as well as set any properties and invoke operations. The steps to JMX enable our applications, for example as a way to add instrumentation or a way to change run-time characteristics without restarting the application:
– add JMX agent (MBean Server; this server is exposed a managed component)
– develop special managed objects: MBeans (standard MBean: implementing an interface whose name ends with MBean (standard naming pattern) with a class named after the interface without the MBean suffix
– register MBean with MBeanServer (svr ManagementFactory.getPlatformServer();
– get handle on server (svr ManagementFactory.getPlatformServer(); )
– create instance of MBean
– create instance of ObjectName
– register MBean with ObjectName in MBeanServer (svr.registerMBean(instance of MBean class, ObjectName))
– making the JMX agent connectable (hooking up JConsole to the application)
– link them to the application (the MBeans need a handle on application objects to get at data and perform operations)
– and expose (data and operations and notification)
– connect with remote manager (JMX consumer)
– remote manager can invoke operations
A simple and effective demo demonstrated a CacheControl MBean. It publishes properties (size of the cache as well as the number of elements it currently contains) of which the first one can be changed. The MBean publishes notifications (every time the cache is full and a new element is added to it). In JConsole, the MBean can be inspected, the cachesize can be polled and displayed in a chart(graph it). The cache size can be changed from JConsole. The notifications published by the MBean can be consumed by any JMX Client, such as JConsole.
A new element for JMX in Java 6 is called MXBeans. They are basically the same as standard MBeans, except for the way they deal with properties not based on simple Java types such as String and Integer: it provides a way to map from custom classes to Maps of simple types (it sounds a bit JSON like?).
To expose an application’s MBeans, with Java 5 we have to run the application with a system property: Dcom.sun.management.jmxremote. In Java 6, it just works: nothing extra is required. Note that we can use later version of JConsole (the version shipped with JDK 6 for example) to connect to a JVM 1.4 or 5. JConsole Lists local VM processes as well as it provides the ability to connect to a remote JVM.
Many commercial products understand JMX (HP OpenView, BMC Patrol, IBM Tivoli, SAP CCMS; mainly for managing AppServer. All J2EE application servers come with JMX (added to J2EE 1.4, but even before that). Numerous open source projects around JMX (eg. over 40 JMX focused projects in SourceForge),including MX4J, MC4J – configurable JMX API console, jManage – web based MBean browser, OpenDMK (discovery, cacading between JMX servers??)
A very interesting project is GlassBox. It is based on Spring, and uses AspectJ to insert timing measurements into any application at runtime ; measurements exposed as MBeans. This means that we can add profiling capability to applications without built in instrumentation, by intercepting calls to key objects and have those calls push timing details to MBeans that can in turn expose them to a JMX Client. I have not seen it before today, but it looks very very interesting. See http://www.glassbox.com/glassbox/Home.html for more details.
JMX 2.0
The JMX API 2.0 (Java 7) is in the works. Its focus: scalability (e.g support for distributed systems, large number of MBeans). The other main focus: Ease of Use. Some elements of JSR-255:
- Cascading of MBean Servers: Import mbeans to master mbeanserver, client connect only to master mbean server (that itself imports remote servers).
- Support for locales: passing client locale to MBean
JSR-262 Web Services Connector: define a way for JMX clients to access MBeans powered application across WS. This allows access to MBeans through firewalls and also have non-Java clients connecting into MBeans. (in practice: change service:jmx:rmi:// to service:jmx:ws://host:port/http-context). Java Types XML Serialization included. WS-Management, SOAP 1.2 based. Note: MBeans can be published by hardware appliances (printer, router,…).
An early access release of the Reference Implementation for this JSR is available at: http://ws-jmx-connector.dev.java.net (Java 5 or Java 6) (JAX-WS 2.1, based on WiseMan: OSS of WS-Man Stack).
Some questions…
I am wondering whether an MBean inside an applet can be contacted from a JMX Client on the client machine running the browser that contains the applet. Does the applet has to be signed? Is it not possible at all? Or do we have channel between applet and client machine, potentially even between HTML and JavaScript via Applet to the local machine.
Can we easily feed JMX Notifications into a JMS Queue (or Topic) and/or such them into an ESB infrastructure?
Could it make sense to publish Notifications throu
gh an RSS feed?
How far w
ould one go with Business oriented information and JMX? And setting application characteristics via MBeans: application meta-data, business logic configuration parameters, live management of domains, feeding current settings such as currency exchange rates etc.
Is Log4J JMX enabled in a sense that we can dynamically change the logging levels for our loggers – through an MBean – rather than changing the config file and restarting the application?
Could you use JMX and MBeans as a interaction interface from within the application. For example: applicationis running a background job, needs user input, sends a notification, users fires up some UI and through that UI makes the necessary updates to MBean properties and invokes the Approve/Continue/Done or Reject operation on the MBean. Or could JMX and MBeans be a tandem to connect a rules engine to an application?
Creating Manageable Systems With JMX, Spring, AOP, and Groovy
A subsequent presentation on JMX, titled Creating Manageable Systems With JMX, Spring, AOP, and Groovy by Vladimir Vivien, drew a large crowd (of course with this title, you can please a lot people). This was also a very interesting, clear presentation. Vladimir argued that most Java applications are like cars without instruments: no runtime visibility, black box, no way of seeing the run time application state. His goal was to convince his audience that using JMX (and Spring with AOP), it is straightforward to instrument every Java application, without impact on the application itself.
He said: We have to move beyond log-files: you need an earlier response from the application. You only check a logfile when an incident already has happened. Our administrators need the ability to monitor (perhaps even feed into BAM?) application events as they happen. And manage operational parameters on the fly.
Using Spring to expose MBeans
By pairing up JMX and Spring, JMX enabling an application becomes much easier and with less (or even any) impact on the application. Spring has extensive support for JMX: publish POJOs as MBeans – no special interface or naming convention or use the MBeanInfoAssemblerAPI in combination with Class annotations that describe which classes to expose as MBeans: Automatically registers beans as MBeans that have the @ManagedResource annotation.
One of the many things Spring can do to beans it instantiates is publish them as MBeans. The example GreetingService class we saw before can be turned MBean by Spring like this:
public class GreetService { // no longer need to implement an MBean interface
public void setLanguage(String lang){...}
public boolean start() {...}
public void stop(int val) {...}
}
<bean id="greetSvc" class="demo.GreetService"/>
<bean id="exporter"
class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="demo.service:type=Greet ..."
value-ref="greetSvc"/>
</map>
</property>
</bean>
or, using the MBeanInfoAssemblerAPI we can do it as follows:
@ManagedResource(objectName="demo.service:type=Greet ...")
public class GreetService {
@ManagedAttribute
public void setLanguage(String lang){...} ...
// other methods left out
}
Spring bean-config that creates bean greetSvc based on class demo.GreetService and exposes it as an MBean, using the annotations in the class fot determine the ObjectName and the attributes to expose:
<bean id="greetSvc" class="demo.GreetService"/>
<bean id="attribSrc"
class="...export.annotation.AnnotationJmxAttributeSource"/>
<bean id="exporter" class="...export.MBeanExporter">
<property name="autodetect" value="true"/>
<property name="assembler">
<bean class="...export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="attribSrc"/>
</bean>
</property>
</bean>
Using AOP (and Spring) we can indirectly publish objects as MBeans that do not have to be aware of it. No need to implement an MBean interface or contain annotations. Just POJOs that by some external trick (AOP) are changed when instantiated. By applying aspects to the beans that we want to expose (indirectly), we can for example intercept business calls, aggregate business information and push that information out to MBeans.
public class GreetService { // no longer need to implement an MBean interface or provide annotations
public void setLanguage(String lang){...}
public boolean start() {...}
public void stop(int val) {...}
}
// The Aspect we will apply
public class GreetingAspect {
private GreetingMbean mbean;
public void beforeGreeting() {...}
public void afterGreeting() {...}
}
The required Spring Configuration to have the GreetingAspect applied to the greet() method of any instance of class demo.GreetServer:
<bean id="aspectBean" class="demo.GreetAspect">
<property name="mbean" ref="OneGreetingMBean"/>
</bean>
<aop:config>
<aop:pointcut id="myPointCut"
expression="execution(* demo.GreetServer.greet(..)) "/>
<aop:aspect id="aspect" ref="aspectBean">
<aop:before pointcut-ref="myPointCut" method="beforeGreeting"/>
<aop:after pointcut-ref="myPointCut" method="afterGreeting"/>
</aop:aspect>
</aop:config>
The aspect applied is based on the aspectBean – instantiated from the demo.GreetAspect class. It is to be applied as a Before and After method interceptor.
The GreetingAspect has an MBean injected. The beforeGreeting and afterGreeting methods in the Aspect can send any information – for example timing of the duration of the method call or the values of the parameters – to that MBean.
Notification
MBeans can send out notifications, asynchronous messages that typically signal a special situation (or just the latest state of the data someone may be interested in). The MBean server broadcasts numerous events. Your MBeans can broadcast/listen for events and management tools (JMX clients, MBean consumers) can subscribe to notifications. There are some interfaces involved with JMX Notifications: Notication, NotificationBroadcaster, NoticationListener, NoticationFilter. The Notification interface defines properties such as : type, objectname, sequence, timestamp, string message, broadcaster supplied data object (payload). You register a listener to handle special types of Notifications.Event broadcasters pass an instance of a
class implementing this interface to event listeners.
public class MyTimer extends javax.management.timer.Timer{}
public class TimerLstnr implements NotificationListener{
public handleNotification(Notification n, Object obj){...}
}
... in some class
public void registerListener throws Exception{
// get the notification broadcaster going
demo.MyTimer timer = new demo.MyTimer();
Notification n = new Notification("timer.heartbeat", null, new Date(System.currentMillis()));
timer.setNotification(n);
timer.setPeriod(3000);
// now instantiate a listener for the JMX Notification broadcast
NotificationFilterSupport f = new NotificationFilterS...// set some sort of filter
f.enableType("timer.heartbeat");
TimerLstnr lstnr = new TimerLstnr();
// add the listener to the JMX broadcaster
timer.addListener(lstnr,f,null);
}
Alternatively, the configuration of a JMX Notification Listener can be done in Spring:
<!-- get the broadcaster going -->
<bean id="myTimer" class="demo.MyTimer">
<property nameâ€period†value=â€3000â€/>
</bean>
<!-- register an instance of demo.TimerListener as a notificationListener for the myTimer broadcaster -->
<bean id="exporter" class="...export.MBeanExporter">
<property name="beans">
<map>
<entry key="jmx.timer:type=Timer" value-ref="myTimer"/>
</map>
</property>
<property name="notificationListenerMappings">
<map>
<entry key="jmx.timer:type=Timer">
<bean class="demo.TimerLstnr"/>
</entry>
</map>
</property>
</bean>
The presentation went on to show how instead of using a Java Class to process notifications, we can also use a Groovy Bean. The interesting bits here – to me at least – were not so much the use of Groovy in this particulare case, as well as the support for Groovy in Spring (that I had missed out on thusfar). Spring 2.0 can instantiate beans that are actually Groovy based (as well as JRuby and BeanShell beans):
<beans>
<!-- instantiate a bean called action based on the Groovy GAction class
<lang:groovy id="action" refresh-check-delay="5000"
script-source="/META-INF/script/GAction.groovy">
<lang:property name="value" value="RUN"/> <!-- pass a property to the bean -->
</lang:groovy>
<bean id=â€listener†class=â€demo.GreetingListenerâ€>
<property name=â€actionâ€>
<ref bean=â€actionâ€/>
</property>
</bean>
</beans>
Note: the Groovy class needs to implement (extends in Groovy terms) a Java Interface, as Java cannot otherwise deal with the dynamic typing of Groovy.
Groovy was used in this demo as a dynamic language to agile-ly (what is the adverb for agile? does it exist?) adapt to business changes (in bussiness conditions and requirements). Among the dynamic (scripting languages), Groovy qualified best as it integrates well with Spring, can be described as " Agile dynamic language for the Java platform inspired by Python, Ruby, and Smalltalk…" and it compiles directly into Java bytecode which means that Groovy scripts can import Java objects (and vice versa)
Hi,
Can you tell me where exactly JMX is used in fusion middleware?
Thanks
Santosh
Jeroen,
I had forgotten about that article. It is pretty good actually! You were way ahead of me in describing the possibilities of using JMX as well as the combination with Spring. Seems that I do not have to travel to San Francisco to learn interesting things, I can just ask my colleagues. Can you/we do session on JMX sometime on an AMIS Academy or KC session? There seem to be so many opportunities for using JMX (now that I have the solution, I can think up a substantial number of problems that it can solve).
Have you looked at Glassbox? That really looks interesting!
Lucas
“Is Log4J JMX enabled in a sense that we can dynamically change the logging levels for our loggers – through an MBean – rather than changing the config file and restarting the application?”
Log4J should be JMX enabled, but I think it is still not production ready. However, there is a way that you can change the logging levels while your application is running. I even tried it and wrote a blog entry about it: http://technology.amis.nl/blog/?p=1238
The article also handles the MBeans in Spring, but without annonations.