The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

JMX::Jmx4Perl::Agent::Protocol - j4p agent protocol specification

DESCRIPTION

This document defines the protocol format for exchanging informations between the Java-Agent j4p.war running in a Java Application Server and the Perl module JMX::Jmx4Perl::Agent which is used on the client side. The communication is based on HTTP as the transport protocol and hence follows a request-response paradigmn. The request is performed by doing a simple restfule GET HTTP request where the request information is part of the URL itself. The response returned by the agent uses JSON for the data representation. Both, the request URL format and the JSON format of the response are described below.

VERSION

This document describes Version 0.20 of the j4p agent protocol. This is the initial version.

REQUEST

Jmx4perl uses a restful style for the request, which essentially is a single URL without additional parameters for specifying the request. For this to work, the URL is divided into parts separated by /. In general, the request URL looks like

 <base-url>/<mode of operation>/<operation specific parameter>/..../

The <base-url> specifies the URL under which the j4p agent is accessible in general. It typically looks like http://localhost:8080/j4p, but depends obviously on your deployment setup. Normally, the last part of this URL is the name of the deployed Webapplication, which by default is based on the filename j4p.war. <mode of operation> specifies one of the supported operations after which operation specific parameters follow.

The supported operations are described now in the following sections.

read

Mode used for reading an JMX attributes. The operation specific parameters have the following format.

  <mbean name>/<attribute name>/<inner path>
mbean name (mandatory)

The canonical name of the MBean for which the attribute should be fetched. Please refer to the JMX documentation for the definition of a canonical name. In short, it contains two parts: A domain part and a list of properties which are separated by :. Properties themselves are combines in a comma separated list of key-value pairs.

Example:

 java.lang:type=Memory
 java.lang:name=Code Cache,type=MemoryPool
attribute name (mandatory)

This is the name of the attribute which is requested.

Example:

 HeapMemoryUsage
 SystemProperties
inner path (optional)

This is an optional part which specifies an inner path within the attribute's type. j4p agent knows how to serialize certain complex data types with JSON, i.e. collections and CompoundData. Please refer to the next section for more details about JSON serialization. An inner path can be used to specify a certain substructure (plain value, array, hash) within the returned complex attribute value. Think of it as something like "XPath lite". This is best explained by an example:

The attribute HeapMemoryUsage of the MBean java.lang:type=Memory can be requested with the URL

  http://localhost:8080/j4p/read/java.lang:type=Memory/HeapMemoryUsage

which returns a complex JSON structure like

 {
   "committed" : 18292736,
   "used" : 15348352,
   "max" : 532742144,
   "init" : 0
 }

In order to get to the value for used heap memory you should specify an inner path used, so that the request

 http://localhost:8080/j4p/read/java.lang:type=Memory/HeapMemoryUsage/used

results in a response of

 15348352

If the attribute contains arrays at some level, use a numeric index as part of the innerpath if you want to transverse into this array.

write

Writing an attribute is quite similar to reading, except that the URL takes an additional value element:

   <mbean name>/<attribute name>/<value>/<inner path>
mbean name (mandatory)

The MBean name as described above (see "read" for details)

attribute name (mandatory)

The attribute name (see "read" for details)

value (mandatory)

The value to set in its string representation. Note, that only values can be set, which have one for the following types:

String
Integer / int
Long / long
Boolean / boolean
inner path (optional)

An optional inner path for specifying an inner object on which to set the value. See "read" for more on inner pathes.

For example, you can set the garbage collector to verbose mode by using something like

  http://localhost:8080/j4p/write/java.lang:type=Memory/Verbose/true

exec

With this mode, you can execute a JMX operation on a target MBean. The format of this looks like

  <mbean name>/<operation name>/<arg1>/<arg2>/....
  
mbean name (mandatory)

The MBean name as described above (see "read" for details)

operation name (mandatory)

Name of the operation to execute

arg1, arg2, ...

String representation for the arguments required to execute this operation. Only certain data types can be used here as desribed for the "write" mode.

For example, to execute a garbage collection you use

  http://localhost:8080/j4p/exec/java.lang:type=Memory/gc

This mode is used to query for certain MBean. It takes a single argument for specifying the search parameter like in

   http://localhost:8080/j4p/search/*:j2eeType=J2EEServer,*

You can use patterns as described in http://java.sun.com/j2se/1.5.0/docs/api/javax/management/ObjectName.html, i.e. it may contain wildcars like * and ?. The Mbean names matching the query are returned as a list within the response.

list

