Jolokia请求发送方式有两种: 其中一种是HTTP GET方式, 这种方式请求参数被编码后完全放入了URL中. 另外一种是POST请求, 这种方式将一个JSON格式的数据装载到了HTTP POST的正文(body)中. GET请求适合与简单的用例以及通过浏览器测试agent. POST请求使用的是HTTP请求体的JSON数据,更适合复杂的请求,并提供一些额外的功能(例如使用POST批量传输请求)。
agent代理返回的响应内容总是使用JSON格式表示。它具有相同的格式,无论是使用GET还是POST请求。
本章的其余部分分为两个部分:第一部分,一般结构的请求和响应,之后,Jolokia表示法支持操作定义。
Jolokia knows about two different styles of handling requests, which are distinguished by the HTTP method used: GET or POST. Regardless of what method is used, the agent doesn't keep any state on the server side (except of course that MBeans are mostly obviously stateful). So in this aspect, the communication can be considered REST like[7].
访问Jolokia最简单的方法是通过发送HTTP GET请求.这些请求的所有参数进行编码后存在于请求URL中。 通常情况下,Jolokia在使用的URL中提取参数的路径信息部分。在路径信息,每部分被一个斜杠(/)分隔。请求URL格式一般为
<base-url>/<type>/<arg1>/<arg2>/..../
The <base-url>
指明要访问的agent. 通常为
http://localhost:8080/jolokia
, 但这取决于你的安装部署. 通常, 为部署的agent名称, 默认情况下是基于agent的文件名
(例如jolokia.war
).
<type>
指明Jolokia支持的操作 (在下一节介绍), 接下来的几个斜杠分割的参数用来指明特定的操作.
例如, the following URL executes a
read
Jolokia operation on the MBean
java.lang:type=Memory
for reading the
attribute HeapMemoryUsage
(see Section 6.2.1, “Reading attributes (read)”). It is assumed, that the agent is
reachable under the base URL
http://localhost:8080/jolokia
:
http://localhost:8080/jolokia/read/java.lang:type=Memory/HeapMemoryUsage
If one of the request parts contain a slash
(/
) (e.g. as part of you bean's name) it
needs to be escaped. An exclamation mark
(!
) is used as escape character[8]. A exclamation mark needs to be doubled for
escaping. Any other characted preceded by an exclamation mark
is taken literally. Table Table 6.1, “转义规则”
illustrates the escape rules as used in GET requests.
表格 6.1. 转义规则
转义序列 | 字符 |
!/ |
/ |
!! |
! |
! (anything else) |
(anything else) |
For example, to read the atrribute State
on the MBean named
jboss.jmx:alias=jmx/rmi/RMIAdaptor
, an
access URL like this has to be constructed:
.../read/jboss.jmx:alias=jmx!/rmi!/RMIAdaptor/State
Client libraries like JMX::Jmx4Perl do this sort of escaping transparently.
Escaping can be avoided alltogether if a slightly different
variant for a request is used (which doesn't look that
REST-stylish, though). Instead of providing the information
as path-info, a query parameter p
can be
used instead. This should be URL encoded, though. For the
example above, the alternative is
http://localhost:8080/jolokia?p=/read/jboss.jmx:alias=jmx%2Frmi%2FRMIAdaptor/State
POST requests are the most powerful way to communicate with the Jolokia agent. There are fewer escaping issues and it allows for features which are not available with GET requests. POST requests uses a fixed URL and put their payload within the HTTP request's body. This payload is represented in JSON, a data serialization format originating from JavaScript world.
The JSON format for a single request is a JSON object, which
is essentially a map with keys (or
attributes) and values. All requests
have a common mandatory attribute,
type
, which specifies the kind of JMX
operation to perform. The other attributes are either
operation specific as described in Section 6.2, “Jolokia operations” or are processing
parameters which influence the overall behaviour
and can be mixed in to any request. See Section 6.3, “Processing parameters” for details.
A sample read request in JSON format looks like the
following example. It has a type
"read"
(case doesn't matter) and the three attributes
mbean
, attribute
and path
which are specific to a read
request.
示例 6.1. JSON Request
{ "type" : "read", "mbean" : "java.lang:type=Memory", "attribute" : "HeapMemoryUsage", "path" : "used", }
Each request JSON object results in a single JSON response object contained in the HTTP answer's body. A bulk request contains multiple Jolokia requests within a single HTTP request. This is done by putting individual Jolokia requests into a JSON array:
[ { "type" : "read", "attribute" : "HeapMemoryUsage", "mbean" : "java.lang:type=Memory", "path" : "used", }, { "type" : "search" "mbean" : "*:type=Memory,*", } ]
This request will result in a JSON array containing multiple JSON responses within the HTTP response. They are returned in same order as the requests in the initial bulk request.
Responses are always encoded in UTF-8 JSON, regardless whether the requst was a GET or POST request. 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 (e.g. 404 means "not found"). (See this page for more information about HTTP error codes..)
In the non-error case a JSON response looks mostly the same
for each request type except for the
value
attribute which is request type
specific.
The format of a single Jolokia response is
Example 6.2. JSON Response
{ "value": .... , "status" : 200, "timestamp" : 1244839118, "request": { "type": ..., .... }, "history":[ {"value": ... , "timestamp" : 1244839045 }, .... ] }
For successful requests, the status
is
always 200
(the HTTP success code). The
timestamp
contains the epoch
time[9] when the
request has been handled. The request leading to this
response can be found under the attribute
request
. Finally and optionally, if
history tracking is switched on (see Section 6.5, “Tracking historical values”), an entry with key
history
contains a list of historical
values along with their timestamps. History tracking is only
available for certain type of requests
(read
, write
and
exec
). The value
is specific for the type of request, it can be a single
scalar value or a monster JSON structure.
If an error occurs, the status
will be
a number different from 200
. An error
response looks like
{ "status":400, "error_type":"java.lang.IllegalArgumentException", "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) ...." }
For status codes it is important to distinguish status codes as they appear in Jolokia JSON response objects and the HTTP status code of the (outer) HTTP response. There can be many Jolokia status codes, one for each Jolokia request contained in the single HTTP request. The HTTP status code merely reflect the status of agent itself (i.e. whether it could perform the operation at all), whereas the Jolokia response status reflects the result of the operation (e.g. whether the performed operation throws an exception). So it is not uncommon to have an HTTP status code of 200, but the contained JSON response(s) indicate some errors.
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. This is typically the message of an exception
occured on the agent side[10]. Finally, error_type
contains the Java class name
of the exception occured.
The stacktrace
contains a Java stacktrace
occured on the server side (if any stacktrace is available).
For each type of operation, the format of the
value
entry is explained in
Section 6.2, “Jolokia operations”
Before we come to the Jolokia operation, the general concept of inner pathes requires some explanation.
An inner path points to a certain substructure (plain value, array, hash) within a a complex JSON 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/jolokia/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/jolokia/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 (0 based) as part of the inner path if you want to
traverse into this array.
For both, GET and POST requests, pathes must be escaped as
described in Table 6.1, “Escaping rules” when they
contain slashes (/
) or exclamation marks
(!
).
Reading MBean attributes is probably the most used JMX method, especially when it comes to monitoring. Concerning Jolokia, it is also the most powerful one with the richest semantics. Obviously the value of a single attribute can be fetched, but Jolokia supports also fetching of a list of given attributes on a single MBean or even on multiple MBeans matching a certain pattern.
Reading attributes are supported by both kinds of requests,
GET
and POST
.
value
will differ dependening on what kind of
read request was performed.
A read request for multiple attributes on the same MBean is initiated by giving a list of attributes to the request. For a POST request this is an JSON array, for a GET request it is a comma separated list of attribute names (where slashes and exclamation marks must be escaped as described in Table 6.1, “Escaping rules”). If no attribute is provided, then all attributes are fetched. The MBean name can be given as a pattern in which case the attributes are read on all matching MBeans. If a MBean pattern and multiple attributes are requestes, then only the value of attributes which matches both are returned, the others are ignored. Pathes cannot be used with multi value reads, though.
The GET URL for a read request has the following format:
<base-url>/read/<mbean name>/<attribute name>/<inner path>
Table 6.2. GET Read Request
Part | Description | Example |
<mbean name> |
The ObjectName
of the MBean for which the attribute should be fetched. It
contains two parts: A domain part and a list of properties
which are separated by : . Properties
themselves are combined in a comma separated list of
key-value pairs. This name can be a pattern in which case
multiple MBeans are queried for the attribute value.
|
java.lang:type=Memory |
<attribute name> |
Name of attribute to read. This can be a list of Attribute names separated by comma. Slashes and exclamations marks need to be escaped as described in Table 6.1, “Escaping rules”. If no attribute is given, all attributes are read. | HeapMemoryUsage |
<inner path> |
This optional part describes an inner path as described in Section 6.1.4, “Pathes” | used |
With this URL the used heap memory can be obtained:
http://localhost:8080/jolokia/java.lang:type=Memory/HeapMemoryUsage/used
A the keys available for read POST requests are shown in the following table.
Table 6.3. POST Read Request
Key | Description | Example |
type |
read | |
mbean |
MBean's ObjectName which can be a pattern | java.lang:type=Memory |
attribute |
Attribute name to read or a JSON array containing a list attributes to read. No attribute is given, then all attributes are read. | HeapMemoryUsage , [
"HeapMemoryUsage", "NonHeapMemoryUsage" ] |
path |
Inner path for accessing the value of a complex value (Section 6.1.4, “Pathes”) | used |
The following request fetches the number of active threads:
{ "type":"read", "mbean":"java.lang:type=Threading", "attribute":"ThreadCount" }
The general format of the JSON response is described in Section 6.1.3, “Responses” in detail. A typical response for an attribute read operation for an URL like
http://localhost:8080/jolokia/read/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 }, .... ] }
The value
contains the response's
value. For simple data types it is a scalar value, more complex
types are serialized into a JSON object. See Section 6.4, “Object serialization” for detail on object serialization.
For read request to a single MBean with multiple attributes, the
returned value is a JSON object with the attribute names as keys
and their values as values. For example a request to
http://localhost:8080/jolokia/read/java.lang:type=Memory
leads to
{ "timestamp": 1317151518, "status": 200, "request": {"mbean":"java.lang:type=Memory","type":"read"}, "value":{ "Verbose": false, "ObjectPendingFinalizationCount": 0, "NonHeapMemoryUsage": {"max":136314880,"committed":26771456,"init":24317952,"used":15211720}, "HeapMemoryUsage": {"max":129957888,"committed":129957888,"init":0,"used":2880008} } }
A request to a MBean pattern returns as value a JSON object,
with the MBean names as keys and as value another JSON object
with the attribute name as keys and the attribute values as
values. For example a request
http://localhost:8080/jolokia/read/java.lang:type=*/HeapMemoryUsage
returns something like
{ "timestamp": 1317151980, "status": 200, "request": {"mbean":"java.lang:type=*","attribute":"HeapMemoryUsage","type":"read"}, "value": { "java.lang:type=Memory": { "HeapMemoryUsage": {"max":129957888,"committed":129957888,"init":0,"used":3080912} } } }
Writing an attribute is quite similar to reading one, except that the request takes an
additional value
element.
Writing an attribute wit an GET request, an URL with the following format has to be used:
<base url>/write/<mbean name>/<attribute name>/<value>/<inner path>
Table 6.4. GET Write Request
Part | Description | Example |
<mbean name> |
MBean's ObjectName | java.lang:type=ClassLoading |
<attribute name> |
Name of attribute to set | Verbose |
<value> |
The attribute name to value. The value must be serializable as described in Section 6.4.2, “Request parameter serialization”. | true |
<path> |
Inner path for accessing the parent object on which to set the value. (See also Section 6.1.4, “Pathes”). Note, that this is not the path to the attribute itself, but to the object carrying this attribute. With a given path it is possible to deeply set an value on a complex object. |
For example, you can set the garbage collector to verbose mode by using something like
http://localhost:8080/jolokia/write/java.lang:type=Memory/Verbose/true
The keys which are evaluated for a POST write request are:
Table 6.5. POST Write Request
Key | Description | Example |
type |
write | |
mbean |
MBean's ObjectName | java.lang:type=ClassLoading |
attribute |
Name of attribute to set | Verbose |
value |
The attribute name to value. The value must be serializable as described in Section 6.4.2, “Request parameter serialization”. | true |
path |
An optional inner path for specifying an inner object on which to set the value. See Section 6.1.4, “Pathes” for more on inner pathes. |
As response for a write operation the old attribute's value is returned. For a request
http://localhost:8080/jolokia/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
).
Beside attribute provides a way for the execution of exposed JMX operations with optional arguments. The same as for writing attributes, Jolokia must be able to serialize the arguments. See Section 6.4, “Object serialization” for details. Execution of overloaded methods is supported. The JMX specifications recommends to avoid overloaded methods when exposing them via JMX, though.
The format of an GET exec request is
<base url>/exec/<mbean name>/<operation name>/<arg1>/<arg2>/....
Table 6.6. GET Exec Request
Part | Description | Example |
<mbean name> |
MBean's ObjectName | java.lang:type=Threading |
<operation name> |
Name of the operation to execute. If an overloaded method, it is mandatory to provide a method signature as well. A signature consist the fully qualified argument class names or native types, separated by columns and enclosed with parentheses. |
loadUsers(java.lang.String,int)
|
<arg1> , <arg2> , ... |
String representation for the arguments required to execute this operation. Only certain data types can be used here as desribed in Section 6.4.2, “Request parameter serialization”. | "true","true" |
The following request will trigger a garbage collection:
http://localhost:8080/jolokia/exec/java.lang:type=Memory/gc
Table 6.7. POST Exec Request
Key | Description | Example |
type |
exec | |
mbean |
MBean's ObjectName | java.lang:type=Threading |
operation |
The operation to execute, optionally with a signature as described above. | dumpAllThreads |
arguments |
An array of arguments for invoking this operation. The value must be serializable as described in Section 6.4.2, “Request parameter serialization”. | [true,true] |
The following request dumps all threads (along with locked monitors and locked synchronizers, thats what the boolean arguments are for):
{ "type":"EXEC", "mbean":"java.lang:type=Threading", "operation":"dumpAllThreads", "arguments":[true,true] }
For an exec
operation, the response
contains the return value of the
operation. null
is returned if either the
operation returns a null value or the operation is declared as
void. A typical response for an URL like
http://localhost:8080/jolokia/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"] } }
The return value get serialized as described in Section 6.4, “Object serialization”.
With the Jolokia search operation the agent can be queried for
MBeans with a given pattern. Searching will be performed on every
MBeanServer
found by the agent.
The format of the search GET URL is:
<base-url>/search/<pattern>
This mode is used to query for certain MBean. It takes a single
argument pattern
for
specifying the search parameter like in
http://localhost:8080/jolokia/search/*:j2eeType=J2EEServer,*
You can use patterns as described here,
i.e. it may contain wildcards like *
and
?
. The Mbean names matching the query
are returned as a list within the response.
A search POST request knows the following keys:
Table 6.8. POST Search Request
Key | Description | Example |
type |
search | |
mbean |
The MBean pattern to search for | java.lang:* |
The following request searches for all MBeans registered in the
domain java.lang
{ "type":"SEARCH", "mbean":"java.lang:*" }
The answer is a list of MBean names which matches the pattern or an empty list if there was no match.
For example, the request
http://localhost:8888/jolokia/search/*:j2eeType=J2EEServer,*
results in
{ "value": [ "jboss.management.local:j2eeType=J2EEServer,name=Local" ], "status":200, "timestamp":1245305648, "request": { "mbean":"*:j2eeType=J2EEServer,*","type":"search" } }
The returned MBean names are properly quoted so that they can be directly used as input for other requests.
The list operation collects information about accessible MBeans. This information includes the MBean names, their attributes, operations and noticifactions 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).
The GET request format for a Jolokia list request is
<base-url>/list/<inner path>
The <inner path>
, as described in Section 6.1.4, “Pathes”
specifies a subset of the complete response. You can
use this to select a specific domain, MBean or
attribute/operation. See the next section for the format of the
complete response.
A list POST request has the following keys:
Table 6.9. POST list Request
Key | Description | Example |
type |
list | |
path |
Inner path for accessing the value of a subset of the complete list (Section 6.1.4, “Pathes”). | java.lang/type=Memory/attr |
The following request fetches the information about the MBean java.lang:type=Memory
{ "type":"LIST", "path":"java.lang/type=Memory" }
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> }, ..... }, "not" : { "name" : <name>, "desc" : <desc>, "types" : [ <type1>, <type2> ] } }, .... }, .... }
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/jolokia/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" } }
The optional parameter maxDepth
can be used
to restrict the depth of the return tree. Two value are
possible: A maxDepth
of 1 restricts the
return value to a map with the JMX domains as keys, a
maxDepth
of 2 truncates the map returned to
the domain names (first level) and the MBean's properties
(second level). The final values of the maps don't have any
meaning ander are dummy values.
The Jolokia command version
returns the version of
the Jolokia agent along with the protocol version.
The GET URL for a version request has the following format:
<base-url>/version
For GET request the version
part can be
omitted since this is the default command if no command is
provided as path info.
A version POST request has only a single key
type
which has to be set to
version.
The response value for a version request looks like:
{ "timestamp":1287143106, "status":200, "request":{"type":"version"}, "value":{ "protocol":"4.0", "agent":"0.80", "info": { product: "glassfish", vendor": "Sun", extraInfo: { amxBooted: false } } }
protocol
in the response value contains the
protocol version used, agent
ist the version of
the Jolokia agent. See Section 6.7, “Jolokia protocol versions” for the various
protocol versions and the interoperatibility. If the agent is able
to detect the server, additional meta information about this
server is returned (i.e. the product name, the vendor and
optionally some extra information added by the server detector).
Jolokia operations can be influenced by so-called processing parameters. These parameters are provided differently for POST and GET requests.
For GET request, the processing parameter are given as normal query parameters:
<GET request URL>?param1=value1¶m2=value2&...
For example the request
http://localhost:8080/jolokia/list?maxObjects=100
will limit the response to at max 100 values.
POST request take the processing instructions within the
JSON request below the key config
:
{ "type" : "list" "config" : { "maxObjects" : 100 } }
The list of known processing parameters is:
maxDepth
Maximum depth of the tree traversal into a bean's properties. The maximum value as configured in the agent's configuration is a hard limit and cannot be exceeded by a query parameter.
maxCollectionSize
For collections (lists, maps) this is the maximum size.
maxObjects
Number of objects to visit in total. A hard limit can be configured in the agent's configuration.
ignoreErrors
If set to "true", a Jolokia operation will not return an error if an JMX operation fails, but includes the exception message as value. This is useful for e.g. the read operation when requesting multiple attributes' values. Default: false
mimeType
The MIME type to return for the response. By default,
this is text/plain
, but it can be
useful for some tools to change it to
application/json
. Init parameters can
be used to change the default mime type.
Jolokia has some object serialization facilities in order to convert complex Java data types to JSON and vice versa. Serialization works in both ways in requests and responses, but the capabilities differ.
Complex data types returned from the agent can be serialized
completely into a JSON value object. It can detect cycles in
the object graph and provides a way to limit the depth of
serialization. For certain types (like
File
or
ObjectName
) it uses simplifier to not
expose internal and redundant information.
Object values used for values in write operations and arguments in exec, type support is limited to a handful of data types.
Jolokia can serialize any object into a JSON representation when generating the response. It uses some specific converters for certain well known data type with a generic bean converter as fallback.
The following types are directly supported:
java.util.List
are converted to JSON arrays
java.util.Map
gets
converted into a JSON object. Note, however, that JSON
Object keys are always strings.
javax.management.openmbean.CompositeData
is converted in a JSON object, with the keys taken from
the CompositeData
's key set and
the value are its values.
javax.management.openmbean.TabularData
is serialized into one or multiple nested JSON objects
where the keys are derived from its
TabularType.indexName()
. If
there is a single valued index, the index's value is the
key and a TabularData
's row
(which in turn is a
CompositeData
) is a map. With
multi valued keys, the map is nested (first level: first
index's value, second level: second index's value and so
on). For the serialization of TabularData
resulting
from a MXBean
translation for
maps, see Section 6.4.3, “Jolokia and MXBeans”java.lang.Class
gets converted to
a JSON object with keys name
(the class
name) and interfaces
(the implemented
interfaces, if any)
java.io.File
becomes a JSON
object with keys name
(file name),
modified
(date of last modification),
length
(file size in bytes),
directory
(whether the file is a directory),
canonicalPath
(the canonical path)
and exists
.
javax.management.ObjectName
is
converted into a JSON object with the single key
objectName
.
java.net.URL
becomes a JSON
object with the key url
containing
the URL as String.
java.util.Date
is represented in
an ISO-8601 format. When used with a path
time
the milliseconds since 1.1.1970
00:00 UTC are returned.
org.w3c.dom.Element
is translated
into a JSON object with the properties
name
, value
and
hasChildNodes
.
Primitive and simple types (like String) are directly converted into their string presentation. All objects not covered by the list above are serialized in JSON objects, where the keys are the public bean properties of the object and the values are serialized (recursively) as described.
Serialization can be influenced by certain processing parameters given with the request (see Section 6.3, “Processing parameters”). I.e. the recursive process of JSON serialization can be stopped when the data set gets too large. Self and other circular references are detected, too. If this happen, special values indicate the truncation of the generated JSON object.
[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.
(see Section 6.3, “Processing parameters”,
parameter maxDepth
)
[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. (see Section 6.3, “Processing parameters”, parameters
maxCollectionSize
and
maxObjects
)
Serialization in the upstream direction (i.e. when sending
values for write
operations or arguments
for exec
operations) differs from
from the object serializaton as used as response values
which is described in Section 6.4.1, “Response value serialization”. Not all types are
supported for upstream serialization [11]
and the capabilities differ also for POST and GET requests.
GET
upstream serialization is limited to
basic types and simple arrays. POST requests on the other
support a much large set of types, including the
serialization of Map
s,
List
s and all Open
Types.
Since parameters get encoded in the URL for GET request,
only the following types can used for values and arguments
in write
and
exec
requests:
The serialized value is simply the string representation of those types. Dates can be set either by an long value (epoch milliseconds) or with a string value (ISO-8601 format). Arrays of the given types are serialized as a comma separated list.
Certain tag values are used to mark special
values. A null
value has to be
serialized as [null]
, an empty String
as ""
. Tag values are not required for
POST requests.
POST request take advantage of the JSON type of the value
transfered. These are basic types for numbers
(42
or 23.5
),
booleans (true
or
false
) and strings
("habanero"
). Also, JSON knows about
null
values so no special 'tags' like
for GET requests are not required. Since JSON supports
intrinsically key-value maps and array types, these can be
used directly, too. I.e. if the JMX operation to execute
takes a Map
argument, the argument
can be given as a JSON object. Be aware, however, that JSON
maps (objects) only support strings as keys.
The agent knows how to convert an JSON array to Java Arrays (of a basic type) or Lists, depending on the requirement as dictated by the MBeans operation or attribute signature. Numbers in JSON are always transfered as long or double values and are as well tried to fit to the MBean's signature. In case of an overflow (e.g. when trying to treat a long with a too large value as int), an exception is raised.
Upstream serialization also supports OpenTypes.
If the signature of JMX exec operation or the value type
of a JMX attribute is a OpenType
,
they are serialized as follows:
SimpleType
s are extracted from
their corresponding JSON type.
ArrayType
is extracted from a
JSONArray
where the elements are
serialized recursively with this algorithms. Only
ArrayType
s with element type
CompositeType
or
SimpleType
are supported.
CompositeType
is extracted
recursively from a JSONObject
where there the string keys must fit to the
CompositeType
's item names and
the values must be serializable as open types.
TabularType
is converted from
JSONObject
. If it is single index
(i.e. has only one single index name), the
JSONObject
must have the index
values as string keys and the map values are other
JSONObject
s representing the row
data. For TabularType
s with more
than one index name, the incoming
JSONObjecct
must be a nested
object with each index as an additional
layer. E.g. the following JSON object works for
a TabularType
with the two
index names lastname
and
firstname
:
{ "Mann": { "Thomas": { lastname: "Mann", firstname: "Thomas", birth: 1875 }, "Heinrich": { lastname: "Mann", firstname: "Heinrich", birth: 1871 } } }
TabularType
used by the MXBean
framework for serialization of Maps are translated
directly from maps. More details are explained in the
next section Section 6.4.3, “Jolokia and MXBeans”.
The MXBean Framework is availale in the JRE since version 6 and allows for easy creation and registration of own MBeans. MXBeans are some what the successor for standard MBeans and support an annotation driven as well as a naming convention driven programming model. The most important difference to standard MBeans it the restriction of MXBean to reference only open types.
Although to the outside only open types are exposed by the MXBean framework, MXBean themselves can use more complex data types. The framework will translate forth and back between the custom and open types according to certain rules as declared in the MXBean specification. Most of the translations to open types fits naturally to Jolokia's serialization, except for the translation of Map.
When an MXBean references a map, the MXBean framework
translates this map into a
TabularData
with a fixed internal
structure, i.e. with an index key
and
rows with keys key
and
value
. This leads directly to a JSON
representation which is quite artificial. E.g a map with
two keys kind
and
hotness
will be converted by the MXBean
framework to a TabularData object which in turn would be
translated by Jolokia to the following JSON struture
{ "kind" : { "key": "kind", "value": "Habanero" }, "hotness" : { "key": "hotness", "value": 10 } }
Since this representation of a simple map is unnecessarily
complicated, Jolokia treats TabularData
of this kind (i.e. one index key
and rows
with properties key
and
value
) specially in order to translate it
back (and forth) to
{ "kind" : "Habanero", "hotness" : 10 }
The Jolokia agents are able to keep requested values in memory along with a timestamp. If history tracking is switched on, then the agent will put the list of historical values specific for this request into the response. History tracking is toggled by an MBean operation on a Jolokia-owned MBean (see Chapter 7, Jolokia MBeans). This has to be done individually for each attribute or JMX operation to be tracked.
A history
entry is contained in every
response for which history tracking was switched on. A certain
JMX operation on an Jolokia specific MBean has to be executed
to turn history tracking on for a specific attribute or
operation. See Chapter 7, Jolokia MBeans for details.The
history
property of the JSON response
contains an array of json objects which have two attributes:
value
containing the historical value
(which can be as complex as any other value) and
timestamp
indicating the time when this
value was current (as measured by the server). Example 6.2, “JSON Response” has an example of a response
containing historical values.
For multi attribute read requests, the history entry in the response is a JSON object instead of an array, where this object's attributes are the request's attribute names and the values are the history arrays as described above.
For proxy requests, POST must be used as HTTP method so that the given JSON request can contain an extra section for the target which should be finally reached via this proxy request. A typical proxy request looks like
{ "type" : "read", "mbean" : "java.lang:type=Memory", "attribute" : "HeapMemoryUsage", "target" : { "url" : "service:jmx:rmi:///jndi/rmi://targethost:9999/jmxrmi", "user" : "jolokia", "password" : "s!cr!t" } }
url
within the target
section is a JSR-160 service URL for the target server
reachable from within the proxy agent. user
and password
are optional credentials used
for the JSR-160 communication.
The protocol definition is versioned. It contains of a major and minor version. Changes in the minor version are backward compatible to other protocol with the same major version. Major version changes incorporate possibly backwards incompatible changes. This document describes the Jolokia protocol version 6.1
Error responses contain now the original request as well, for single and bulk requests.
Escaping has been changed from /-/
to
!/
. This affects GET Urls and
inner paths.
javax.management.openmbean.TabularData
is serialized differently when generating the
response. In fact, the serialization as an array in
the former versions of this protocol is not correct,
since TabularData
in fact is a
hash and not a list. It is now generated as map (or
multiple maps), dependening on the declared
index. Also, access via path is now
an access via key, not a list index. For the special
case of MXBean map serialization, where the returned
TabularData
has a fixed format
(i.e. with key
and
value
columns), the
TabularData
is transformed to an
appropriate map..
Removed JSON property modified
from
the serialized JSON representation of a File return
value since it duplicated the
lastModified
property on the same
object.
The list
operation supports a
maxDepth
option for truncating the
answer.
Response values are returned in the native JSON datatype, not always as strings as in previous versions of this protocol. Parameter serialization for writing attribute values or for arguments in exec operations has been enhanced for POST requests, which are now represented as native JSON types and not in a string representation as before. GET requests still use a simplified string representation.
This is the initial version for Jolokia. Versions below 4 are implemented by jmx4perl
[7] This document will avoid the term REST as much as possible in order to avoid provoking any dogmatic resentments.
[8]
A backslash (\
) can not be used, since
most servlet container translate a backslash into a forward
slash on the fly when given in an URL.
[9] Seconds since 1.1.1970
[10]
If the server exception
is a subtype of MBeanException
, the wrapped
exception's message is used.
[11] Conversion from a typed system to an untyped representation is obviously much easier than vice versa. Please note, that Jolokia does not replace a full blown JSON object serialization framework like Jackson. Nor does it use one in order to keep the agent small and simple with a low dependency count.