Superior app management with JMX

Integrate JMX, a reusable configuration framework, with your JSPs

Let’s face it, configuration management of any application server can be a burden, and most projects don’t even have enough development cycles to include a configuration framework. Java Management Extensions (JMX) to the rescue: Now you have a reusable framework for exposing your application to remote or local management tools. JMX enables you to query the configuration settings and change them during runtime. It also provides other services, such as monitoring, event notification, a timer, and dynamic class loading from XML files. You can use JMX to load, initialize, change, and monitor your application and its distributed components. You can leverage your knowledge of this framework across third-party or your own custom software, creating a consistent approach to managing your applications.

This article will reveal some of JMX’s architecture. The specification is detailed in JSR-000003, and is available for download. You can also download a reference implementation with source code. After exploring JMX internals, we will use a JavaServer Page (JSP) to interface with JMX using JBoss and Tomcat.

JMX revealed

The three JMX layers that are important here are instrumentation, agent, and distributed services.

The instrumentation layer

The instrumentation layer exposes the application as one or more managed beans (MBeans). Each MBean provides access to its state using public methods. An MBean can be any Java object that you modify to support the interfaces and semantics specified in the JMX specification for the type of MBean you create. The MBean types are standard, dynamic, open, and model. A standard MBean provides a static interface. A dynamic MBean exposes its interface to the JMX agent at runtime using metadata. The open MBean is a dynamic MBean that uses predefined Java data types so that dependencies on other classes are reduced, allowing for better runtime discovery and dynamic behavior. The model MBean, as the name implies, is a generic and configurable MBean that is provided with each JMX implementation. You can instantiate and use the model instead of defining your own MBean classes.

The standard MBean is the most common type. As an example, suppose you have a class called Logger that configures application debug messages by specifying a log filename and a verbosity level. You can turn Logger into a standard MBean by creating an interface called LoggerMBean. On this interface, add public setter and getter methods to expose the filename and verbosity attributes. Examples of these methods for the filename attribute would be setFileName() and getFileName(). The method naming convention for setters and getters is based on the setXXX and getXXX method names like in a JavaBean. Completing the puzzle, the Logger class needs to implement the LoggerMBean interface so that the JMX agent can use introspection to create metadata about the Logger MBean. The MBean is managed from the JMX agent by invoking attribute and other operational methods defined in the interface. The MBean is the link between the managed resource (your application) and the rest of the JMX framework.

The agent layer

The JMX agent is the next and most interesting layer. The agent provides remote management application access to all of its registered MBeans; it is the hub for the JMX framework. The agent also provides additional services, such as dynamic loading and monitoring. These services are also registered MBeans, so they can benefit from the framework as well. The core agent component is called the MBean server and is defined by the interface javax.management.MBeanServer. You create the server by invoking the static method createMBeanServer() on MBeanServerFactory. The factory will also keep references of previously created MBean servers, so you will not have to cache them. You retrieve these references by invoking findMBeanServer().

The distributed services layer

The last layer, distributed management services, provides the interfaces and components that remote tools use to interface with agents. Again, the current specification leaves the definition of these interfaces and other functionality to a future version of JMX.

Although brief, this overview should give you a good introduction to JMX and the terminology used to describe it. The example used in this article demonstrates how a JSP page can integrate with the JMX agent to manage configuration parameters.

Tomcat and JBoss setup

Tomcat and JBoss will be used as the application servers, so you must install them first. Here are the steps:

  1. Download Tomcat and JBoss as one distribution bundle from the SourceForge Website. Even if you already have Tomcat, this download can be more convenient because the configuration is already done for you. This example uses JBoss-Tomcat 2.2.1.
  2. Copy tools.jar from your JDK lib directory to Tomcat lib directory. This is needed for compiling JSP pages when running Tomcat embedded within JBoss. An alternative is to add tools.jar to your classpath.
  3. Copy jmxri.jar from the JBoss lib directory to Tomcat’s lib directory. This jar file contains the JMX classes referenced in the JSP page.
  4. Test the server by typing run.bat for Windows or run.sh for Linux from the JBoss bin directory. There is a console message for starting Embedded Tomcat as part of the startup process. Use Ctrl-c to shutdown.

Using JSP