The list operation allows you to get information about the accessible MBeans. This information includes the MBean names, their attributes and operations along with type information and description (as far as they are provided by the MBean author which doesn't seem to be often the case).

A list-request can take these specific, optional, parameters

  <inner path>
inner path (optional)

The inner path, as above, specifies a subset of the complete response. You can use this to select a specific domain, MBean or attribute/operation. See below for the format of the complete answer.

Escaping

If you are forced to use a slash (/) as part of your request (e.g. as part of you bean's name) you need to escape it. A single slash (/) is escaped by the combination /-/, two subsequent slashes (//) are to be escaped with /--/ and so on. For example, to request the atrribute State on the MBean named jboss.jmx:alias=jmx/rmi/RMIAdaptor, you should an URL like

  .../read/jboss.jmx:alias=jmx/-/rmi/-/RMIAdaptor/State

JMX::Jmx4Perl::Agent does this sort of escaping transparently. If the part (e.g. MBean's name) ends in a slash you need to use a + instead of a minus, so the j4p agent can combine parts properly. The corresponding perl code for creating such a format looks like

  $input =~ s|(/+)|"/" . ('-' x length($1)) . "/"|eg;
  $input =~ s|-/$|+/|; # The last slash needs a special escape

You might wonder, why simple URI encoding isn't enough for escaping slashes. The reason is rather simple: JBoss/Tomcat has a nasty bug, which returns an HTTP response HTTP/1.x 400 Invalid URI: noSlash for any URL which contains an escaped slash in the path info (i.e. %2F). Other appservers might croak as well, though not test. Try it yourself!

RESPONSE

As already mentioned, the response is an HTTP response containing a JSON payload. This section describes the format of the retuned answer, depending on the operation mode. In general, two kinds of responses can be classified: In the normal case, a HTTP Response with response code 200 is returned, containing the result of the operation as a JSON payload. In case of an error, a 4xx or 5xx code will be returned and the JSON payload contains details about the error occured.

In the non-error case, the top-level JSON response objects contains a value, a status of 200 and a request, which encapsulated the original request. This request has as members a type member for the operational mode ("read", "list", ...) and additional entries containing the operation specific parameters as given in the request URL.

read

A typical response for an attribute read operation for an URL like

 http://localhost:8080/j4p/java.lang:type=Memory/HeapMemoryUsage/

looks like

 {
   "value":{
             "init":134217728,
             "max":532742144,
             "committed":133365760,
             "used":19046472
           },
   "status":200,
   "timestamp":1244839118,
   "request":{
               "mbean":"java.lang:type=Memory",
               "type":"read",
               "attribute":"HeapMemoryUsage"
             },
   "history":[{"value":{
                         "init":"134217728",
                         "max":"532742144",
                         "committed":"133365760",
                         "used":"18958208"
                       },
               "timestamp":1244839045
             }, ....
             ]
 }

As you can see, the value contains the attribute's value, either as a single, simple value if the attribute has a primitive type, or a complex JSON structure (containing maps and arrays) if the attribute has a more complex type understood by the j4p agent. For complex object types, which can not be serialized by the j4p agent, the stringified value (i.e. the output of the object's toString() method) is returned here. For a successul request the status is always 200. timestamp contains the timestamp (i.e. epoch seconds) when the attribute was read on the server.

Optionally, a history entry might be present. This is the case, when history tracking is switched on. See jmx4perl how to do this, in short, you have to execute an JMX operation on certain, jmx4perl specific MBean to turn it on. If this is the case, history contains an array of json object, which have two attribute: value containing the historical value (which can be as complex as any value) and timestamp indicating the time when this value was current.

The request's attribute are:

mbean

name of the requested MBean

attribute

attribute name

type

is always read

path

an optional path, if provided in the request.

write

As response for a writing operation you get back the old value if the value was set. For a request

  http://localhost:8080/j4p/write/java.lang:type=ClassLoading/Verbose/true

you get the answer (supposed that verbose mode was switched off for class loading at the time this request was sent)

 { 
   "value":"false",
   "status":200,
   "request": {
                "mbean":"java.lang:type=ClassLoading",
                "type":"write",
                "attribute":"Verbose",
                "value":"true"
              }
 }

The response is quite similar to the read operation except for the additional value element in the request (and of course, the different type).

exec

For an exec operation, the response contains the return value of the opeartion. null is returned if either the operation return a null value or the operation is declared as void. A typical response for an URL like

 http://localhost:8080/j4p/exec/java.util.logging:type=Logging/setLoggerLevel/global/INFO

looks like

 {
   "value":null,
   "status":200,
   "request": {
                "type":"exec",
                "mbean":"java.util.logging:type=Logging",
                "operation":"setLoggerLevel",
                "arguments":["global","INFO"]
              }
}

search

Searching for MBean names is done with the search operation. As single argument a MBean search pattern like *:j2eeType=J2EEServer,* has to be provided. The answer is a list of MBean names which matches the pattern. A 404 Response will be returned in case no MBean matches this name.

Example:

  http://localhost:8888/j4p/search/*:j2eeType=J2EEServer,*

results in

 {
   "value": [
              "jboss.management.local:j2eeType=J2EEServer,name=Local"
            ],
   "status":200,
   "timestamp":1245305648,
   "request": {
       "mbean":"*:j2eeType=J2EEServer,*","type":"search"
   }
 }

list

The list operation (without a path) returns a JSON object containing a value, status and request member as for read operations.

The value has the following format:

 { 
  <domain> : 
  {
    <prop list> : 
    {
      "attr" : 
      {
        <attr name> : 
        { 
          "type" : <attribute type>,
          "desc" : <textual description of attribute>,
          "rw"   : true/false
        },
        ....
      }, 
      "op" :
      {
         <operation name> :
         {
           "args" : [
                      { 
                       "type" : <argument type>
                       "name" : <argument name>
                       "desc" : <textual description of argument>
                      },
                      .....
                     ],
           "ret"  : <return type>,
           "desc" : <textual description of operation>
         }, 
         .....
      }
    }, 
    ....
  },
  ....
 }

The domain name and the property list together uniquely identify a single MBean. The property list is in the so called canonical order, i.e. in the form "<key1>=<val1>,<key2>=<val2>,.." where the keys are ordered alphabetically. Each MBean has zero or more attributes and operations which can be reached in an MBeans JSON object with the keys attr and op respectively. Within these groups the contained information is explained above in the schema and consist of Java types for attributes, arguments and return values, descriptive information and whether an attribute is writable (rw == true) or read-only.

As for reading attributes you can fetch a subset of this information using an path. E.g a path of domain/prop-list would return the value for a single bean only. For example, a request

 http://localhost:8080/j4p/list/java.lang/type=Memory

results in an answer

 {
   "value":
   { 
     "op":
     { 
       "gc":
       {
         "args":[],
         "ret":"void",
         "desc":"gc"
       }
     },
     "attr":
     {
       "NonHeapMemoryUsage":
       {
         "type":"javax.management.openmbean.CompositeData",
         "rw":false,
         "desc":"NonHeapMemoryUsage"
       },
       "Verbose":
       {
         "type":"boolean",
         "rw":true,
         "desc":"Verbose"
       },
       "HeapMemoryUsage":
       {
         "type":"javax.management.openmbean.CompositeData",
         "rw":false,
         "desc":"HeapMemoryUsage"
       },
       "ObjectPendingFinalizationCount":
       {
         "type":"int",
         "rw":false,
         "desc":"ObjectPendingFinalizationCount"
       }
     }
   },
   "status":200,
   "request":
   {
     "type":"list",
     "path":"java.lang\/type=Memory"
   }
 }

version

A command version returns the version of the underlying jmx4perl package. The response looks like any other response, the version number itself is returned as value attribute in the response.

Error Response

An error response looks like

  {
    "status":400,
    "error":"java.lang.IllegalArgumentException: Invalid request type 'java.lang:type=Memory'",
    "stacktrace":"java.lang.IllegalArgumentException: Invalid request type 'java.lang:type=Memory'\n
                  \tat org.cpan.jmx4perl.JmxRequest.extractType(Unknown Source)\n
                  \tat org.cpan.jmx4perl.JmxRequest.<init>(Unknown Source) ...."
  } 

I.e. the status has a code in the range 400 .. 499 or 500 .. 599 as it is specified for HTTP return codes. The error member contains an error description while stacktrace contains a Java stacktrace occured on the server side (if any).

LICENSE

Copyright (C) 2009 Roland Huss

Jmx4perl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.

jmx4perl is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with jmx4perl. If not, see http://www.gnu.org/licenses/.

A commercial license is available as well. You can either apply the GPL or obtain a commercial license for closed source development. Please contact roland@cpan.org for further information.

PROFESSIONAL SERVICES

Just in case you need professional support for jmx4perl (or Nagios or JMX in general), you might want to have a look at http://www.consol.com/opensource/nagios/. Contact roland.huss@consol.de for further information (or use the contact form at http://www.consol.com/contact/)

AUTHOR

roland@cpan.org

1 POD Error

The following errors were encountered while parsing the POD:

Around line 158:

You forgot a '=back' before '=head2'