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.30 of the j4p agent protocol. This is the initial version.

REQUEST

Jmx4perl know about two different style for handling a request which are distinguished by the HTTP method used, GET or POST.

For GET requests it uses restful style, which essentially is a single URL which encodes all requests parameters. 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.

In addition to the command provided as a path, the agent knows about some query parameters which influence the value returned. These are described in section "Query Parameters"

For POST the complete request is specified in the content. This content is a JSON representation of the JMX request. Beside the operations available for a simple GET request, POST request can contain additional parameters, e.g. for specifying a proxy. Additionally, with POST request you can submit multiple JMX request at a time realizing bulk operation and minimizing turnaround times.

The supported operations are described now in the following sections.

GET Requests

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!

POST Requests

All operations as desrcibed above are available for post requests as well. In its most general form, the content of a POST has the following format:

 [
  {
    "attribute":"HeapMemoryUsage",
    "mbean":"java.lang:type=Memory",
    "path":"used",
    "type":"READ"
  },
  { 
    "mbean":"*:type=Memory,*",
    "type":"SEARCH"
  }
 ]

In this case, multiple request are represented as a JSON array with maps, where the map's entries are the single request's attribute along with its value. For a single request, the array can be omitted. Depending on whether you send an array of requests or a single request you get an array of responses or a single response as result.

The parameters known to a single request are:

type

Operational type as defined in JMX::Jmx4Perl::Request ("READ", "WRITE", "EXEC", "LIST", "SEARCH")

mbean

Name of the targetted mbean in its canonical format.

attribute

If type is READ or WRITE this specifies the requested attribute

value

For WRITE this specifies the value to set

arguments

List of arguments of EXEC operations

path

Inner path

maxDepth, maxObjects, maxCollectionSize

Optional parameters in order to influence the size of the returned JSON response.

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 directly, bean properties (i.e public, no-argument get methods on the Java objects) are examined recursively up to a maximum depth. You can influence the traversal by providing regular HTTP query parameters to the request URL. The known parameters are

maxDepth

Maximum depth of the tree traversal into a bean's properties. The maximum value as configured in the agent's web.xml is a hard limit and cannot be exceeded by a query parameter (5)

maxCollectionSize

For collections (lists, maps) this is the maximum size. By default, no limit applies to collections

maxObjects

Number of objects to visit in total. A hard limit can be configured in the agent's web.xml deployment descriptor. (10000)

If bean serialization is used, certain special values indicate some special treatment:

[this]

This label is used when a property contains a self reference

[Depth limit .... ]

When a depth limit is used or the hard depth limit is exceeded, this label contains a string representation of the next object one level deeper.

[Reference .... ]

If during the traversal an object is visited a second time, this label is used in order to break the cycle.

[Object limit exceeded]

The total limit of object has been exceeded and hence the object are not deserialized further.

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 172:

You forgot a '=back' before '=head3'