JMX can be interfaced with JSP to provide easy application management. The JSP code in Listing 1 interfaces with the JMX agent, or MBean server, that is inside JBoss. First you need to copy Listing 1 and save it in a file named jmx.jsp in the webapps/admin directory under the Tomcat install root. (Make sure to start JBoss if it isn’t already running and point your browser to

Listing 1: JSP page

<%@ page import="javax.management.*,java.util.*" %> <% try { //Step 1 - Get MBean server reference ArrayList servers = MBeanServerFactory.findMBeanServer(null); if (servers == null) throw new Exception("No MBeanServer found."); MBeanServer server = (MBeanServer)servers.get(0); //Step 2 - Create object to identify MBean ObjectName objName = new ObjectName("DefaultDomain:service=Logging,type=File"); //Step 3 - Update MBean with new log file name String newvalue = (String)request.getParameter("LogName"); if (newvalue != null && newvalue.length() > 0) { Attribute attr = new Attribute("LogName", newvalue); server.setAttribute( objName, attr ); } //Step 4 - Get latest log name attribute String value = (String)server.getAttribute( objName, "LogName"); %>

MBean <%= objName.getCanonicalName() %>

<FORM METHOD="post" ACTION="jmx.jsp"> <TABLE ALIGN="left" BORDER="1" WIDTH="40%" CELLPADDING="3"> <TR> <TH WIDTH="23%"> Attribute </TH><TH WIDTH="35%"> Value </TH> </TR> <TR> <TD><B>LogName</B></A></TD> <TD><INPUT TYPE="text" NAME="LogName" VALUE="<%= value %>" SIZE="34%"></TD> </TR> <TR> <TD ALIGN=LEFT><INPUT TYPE="submit" VALUE="UPDATE"></TD> </TR> </TABLE> </FORM> <% } catch (Exception e) { out.println(e.getMessage()); } %>

As a result of Listing 1, Figure 1 should appear in your browser:

MBean           DefaultDomain:service=Logging,type=File
Attribute Value
LogName
Figure 1. The result of code in Listing 1

Figure 1 shows org.jboss.logging.FileLoggingMBean with an attribute called LogName. This attribute represents the name of JBoss’s log file. First, change the value in the textbox to jbosslog and click the Update button. Then go to the dist/log directory under JBoss where there is a new log file called jbosslog. Clicking on the Update button invokes the setAttribute() method on the MBean server, which delegates the call to setLogName() on the FileLoggingMBean. The MBean server, JBoss, and the JSP page all run inside the same JVM. You can take the same approach with your own applications to start using JMX immediately. All you need to do is create the MBean server, register your MBeans, and then write your JSP page. That is a simple way to add JMX to your existing environment.

An alternative approach is to use the reference implementation’s HtmlAdapterServer class instead of developing your own JSP. It is included with the JMX reference implementation in the jmxtools.jar file. The HtmlAdapterServer is also an MBean. An example of what the page looks like can be seen by starting the JBoss server and pointing your browser to to see all of the managed beans. You can use HtmlAdapterServer like JBoss does, but you may not like the generic format that is presented.

How the code works

The general structure of the page is to integrate with the MBean server in the top part followed by an HTML form. Step 1 retrieves a reference to the server by invoking the static method findMBeanServer(null) on MBeanServerFactory. Passing a null parameter means that you want all the servers known by the factory. We only expect and assume one from JBoss. When using the MBean server interface, you have to identify which MBean to send messages to.

In Step 2, an ObjectName class is instantiated with the canonical MBean name passed into the default constructor. The pattern for the canonical name is the domain, which can be DefaultDomain or a custom domain, followed by property value pairs separated by commas. You need at least one property value pair. The format is: [domainName]:property=value[,property=value]*.

Step 3 is for updating FileLoggerMBean with the new log filename that was posted to the JSP page. You do that by creating a JMX Attribute object with the attribute name and value passed into the constructor. Then invoke the setAttribute() method on the MBean server passing in the Attribute and ObjectName parameters. These parameters identify which MBean to interact with, the attribute, and the associated value. The setAttribute() method will use MBean metadata stored inside the server to invoke the appropriate setter method on the MBean.

Step 4 retrieves the attribute value from FileLoggerMBean. You invoke getAttribute() method using parameters ObjectName and the attribute name as a String. You need to typecast the returned object to what the getter method returns, as defined in the FileLoggerMBean interface.

JMX services

JMX does much more than provide a framework for remote management. It provides additional services that can become the core part of your development effort. Here is a brief list of additional features:

  • Event notification: Interfaces are provided to notify broadcasters and listeners of events, such as an attribute change. This allows MBeans to communicate with other MBeans or the remote manager about state changes.
  • Monitor service: Monitor MBeans can send event notifications to registered listeners. A listener can be another MBean or management application. The target attributes observed can be a counter, gauge, or string.
  • Timer service: The timer MBean will send notifications to registered listeners based on a specific date or time interval.
  • M-let service: The m-let service can instantiate and register MBeans with the MBean server. The list of MBeans and their class names are defined in an m-let file using MLET tags. A URL specifies the location of the m-let file.

Conclusion

JMX is a relevant and useful framework for your applications. I hope by reading this introduction you’re excited about using it. The architecture is flexible enough to implement into your application and development environment. By including this new standard, you can bring consistency to your J2EE applications and improve software quality.

Todd Bowker is a Java software engineer
located in Salt Lake City, Utah. Todd has been programming for more
than 10 years and is an alumni of Oregon State University.
Currently he is involved in engineering ecommerce and open source
applications using J2EE standards, proving that Java can be used to
deploy enterprise object-oriented applications.

Source: www.infoworld.com