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 MBeanjava.lang:type=Memory
can be requested with the URLhttp://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 requesthttp://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
search
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
orWRITE
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'