Introduction

The latest and greatest Java CAPS 6 has a management and Monitoring API exercisable from any language that supports JSR 223 scripting for the Java platform. Currently this includes 25 different scripting languages, including Groovy, JRuby, Jython, JACL, etc.

I still have a lot of projects with Java CAPS 5.1 therefore I decided to investigate if I can already create monitoring scripts with release 5.1. The answer is yes and monitoring scripts provide a lot of flexibility and features for Java CAPS 5.1

Investigate with the Web based JMX Console

The web based JMX console is accessible using the URL http://localhost:18000/jmx-console
The user name is Administrator. It looks like this. It is possible to look at all MBeans with their attributes and methods. But it is not practical at all when I want to query an MBean repeatedly.

Enabling the JMX agent

In order to query the JMX server programmatically we need to enable the JMX agent.
  • Open the domain.xml located in <JCAPS_DIR>\logicalhost\is\domains\domain1\config
  • Locate the <java-config> tag and add the following options:
            <jvm-options>-Dcom.sun.management.jmxremote=true</jvm-options>
            <jvm-options>-Dcom.sun.management.jmxremote.port=9877</jvm-options>
            <jvm-options>-Dcom.sun.management.jmxremote.authenticate=false</jvm-options>
            <jvm-options>-Dcom.sun.management.jmxremote.ssl=false</jvm-options>
    
    You can get more details about these options in the Java SE documentation
  • Restart the domain

    Investigate with Java

    A Java client for the JMX protocol is bundled with the Java platform itself. To write a JMX client there is no additional JMX library to import. It is also not required to have the same Java version in the client. Java CAPS 5.1 runs on Java 1.5 and you can write a JMX client in Java 6. This code is a crude example which 1/ connects to the JMX server 2/ lists all MBeans in the server.

    As I was writing this code I was thinking that there are too many loops, Iterators and dynamic code. The MBeans are objects but they do not appears as Java objects in the Java code. That is to say, to get the attribute of an MBean, I cannot just use the notation "object.attributeName". I need to the cumbersome getAttribute() method. Similarly, to invoke a method of an MBean I need to use the invoke() method and pass arguments as arrays. In short I was thinking that I needed a more dynamic language. I found my source of inspiration in the Groovy and JMX page

    Install Groovy

  • Download and unzip Groovy. I am using groovy-binary-1.5.6.zip.
  • in groovy/lib remove mx4j.jar because it would conflict with the standard JMX library

    Investigate with Groovy

    The following script lists all MBean in the server. It is equivalent to this Java code
    import javax.management.ObjectName
    import javax.management.remote.JMXConnectorFactory as JmxFactory
    import javax.management.remote.JMXServiceURL as JmxUrl
    
    def serverUrl = 'service:jmx:rmi:///jndi/rmi://localhost:9877/jmxrmi'
    def server = JmxFactory.connect(new JmxUrl(serverUrl)).mBeanServerConnection
    
    server.queryNames(null, null).each{ name -> 
    	def mbean = new GroovyMBean(server, name)
    	println mbean
    	println "-----------------------"
    }
    
    This demonstrates the benefits of the "each" Groovy looping. It replaces a lot of Iterators and casts.

    The following code demonstrates how to get the memory usage of the Application server in real time.
    import javax.management.ObjectName
    import javax.management.remote.JMXConnectorFactory as JmxFactory
    import javax.management.remote.JMXServiceURL as JmxUrl
    
    def serverUrl = 'service:jmx:rmi:///jndi/rmi://localhost:9877/jmxrmi'
    def server = JmxFactory.connect(new JmxUrl(serverUrl)).mBeanServerConnection
    
    def query = new ObjectName('java.lang:type=Memory')
    String[] allNames = server.queryNames(query, null)
    if (allNames.size()==1) {
    	memoryBean = new GroovyMBean(server, allNames[0])
    	memoryBean.HeapMemoryUsage.contents.each { item ->
    		println item.key + ": " + (item.value/1024/1024) + " MB"
    	}	
    }
    
    /* Example output:
    committed: 80.34375 MB
    init: 0 MB
    max: 989.875 MB
    used: 40.3523330688 MB
    */
    
    
    There are a lot of useful things I can do on top using this simple script as a base:
  • wrap inside a loop and collect the memory usage into a file for reporting
  • send an alert when a given threshold is reached
  • call the gc() method to force garbage collection. To call a method of an MBean from Groovy is as simple as adding:
    memoryBean.gc()
    The GroovyMBean figures dynamically how to invoke the appropriate JMX method.

    Next steps

    I barely scratched the surface of the available JMX MBeans in Java CAPS 5.1. There are a lot of interesting MBeans for example "type=Threading" gives a lot of information on the threads. There are also a lot of MBeans created with eGate and eInsight projects. But investigating these ones will have to wait another blog entry.
  • Comments:

    Post a Comment:
    Comments are closed for this entry.

    This blog copyright 2009 by Eric Lerognon