1.What is JMX architecture?
First, let's get a overview of the JMX architecture, it contains three layers as below:
- Instrumentation Layer: This layer only contains the manageable resources which might be property files or printer,fax device. Actually, no matter what the resources are, they are only applications,let's think about how we get access to these resources first, thro applicactions, isn't it?When we have this in common that the manageable resources are indeed applications, let's check what jmx can give us in this layer. In JMX's programmable world, this layer only contains two things: one is the MBean which is equal to the manageable resources,applications, the other is its corresponding MBean interface. As mentioned above, MBean is actually the original applictions, and its corresponding MBean interface is used to expose a set of manageable interface to the outside world, tell them what they can do on this manageable resources.
- Agent Layer:Agent right here is like a container, the main thing in a agent is that, a MBeanServer, MBeanServer is used to hold the manageable resources, that is MBean. And besides that, agent layer also provide four typical services, they are timer service, dynamic loading manageable resources service, relationship service and the monitoring service, we will cover these four services later, but not here. Usually, agent used to be in the same machine with the manageable resources, what agent can do is providing a way to manage the resources.
- Distributed Layer: After preparing the manageable resources and hold them in a MBeanServer,and then how can a client get access to them. Well, Distributed Layer will do things that would make agent layer availabel to the clients by adapter or connector, as the above picture shows. In brief,Distributed Layer is the outermost layer and make manageable resources accessible. It contains two types of interaction (as I said before, adaptor and connector), which allow client to connect to the agent layer.
2.Ready for our first example?
In order to help you better understand the above concepts, I will show you an example to tie these three layers together,but before diving into this example, we need to visist a jmx friend first, that is ObjectName, ObjectName is a naming system in jmx's world. It is just like the ID card in our world which is unique, it consists of two parts:
1.Domain Name: domain name is used to group the Mbeans register in a Mbean Server. Just for convinience, nothing else.
2.Key-Value pair: only provide descriptions for registered mbeans, such as ‘name=HelloWorld, this dont have to be the actual attribute the mbean has. And there is something we need to know is that this key-value pair will also be used to distinguish from other mbeans when their domain name is identical.
Ok,now let's come to our example, I dont want to use the common HelloWorld example, and here, I want to show you a more realistic example-the logging example.
Many of us have ever ran into this situation that is we got a problem on production environment and we can't reproduce it on development environment, and as we know, we can't get the enough log information from production environment due to its higher log level. In such a case, we need to change the log level to get enough log info, of cource, restarting the server is necessary. But as you know, it is almost impossible to restart the production server to trace problems like that. So, what can we do? Dont worry, JMX come to your rescue.
First,let's check our manageble resource,
public class LogManager implements LogManagerMBean{
private static final String LOG_PATH = "log.properties";
private static final String LOG_LEVEL="logLevel";
private static final String DEBUG="debug";
private static final String INFO="info";
private final Properties content = new Properties();
public LogManager() throws Exception {
InputStream is = LogManager.class.getResourceAsStream(LOG_PATH);
content.load(is);
}
public String getLogLevel()
{
return content.getProperty(LOG_LEVEL);
}
public void setLogLevel(String value)
{
content.setProperty(LOG_LEVEL, value);
}
public void printLogInfo()
{
String logLevel=getLogLevel();
if(logLevel.equals(INFO))
System.out.println("[info]: welcome jmx's world.");
else if(logLevel.equals(DEBUG))
System.out.println("[debug]: welcome jmx's world.");
else
System.out.println("[warn]: welcome jmx's world.");
}
}
and then is our MBean interface, which determines what operations client can do on the manageable resource.
public interface LogManagerMBean {
public void setLogLevel(String value);
public void printLogInfo();
}
From the above MBean interface, we can see that client can change the log level of logger on-the-fly.
Note: printLogInfo() method only stimulate the usage of logger, since i dont want to introduce a complex example at your first glance of JMX application.
The last will be our agent:
public class Agent {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
//new a MBean server
MBeanServer server=MBeanServerFactory.createMBeanServer("Hello");
//new a manageable resource and register it in the server
LogManagerMBean logManager=new LogManager();
ObjectName logManagerName=new ObjectName("Hello:name=logManager");
server.registerMBean(logManager, logManagerName);
//new a adaptor and register it in the server
HtmlAdaptorServer adaptor=new HtmlAdaptorServer();
adaptor.setPort(8888);
ObjectName adaptorName=new ObjectName("Hello:name=adaptor");
server.registerMBean(adaptor, adaptorName);
//start the adaptor
adaptor.start();
}
}
The above are all codes we need, it is easy,isnt it?
When we done that, let's start our agent- java Agent, can connect to it thro our web browser(IE or FireFox etc) by using the url:
http://localhost:8888
You can get a view like this:
Before we change the log level, the log info would be like the following:
And then change the log level to 'debug':
Then let's check out the log info again:
Wow, we got it.