Advertisements
In this section, we will see how to use JMX API without the support of Spring. After exploring this sample, readers will be able to understand the pain involved in writing a simple monitoring system that involves lot of boiler-plate code. Here comes a simple logger service which will store the log string to be logged. The string to be logged will be stored as an attribute. There is an operation for logging the log string called log()
.
Logger Service
LoggerService.java
package net.javabeat.spring.articles.jmx.log;
public class LoggerService {
private String logString;
public String getLogString() {
return logString;
}
public void setLogString(String logString) {
this.logString = logString;
}
public void log(){
System.out.println(logString);
}
}
JdkMainLog
The JdkMainLog does a lot many things. As part of the initialization process, it creates an instance of logger service that will be monitored by the MBean server. Then, for encapsulating the object name we give a description name to logger service by using ObjectName
class. Next our logger service is wrapped into an appropriate model bean through RequiredModelMBean
. Note that the logger service object is wrapped when a call is made to setManagedBean()
defined on RequiredModelMBean
object. The second argument to the method provides an indication on the type of the object to the MBean Server. Here the type is set to objectReference
. Other possible types could be RMIReference
, EJBHandle
etc.
A call to getPlatformMBeanServer() returns the implementation of MBeanServer that ships with the JDK Platform. Now, if you look into the class definition of logger service we can see that there is a single attribute called logString
and two operations getLogString()
and setLogString()
. The attribute logString
is encapsulated through ModelMBeanAttributeInfo
by passing the necessary properties such as the name
, description
, type
etc. Similarly for encapsulating the methods getLogString()
and setLogString()
, the class ModelMBeanOperationInfo
comes into picture for encapculating them as managed operations. Finally the managed attribute and the managed operations are encapsulated as ModelMBeanInfo
object which is then registered to the Platform MBean by calling registerMBean()
method.
After running the program, the Platform MBean Server will be started and the MBean object will be registered. A client application such as jConsole (which will be located in JDK_HOME/bin
directory) will be needed to connect to the server.
JdkLogMain.java
package net.javabeat.spring.articles.jmx.log.jdk;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import javax.management.Descriptor;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.modelmbean.DescriptorSupport;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import javax.management.modelmbean.RequiredModelMBean;
import net.javabeat.spring.articles.jmx.log.LoggerService;
public class JdkLogMain {
public static void main(String[] args) throws IOException {
LoggerService logService = new LoggerService();
try {
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
ObjectName objectName = new ObjectName("bean:name=logService");
RequiredModelMBean mbean = new RequiredModelMBean();
mbean.setManagedResource(logService, "objectReference");
Descriptor logStringDescriptor = new DescriptorSupport(new String[] {"name=logString", "descriptorType=attribute",
"getMethod=getLogString", "setMethod=setLogString" });
ModelMBeanAttributeInfo logStringAttribute = new ModelMBeanAttributeInfo(
"logString", "java.lang.String", "String to be logged", true, true, false, logStringDescriptor);
ModelMBeanOperationInfo getLogStringOperation = new ModelMBeanOperationInfo(
"Get the log string", LoggerService.class.getMethod("getLogString"));
ModelMBeanOperationInfo setLogStringOperation = new ModelMBeanOperationInfo(
"Set the log string", LoggerService.class.getMethod("setLogString", String.class));
ModelMBeanInfo mbeanInfo = new ModelMBeanInfoSupport("LoggerService", "Logger Service",
new ModelMBeanAttributeInfo[] {logStringAttribute}, null,
new ModelMBeanOperationInfo[] {getLogStringOperation, setLogStringOperation},null);
mbean.setModelMBeanInfo(mbeanInfo);
mbeanServer.registerMBean(mbean, objectName);
}catch (Exception e) {
e.printStackTrace();
}
System.in.read();
}
}
JMX with Spring
Now we will see how to monitor the same logger service through Spring. There won't be much coding involved in exposing the Logger Service as a managed bean though there will some wiring involved between beans in a Spring configuration file. Have a look at the following configuration file.
Spring Config
<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">
<bean id="logService" class="net.javabeat.spring.articles.jmx.log.LoggerService" />
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=logService" value-ref="logService"/>
</map>
</property>
<property name="server" ref="mbeanServer"/>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
</bean>
</beans>
The most important points to note in the above declaration is the use of MBeanExporter
and the MBeanServerFactoryBean
classes. Firstly, MBeanExporter
class is used to export the given objects as managed JMX Beans into the MBean Server. Note that the fully qualified class is org.springframework.jmx.export.MBeanExporter
. It has a property beans
that specifies the list of object to be exported as beans. In our case, it is only the logger service object. Note that key is bean:name=logService
which will internally be used as the object name for the managed bean instance. The next property for the MBeanExporter
is the server
property which denotes to which server the beans have to be exported. It happens to be an instance of org.springframework.jmx.support.MBeanServerFactoryBean
which internally uses javax.management.MBeanServerFactory
class for creating the MBeanServer
object.
SpringLogMain
SpringLogMain.java
package net.javabeat.spring.articles.jmx.log.spring;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringLogMain {
public static void main(String[] args) throws Exception{
new ClassPathXmlApplicationContext("log.xml");
System.in.read();
}
}
The main class is very simple as it initiates the object creating process by simply loading the context containing the very spring beans.