Clients
Three client implementations exists for Jolokia: Jmx4Perl, the Perl binding (the grandmother of all clients ;-), a Java library and a JavaScript library. This reference describes the client bindings bundled with Jolokia. Information about Jmx4Perl can be found elsewhere.
JavaScript Client Library
Notable difference from previous version (pre 2.1.0) are:
-
The code is developed now using TypeScript language and processed using Rollup JS into ESM version (
jolokia.mjs
to be used withimport
statement) and UMD version (jolokia.js
- to be used with browsers when not loading the script astype="module"
) -
There’s no dependency on JQuery anymore
-
For HTTP requests, we use Fetch API.
-
There’s no support for ancient JSONP. CORS it the way to handle cross-origin requests.
-
Because Fetch API is used, there’s no direct support for synchronous requests - this can be achieved simply using
async
andawait
-
There was an
ajaxError
option to handle HTTP/connection errors, but it was used to configure jQuery’s$.ajax
call. NowJolokia.request
in Promise mode returns aPromise
object and we can handle global errors usingPromise.catch()
handler where the passed object is a Response object. -
In callback mode we can still pass
success
anderror
callbacks (to handle successfull and failed Jolokia responses - all delivered with HTTP 200 status code) and additionally we can passfetchError
(name was changed fromajaxError
, because signature has changed as well) configuration option when creating newJolokia
object - this callback will be called with Response object to check for HTTP errors, etc. (when HTTP status is not200
) and/or with an error thrown byfetch()
API call. -
fetch()
call may throw an exception (DOMException
orTypeError
) when networking error occurs orfetch()
is configured in wrong way (for example with bad headers). Mind that it was a bit different with jQuery Ajax, where both HTTP error responses (like404
) and networking errors where handled with single callback being called withxhr
instance. After switching tofetch()
API, these errors in promise mode have to be handled in different way:-
networking and configuration errors can be handled by attaching a
.catch()
handler toJololokia.request()
returned promise. The error will be aDOMException
orTypeError
-
HTTP error responses (where status is different than
200
) can be handled by attaching a.catch()
handler, where the passed object will be a Response. -
In callback mode, both the exception and failed
Response
objects can be passed to a callback configured withfetchError
option.
-
All methods of this library are available via the
Jolokia
client object, which needs to be
instantiated up-front. In the following example a client object is
created and the used heap memory is requested synchronously via
the simple API. The agent is deployed within the same webarchive
which also serves this script.
Here’s a sample code fragment that uses global Jolokia
class which is used to create a jolokia
instance used to invoke simple (from @jolokia.js/simple
package) getAttribute()
operation:
const jolokia = new Jolokia("/jolokia")
const value = await jolokia.getAttribute("java.lang:type=Memory", "HeapMemoryUsage", "used")
console.log("Heap Memory used: " + value)
Installation
The Jolokia JavaScript library is distributed in the form of npm packages which should be used as standard JavaScript libraries. It’s out of scope of this documentation to describe all possible bundler setups which may be used, let’s simply focus on two flavors of these libraries.
package.json
for jolokia.js
package contains this module-related section:
"exports": {
".": {
"types": "./dist/dts/jolokia.d.ts",
"import": "./dist/jolokia.mjs",
"default": "./src/jolokia.ts"
}
}
The recommended way to use this package is with JavaScript ES modules:
import Jolokia from "jolokia.js"
const jolokia = new Jolokia("/jolokia")
...
However if there’s a need to use Jolokia JavaScript libraries directly, it’s always possible to download relevant files (normal an minified) from download page. Then we can refer to the scripts from HTML page:
<head>
<script src="jolokia-2.1.1.min.js"></script>
<script src="jolokia-simple-2.1.1.min.js"></script>
</head>
A Jolokia client is always created as an instance of
Jolokia
. Requests to the agent are sent
by calling methods on this object. The constructing function
takes a plain object, which provides default parameters which
are used in the request()
if no
overriding are given there.
Usage
All functions of this library are available as methods of the
Jolokia
object. The options
argument needs to be
instantiated as usual and it takes a set of default options, which
can be overwritten by subsequent requests. On the most basic
layer is a single request()
method,
which takes two arguments: A request object and an optional
options object. For example, a request for obtaining
the agent’s version for a agent running on the same server which
delivered the JavaScript looks like:
let jolokia = new Jolokia({ url: "/jolokia" });
let response = await jolokia.request({ "type": "version" }, { "method": "post" });
console.log("Agent Version: " + response.value.agent);
If the constructor is used with a single string argument, this
value is considered to be the agent’s access URL. I.e. in the
example above the construction of the
Jolokia
could have been performed with a
single string argument (new Jolokia("/jolokia")
).
Requests
Jolokia requests and responses are represented as JSON objects. They have exactly the same format, which is expected and returned by the agent as defined in Jolokia Protocol for POST requests. All request types are supported.
The request()
method expects as its first
argument either a single request object or, for bulk requests,
an array of request objects.
When Jolokia JavaScript library was using JQuery Ajax, there were two types of operations supported:
-
synchronous - when
options
object didn’t containsuccess
callback -
asynchronous - when user specified
success
callback inoptions
object
Depending on this for synchronous operations either a single response JSON object is returned or an array of responses (in the order of the initial request array). For asynchronous request one or more callbacks are called for each response separately. See Operational modes for details.
With new Fetch API, there are more types of operations:
-
callback mode for compatibility purposes - you have to pass
success
and (optional)error
callbacks throughoptions
object -
recommended JSON method in promise mode when there’s no
success
callback passed andrequest()
returns a Promise object:-
for HTTP status 200, it is resolved with the response value, which may be successfull or error Jolokia responses containing JSON data with response or error details obtained from
Response.json()
-
for HTTP status != 200, it throws an exception which is a Fetch
Response
object - user can attach.catch()
to the promise and analyze the Response object for headers, status code, etc.
-
-
special Text method in promise mode when there’s no
success
callback,dataType: "text"
is passed andrequest()
returns a Promise object:-
for HTTP status 200, it is resolved with the response value, which is plain text response obtained from
Response.text()
. -
for HTTP status != 200 it’s the same as in recommended JSON method
-
-
low level Response method in promise mode, when
resolve: "response"
is passed withoptions
andrequest()
returns a Promise object:-
for any HTTP status code, the returned promise is resolved with entire Response object and user is free to call
Response.json()
,Response.text()
,Response.blob()
or any method from Response API.
-
Remember - when no success
callback is passed, the returned Promise has to be configured for resolution:
-
by attaching
.then()
to get the value (both successful and error Jolokia responses - all within successful HTTP response (status ==200
)) -
by attaching
.catch()
to catch the exceptions:-
a Response object when there is some HTTP response
-
a
DOMException
orTypeError
when there’s a networking or configuration error (see fetch exceptions)
-
-
by using
await jolokia.request()
to get the response -
by surrounding with
try..catch
when there’s no.catch()
used
For convenience, in both callback and promise modes, we can pass fetchError
callback method in the options (in request()
call or initially when creating Jolokia
instance). Before Jolokia 2.1.0 this option was passed directly to $.ajax()
call in jQuery. This callback has the following signature:
function(response, error)
and the parameters are:
-
response
is a Response object when available -
error
is an exception object thrown byfetch()
call (see fetch exceptions)
The following example shows a single and bulk request call to the Jolokia agent:
let jolokia = new Jolokia({ "url": "/jolokia" })
let req1 = { "type": "read", "mbean": "java.lang:type=Memory", "attribute": "HeapMemoryUsage" }
let req2 = { "type": "list" }
let response = await jolokia.request(req1)
let responses = await jolokia.request([ req1, req2 ])
Request options
Each request can be configured with a set of optional parameters
provided either as default during construction of the
Jolokia
object or as optional last
parameter for the request object. Also a request can carry a
config
attribute, which can be used for all
processing parameters (Processing parameters).
The known options are summarized in Table 1, “Request options”
Key | Description |
---|---|
|
Agent URL (mandatory) |
|
Either "post" or "get" depending on the desired HTTP method
(case does not matter). Please note, that bulk requests are
not possible with "get". On the other hand, JSONP requests
are not possible with "post" (which obviously implies that
bulk request cannot be used with JSONP requests). Also, when
using a |
|
The type of data specified to Jolokia request. The default value is |
|
Callback function which is called for a successful
request. The callback receives the response as single
argument. If no |
|
Callback in case a Jolokia error occurs. A Jolokia error is
one, in which the HTTP request succeeded with a status code
of 200, but the response object contains a Jolokia (not HTTP) status other than
OK (200) which happens if the request JMX operation
fails. This callback receives the full Jolokia response
object (with a key |
|
A callback invoked when This callback can be specified both in callback and promise mode - both at |
|
This option is passed directly to |
|
A username used for HTTP authentication |
|
A password used for HTTP authentication |
|
Timeout for the HTTP request used with Abort Signal |
|
This option is passed directly to |
|
Maximum traversal depth for serialization of complex return values |
|
Maximum size of collections returned during serialization. If larger, the collection is returned truncated. |
|
Maximum number of objects contained in the response. |
|
How to serialize long values in the JSON response: |
|
If set to "true", errors during JMX operations and JSON serialization are ignored. Otherwise if a single deserialization fails, the whole request returns with an error. This works only for certain operations like pattern reads. |
|
Defaults to true for canonical (sorted) property lists on object names; if set to "false" then they are turned in their unsorted format. |
|
Whether the response object should contain related request object. |
|
Whether the response object for |
|
A flag (defaults to |
|
If true then in case of an error, the exception itself is returned in
it JSON representation under the key |
|
By default, a stacktrace is returned with every error (key: |
|
The |
Operational modes
Requests can be handled either with Promises or callbacks.
If a success
callback is given in the
request options, the fetch()
promise is handled by Jolokia.
The callback gets these arguments:
-
a Jolokia JSON response object (see Requests and Responses)
-
an integer index indicating for which response this callback is being called.
For bulk requests, this index corresponds to the array
index of the request which lead to this response. The value of
this option can be an array of callback functions which are
called in a round robin fashion when multiple responses are
received in case of bulk requests. These callbacks are called
only when the returned Jolokia response has a status code of
200
, otherwise the callback(s) given with
the error
option are consulted. If no error
callback is given, the error is printed on the console by
default. As for success callbacks, error callbacks receive the
Jolokia error response as a JSON object.
The following example shows callback-based requests for a single Jolokia request as well as for bulk request with multiple callbacks.
let jolokia = new Jolokia("/jolokia");
// Single request with a single success callback
jolokia.request(
{
"type": "read",
"mbean": "java.lang:type=Memory",
"attribute": "HeapMemoryUsage"
},
{
"success": function(response) {
if (response.value.used / response.value.max > 0.9) {
console.info("90% of heap memory exceeded");
}
},
"error": function(response) {
console.info("Jolokia request failed: " + response.error);
}
}
);
// Bulk request with multiple callbacks
jolokia.request(
[
{
"type": "read",
"mbean": "java.lang:type=Threading",
"attribute": "ThreadCount"
},
{
"type": "read",
"mbean": "java.lang:type=Runtime",
"attribute": [ "VmName", "VmVendor" ]
}
],
{
"success": [
function(response) {
console.log("Number of threads: " + response.value);
},
function(response) {
console.log("JVM: " + response.value.VmName + " -- " + response.value.VmVendor);
}
],
"error": function(response) {
alert("Jolokia request failed: " + response.error);
}
}
);
Both callbacks, success
and
error
, are only called when HTTP response code is 200
.
In case of an error on the HTTP level It is the responsibility of user
to attach .catch()
to the returned Promise object. The passed function is called with the
Response
object, so we can get more information. For example:
const response = await jolokia.request({ type: "version" })
.catch(r => {
if (r.status <= 400) {
// handle non-critical error
console.warn(r.statusText)
} else {
// handle codes like 404 or 500
console.warn("Critical error", r.statusText)
}
})
As explained in Requests and Responses the Jolokia
agent supports two HTTP methods, GET
and
POST
. POST
is more
powerful since it supports more features. e.g. bulk requests and
JMX proxy requests are only possible with POST. By default, the
Jolokia JavaScript library selects an HTTP method automatically,
which is GET
for simple cases and POST
for more sophisticated requests. The HTTP method can be
overridden by setting the option method
to
"get"
or "post"
.
There are some limitations in choosing the HTTP method depending on the request and other options given:
-
Bulk requests (i.e. an array of multiple requests) can only be used with
POST
. -
READ
requests for multiple attributes (i.e. theattribute
request parameter is an array of string values) can only be used withPOST
. -
The JMX proxy mode (see Proxy Mode) can only be used with
POST
.
Using Promises
Without callbacks we can leverage full potential of promises.
The example we’ve shown to describe success
and error
callbacks can be written using promises:
let jolokia = new Jolokia("/jolokia");
// Single request with a single success callback
let response = await jolokia.request({
"type": "read",
"mbean": "java.lang:type=Memory",
"attribute": "HeapMemoryUsage"
}).catch(r => {
console.info("Jolokia request failed: " + r.statusText);
})
if (response && response.value.used / response.value.max > 0.9) {
console.info("90% of heap memory exceeded")
}
Simple API
Building upon the basic
Jolokia.request()
method, a simplified
access API is available. It is contained in
jolokia-simple.js
(from @jolokia.js/simple
npm package) which must be included after
jolokia.js
. This API provides dedicated
method for the various request types and supports all options as
described in Table 1, “Request options”.
There is one notable difference for asynchronous callbacks and
synchronous return values though: In case of a successful call,
the callback is fed with the response’s
value
object, not the full response
(i.e. response.value
instead of response
).
Similar when a Promise
is returned, it is resolved with
the value itself from the response and not entire response.
There are also differences in error handling between simple and normal API:
-
for callback mode, the Jolokia error message is passed in the same way
-
for promise mode, if HTTP return code is 200, but it is a Jolokia error, instead of returning the error JSON message, its
error
field is thrown as an exception. HTTP error codes different that 200 are handled in the same way (by throwing or returning Fetch Response object)
Remember - to deal with values directly, await
has to be used on the Promise returned from simple API.
getAttribute(mbean, attribute, path, opts)
-
This method returns the value of an JMX attribute
attribute
of an MBeanmbean
. A path can be optionally given, and the optional request options are given as last argument(s). The return value for synchronous operations are the attribute’s value, for callback operations (i.e.opts.success != null
) it isnull
. See Reading attributes (read) for details.For example, the following method call can be used to synchronously fetch the current heap memory usage:
let memoryUsed = await jolokia.getAttribute("java.lang:type=Memory", "HeapMemoryUsage", "used");
setAttribute(mbean, attribute, value, path, opts)
-
For setting an JMX attribute, this method takes the MBean’s name
mbean
, the attributeattribute
and the value to set asvalue
. The optionalpath
is the inner path of the attribute on which to set the value (see Writing attributes (write) for details). The old value of the attribute is returned or given to asuccess
callback.To enable verbose mode in the memory-handling beans, use
let gsLoggingWasOn = await jolokia.setAttribute("java.lang:type=Memory", "Verbose", true);
execute(mbean, operation, arg1, arg2, …, opts)
-
With this method, a JMX operation can be executed on the MBean
mbean
. Beside the operation’s nameoperation
, one or more arguments can be given depending on the signature of the JMX operation. The return value is the return value of the operation. See Executing JMX operations (exec) for details.The following exampled asynchronously fetches a thread dump as a JSON object and logs it into the console:
jolokia.execute("java.lang:type=Threading", "dumpAllThreads(boolean,boolean)", true, true, { "success": function(value) { console.log(JSON.stringify(value)); } });
search(mBeanPattern, opts)
-
Searches for one or more MBeans whose object names fit the pattern
mBeanPattern
. The return value is a list of strings with the matching MBean names ornull
if none is found. See Searching MBeans (search) for details.The following example looks up all application servers available in all domains:
let servletNames = await jolokia.search("*:j2eeType=Servlet,*");
list(path, opts)
-
For getting meta information about registered MBeans, the
list
command can be used. The optionalpath
points into this meta information for retrieving partial information. The format of the return value is described in detail in Listing MBeans (list).This example fetches only the meta information for the attributes of the
java.lang:type=OperatingSystem
MBean:let attributesMeta = await jolokia.list("java.lang/type=OperatingSystem/attr");
version(opts)
-
The
version
method returns the agent’s version, the protocol version, and possibly some additional server-specific information. See Getting the agent version (version) for more information about this method.A sample return value for an Apache Tomcat server looks like:
{ "agent": "2.1.1", "protocol": "8.0", "details": { "agent_version": "2.1.0-SNAPSHOT", "agent_id": "192.168.0.221-72527-6baa8838-servlet", "server_product": "tomcat", "server_vendor": "Apache", "server_version": "10.1.28", "secured": true, "url": "http://192.168.0.221:8080/jolokia" }, "id": "192.168.0.221-72527-6baa8838-servlet", "config": { ... }, "info": { "proxy": {}, "jmx": {} } }
Request scheduler
A Jolokia
object can be also used for
periodically sending requests to the agent. Therefore requests
can be registered to the client object, and a poller can be
started and stopped. All registered requests are send at once
with a single bulk request so this is a quite efficient method for
periodically polling multiple values.
Here is a simple example, which queries the heap memory usage every 10 seconds and prints out the used memory on the console:
let jolokia = new Jolokia("/jolokia")
handle = jolokia.register(function(resp) {
console.log("HeapMemory used: " + resp.value);
},
{
"type": "read",
"mbean": "java.lang:type=Memory",
"attribute": "HeapMemoryUsage", "path": "used"
});
jolokia.start(10000);
handle = jolokia.register(callback, request, request,….)
-
This method registers one or more request for being periodically fetched.
callback
can be either a function or an object.If a function is given or an object with an attribute
callback
holding a function, then this function is called with all responses received as argument, regardless whether the individual response indicates a success or error state.If the first argument is an object with two callback attributes
success
anderror
, these functions are called for each response separately, depending whether the response indicates success or an error state. If multiple requests have been registered along with this callback object, the callback is called multiple times, one for each request in the same order as the request are given. As second argument, the handle which is returned by this method is given and as third argument the index within the list of requests.If the first argument is an object, an additional
config
attribute with processing parameters can be given which is used as default for the registered requests. Requests with aconfig
section take precedence.Furthermore, if a
onlyIfModified: true
exists in the callback object, then thesuccess
anderror
callbacks are called only if the result changed on the server side. Currently, this is supported for thelist
operation only in which case the callback is only called when MBean has been registered or deregistered since the last call of the scheduler. If a singlecallback
function is used which gets all responses for a job at once, then this function is called only with the responses, which carry a value. If none of the registered requests produced a response with value (i.e. the server decided that there was no update for any request), then a call to the callback function is skipped completely.register()
returns a handle which can be used later for unregistering these requests.In the following example two requests are registered along with a single callback function, which takes two responses as arguments:
handle = jolokia.register(function(resp1, resp2) { console.log("HeapMemory used: " + resp1.value); console.log("ThreadCount: " + resp2.value); }, { "type": "read", "mbean": "java.lang:type=Memory", "attribute": "HeapMemoryUsage", "path": "used" }, { "type": "read", "mbean": "java.lang:type=Threading", "attribute": "ThreadCount" });
In the next example, a dedicated
success
anderror
callback are provided, which are called individually for each request (in the given order):jolokia.register( { "success": function(resp) { console.log("MBean: " + resp.mbean + ", attr: " + resp.attribute + ", value: " + resp.value); }, "error": function(resp) { console.log("Error: " + resp.error_text); }, config: { "serializeException": true }, "onlyIfModified": true }, { "type": "list", "config": { "maxDepth": 2 } }, { "type": "read", "mbean": "java.lang:type=Threading", "attribute": "ThreadCount", "config": { "ignoreErrors": true } }, { "type": "read", "mbean": "bla.blu:type=foo", "attribute": "blubber" } );
jolokia.unregister(handle)
-
Unregister one or more requests registered with
handle
so that they are no longer polled with the scheduler. jolokia.jobs()
-
Return an array of handles for all registered jobs. This array can be freely manipulated, its a copy of the handle list.
jolokia.start(period)
-
Startup the scheduler for requeting the agent every
period
milliseconds. If the scheduler is already running, it adapts its scheduling period according to the given argument. If noperiod
is given, the period provided during construction time (with the optionfetchInterval
) is used. The default value is 30 seconds. jolokia.stop()
-
Stop the scheduler. If the scheduler is not running, nothing happens. The scheduler can be restarted after it has been stopped.
jolokia.isRunning()
-
Checks whether the scheduler is running. Returns
true
if this is the case,false
otherwise.
JavaScript Client Library (before ES modules)
- NOTE
-
Since Jolokia 2.1.0 we recommend to use new (based on ES modules) version of Jolokia JavaScript libraries provided in these npm packages:
-
jolokia.js
-
@jolokia.js/simple
-
The Jolokia JavaScript library provides a JavaScript API to the to the Jolokia agent. It comes with two layers, a basic one which allows for sending Jolokia requests to the agent synchronously or asynchronously and one with a simplified API which is less powerful but easier to use. This library supports bulk requests, HTTP GET and POST requests and JSONP for querying agents which are located on a different server.
All methods of this library are available via the
Jolokia
client object, which needs to be
instantiated up-front. In the following example a client object is
created and then used heap memory is requested synchronously via
the simple API. The agent is deployed within the same webarchive
which also serves this script.
let j4p = new Jolokia("/jolokia");
let value = j4p.getAttribute("java.lang:type=Memory", "HeapMemoryUsage", "used");
console.log("Heap Memory used: " + value);
Installation
The Jolokia JavaScript library is distributed in two parts, in compressed and uncompressed forms:
jolokia.js
andjolokia-min.js
-
Base library containing the Jolokia object definition which carries the
request()
jolokia-simple.js
andjolokia-simple-min.js
-
Library containing the Jolokia simple API and which builds up on
jolokia.js
It must be included afterjolokia.js
since it adds methods to theJolokia
object definition.
All four files can be obtained from the download page. For production environments the compressed version is highly recommended since the extensive API documentation included in the original version is stripped off here. For Maven users there is an even better way to integrate them, described in Maven integration.
jolokia.js
uses
jQuery, which must be
included as well. Since Jolokia 2 is compliant with ES5, using json2.js is no longer required.
As sample HTML head for including all necessary parts looks like:
<head>
<script src="jquery-3.7.1.js"></script>
<script src="jolokia-min.js"></script>
<script src="jolokia-simple-min.js"></script>
</head>
A Jolokia client is always created as an instance of
Jolokia
. Requests to the agent are sent
by calling methods on this object. The constructing function
takes a plain object, which provides default parameters which
are used in the request()
if no
overriding are given there.
Usage
All functions of this library are available as methods of the
Jolokia
object. The options
argument needs to be
instantiated as usual and it takes a set of default options, which
can be overwritten by subsequent requests. On the most basic
layer is a single request()
method,
which takes two arguments: A request object and an optional
options object. For example, a synchronous request for obtaining
the agent’s version for a agent running on the same server which
delivered the JavaScript looks like:
let j4p = new Jolokia({ "url": "/jolokia" });
let response = j4p.request({ "type": "version" }, { "method": "post" });
console.log("Agent Version: " + response.value.agent);
If the constructor is used with a single string argument, this
value is considered to be the agent’s access URL. I.e. in the
example above the construction of the
Jolokia
could have been performed with a
single string argument (new Jolokia("/jolokia")
).
Requests
Jolokia requests and responses are represented as JSON objects. They have exactly the same format, which is expected and returned by the agent as defined in Jolokia Protocol for POST requests. All request types are supported.
The request()
expects as its first
argument either a single request object or, for bulk requests,
an array of request objects. Depending on this for synchronous
operations either a single response JSON object is returned or
an array of responses (in the order of the initial request
array). For asynchronous request one or more callbacks are
called for each response separately. See
Operational modes for details.
The following example shows a single and bulk request call to the Jolokia agent:
let j4p = new Jolokia({ "url": "/jolokia" });
let req1 = { "type": "read", "mbean": "java.lang:type=Memory", "attribute": "HeapMemoryUsage" };
let req2 = { "type": "list" };
let response = j4p.request(req1);
let responses = j4p.request([ req1, req2 ]);
Request options
Each request can be influenced by a set of optional options
provided either as default during construction of the
Jolokia
object or as optional last
parameter for the request object. Also a request can carry a
config
attribute, which can be used for all
processing parameters (Processing parameters).
The known options are summarized in Table 2, “Request options”
Key | Description |
---|---|
|
Agent URL (mandatory) |
|
Either "post" or "get" depending on the desired HTTP method
(case does not matter). Please note, that bulk requests are
not possible with "get". On the other hand, JSONP requests
are not possible with "post" (which obviously implies that
bulk request cannot be used with JSONP requests). Also, when
using a |
|
The type of data specified to the Ajax request. The default value is |
|
Whether the request should be sent via JSONP (a technique for allowing cross domain request circumventing the infamous "same-origin-policy"). This can be used only with HTTP "get" requests. |
|
Callback function which is called for a successful
request. The callback receives the response as single
argument. If no |
|
Callback in case a Jolokia error occurs. A Jolokia error is
one, in which the HTTP request succeeded with a status code
of 200, but the response object contains a status other than
OK (200) which happens if the request JMX operation
fails. This callback receives the full Jolokia response
object (with a key |
|
Global error callback called when the Ajax request itself
failed. It obtains the same arguments as the error callback
given for |
|
A username used for HTTP authentication |
|
A password used for HTTP authentication |
|
Timeout for the HTTP request |
|
Maximum traversal depth for serialization of complex return values |
|
Maximum size of collections returned during serialization. If larger, the collection is returned truncated. |
|
Maximum number of objects contained in the response. |
|
How to serialize long values in the JSON response: |
|
If set to "true", errors during JMX operations and JSON serialization are ignored. Otherwise if a single deserialization fails, the whole request returns with an error. This works only for certain operations like pattern reads. |
|
Defaults to true for canonical (sorted) property lists on object names; if set to "false" then they are turned in their unsorted format. |
|
Whether the response object should contain related request object. |
|
Whether the response object for |
|
A flag (defaults to |
|
If true then in case of an error, the exception itself is returned in
it JSON representation under the key |
|
By default, a stacktrace is returned with every error (key: |
|
The |
Operational modes
Requests can be send either synchronously or asynchronously via
Ajax. If a success
callback is given in the
request options, the request is performed asynchronously via an
Ajax HTTP request. The callback gets these arguments: a Jolokia JSON
response object (see Requests and Responses) and an
integer index indicating for which response this callback is being
called. For bulk requests, this index corresponds to the array
index of the request which lead to this response. The value of
this option can be an array of callback functions which are
called in a round robin fashion when multiple responses are
received in case of bulk requests. These callbacks are called
only when the returned Jolokia response has a status code of
200
, otherwise the callback(s) given with
the error
option are consulted. If no error
callback is given, the error is printed on the console by
default. As for success callbacks, error callbacks receive the
Jolokia error response as a JSON object.
The following example shows asynchronous requests for a single Jolokia request as well as for bulk request with multiple callbacks.
let j4p = new Jolokia("/jolokia");
// Single request with a single success callback
j4p.request(
{
"type": "read",
"mbean": "java.lang:type=Memory",
"attribute": "HeapMemoryUsage"
},
{
"success": function(response) {
if (response.value.used / response.value.max > 0.9) {
alert("90% of heap memory exceeded");
}
},
"error": function(response) {
alert("Jolokia request failed: " + response.error);
}
}
);
// Bulk request with multiple callbacks
j4p.request(
[
{
"type": "read",
"mbean": "java.lang:type=Threading",
"attribute": "ThreadCount"
},
{
"type": "read",
"mbean": "java.lang:type=Runtime",
"attribute": [ "VmName", "VmVendor" ]
}
],
{
"success": [
function(response) {
console.log("Number of threads: " + response.value);
},
function(response) {
console.log("JVM: " + response.value.VmName + " -- " + response.value.VmVendor);
}
],
"error": function(response) {
alert("Jolokia request failed: " + response.error);
}
}
);
Both callbacks, success
and
error
, are only called when the Ajax
request succeeds. In case of an error on the HTTP level, the
callback ajaxError
is called with the
XMLHttpRequest
, a
textStatus
and an optional exception
object. It has the same signature as the underlying
error
callback of the
jQuery.ajax()
call. (See the
jQuery documentation
for details).
The Jolokia agent also supports
JSONP requests
for cases where the Jolokia agent is served on a different server or port
than the JavaScript client. By default, such access is forbidden by the so called
same-origin-policy. To switch on JSONP, the
option jsonp
should be set to
"true"
.
As explained in Requests and Responses the Jolokia
agent supports two HTTP methods, GET
and
POST
. POST
is more
powerful since it supports more features. e.g. bulk requests and
JMX proxy requests are only possible with POST. By default, the
Jolokia JavaScript library selects an HTTP method automatically,
which is GET
for simple cases and POST
for more sophisticated requests. The HTTP method can be
overridden by setting the option method
to
"get"
or "post"
.
There are some limitations in choosing the HTTP method depending on the request and other options given:
-
Bulk requests (i.e. an array of multiple requests) can only be used with
POST
. -
READ
requests for multiple attributes (i.e. theattribute
request parameter is an array of string values) can only be used withPOST
. -
The JMX proxy mode (see Proxy Mode) can only be used with
POST
. -
JSONP can only be used with
GET
and only in asynchronous mode (i.e. asuccess
callback must be given). This is a limitation of the JSONP technique itself.
The restrictions above imply, that JSONP can only be used for single, simple requests and not for JMX proxy calls.
Simple API
Building upon the basic
Jolokia.request()
method, a simplified
access API is available. It is contained in
jolokia-simple.js
which must be included after
jolokia.js
. This API provides dedicated
method for the various request types and supports all options as
described in Table 2, “Request options”. There
is one notable difference for asynchronous callbacks and
synchronous return values though: In case of a successful call,
the callback is fed with the response’s
value
object, not the full response
(i.e. response.value
). Similar, for synchronous
operations the value itself is returned. In case of an error,
either an error
callback is called with the
full response object or an Error
is
thrown for synchronous operations.
getAttribute(mbean, attribute, path, opts)
-
This method returns the value of an JMX attribute
attribute
of an MBeanmbean
. A path can be optionally given, and the optional request options are given as last argument(s). The return value for synchronous operations are the attribute’s value, for asynchronous operations (i.e.opts.success != null
) it isnull
. See Reading attributes (read) for details.For example, the following method call can be used to synchronously fetch the current heap memory usage:
let memoryUsed = j4p.getAttribute("java.lang:type=Memory", "HeapMemoryUsage", "used");
setAttribute(mbean, attribute, value, path, opts)
-
For setting an JMX attribute, this method takes the MBean’s name
mbean
, the attributeattribute
and the value to set asvalue
. The optionalpath
is the inner path of the attribute on which to set the value (see Writing attributes (write) for details). The old value of the attribute is returned or given to asuccess
callback.To enable verbose mode in the memory-handling beans, use
let gsLoggingWasOn = j4p.setAttribute("java.lang:type=Memory", "Verbose", true);
execute(mbean, operation, arg1, arg2, …, opts)
-
With this method, a JMX operation can be executed on the MBean
mbean
. Beside the operation’s nameoperation
, one or more arguments can be given depending on the signature of the JMX operation. The return value is the return value of the operation. See Executing JMX operations (exec) for details.The following exampled asynchronously fetches a thread dump as a JSON object and logs it into the console:
j4p.execute("java.lang:type=Threading", "dumpAllThreads(boolean,boolean)", true, true, { "success": function(value) { console.log(JSON.stringify(value)); } });
search(mBeanPattern, opts)
-
Searches for one or more MBeans whose object names fit the pattern
mBeanPattern
. The return value is a list of strings with the matching MBean names ornull
if none is found. See Searching MBeans (search) for details.The following example looks up all application servers available in all domains:
let servletNames = j4p.search("*:j2eeType=Servlet,*");
list(path, opts)
-
For getting meta information about registered MBeans, the
list
command can be used. The optionalpath
points into this meta information for retrieving partial information. The format of the return value is described in detail in Listing MBeans (list).This example fetches only the meta information for the attributes of the
java.lang:type=OperatingSystem
MBean:let attributesMeta = j4p.list("java.lang/type=OperatingSystem/attr");
version(opts)
-
The
version
method returns the agent’s version, the protocol version, and possibly some additional server-specific information. See Getting the agent version (version) for more information about this method.A sample return value for an Apache Tomcat server looks like:
{ "agent": "2.1.1", "protocol": "7.2", "details": { "agent_version": "2.0.0-SNAPSHOT", "agent_id": "192.168.0.221-72527-6baa8838-servlet", "server_product": "tomcat", "server_vendor": "Apache", "server_version": "10.1.16", "secured": true, "url": "http://192.168.0.221:8080/jolokia" }, "id": "192.168.0.221-72527-6baa8838-servlet", "config": { ... }, "info": { "proxy": {}, "jmx": {} } }
Request scheduler
A Jolokia
object can be also used for
periodically sending requests to the agent. Therefore requests
can be registered to the client object, and a poller can be
started and stopped. All registered requests are send at once
with a single bulk request so this is a quite efficient method for
periodically polling multiple values.
Here is a simple example, which queries the heap memory usage every 10 seconds and prints out the used memory on the console:
let j4p = new Jolokia("/jolokia")
handle = j4p.register(function(resp) {
console.log("HeapMemory used: " + resp.value);
},
{
"type": "read",
"mbean": "java.lang:type=Memory",
"attribute": "HeapMemoryUsage", "path": "used"
});
j4p.start(10000);
handle = j4p.register(callback, request, request,….)
-
This method registers one or more request for being periodically fetched.
callback
can be either a function or an object.If a function is given or an object with an attribute
callback
holding a function, then this function is called with all responses received as argument, regardless whether the individual response indicates a success or error state.If the first argument is an object with two callback attributes
success
anderror
, these functions are called for each response separately, depending whether the response indicates success or an error state. If multiple requests have been registered along with this callback object, the callback is called multiple times, one for each request in the same order as the request are given. As second argument, the handle which is returned by this method is given and as third argument the index within the list of requests.If the first argument is an object, an additional
config
attribute with processing parameters can be given which is used as default for the registered requests. Requests with aconfig
section take precedence.Furthermore, if a
onlyIfModified: true
exists in the callback object, then thesuccess
anderror
callbacks are called only if the result changed on the server side. Currently, this is supported for thelist
operation only in which case the callback is only called when MBean has been registered or deregistered since the last call of the scheduler. If a singlecallback
function is used which gets all responses for a job at once, then this function is called only with the responses, which carry a value. If none of the registered requests produced a response with value (i.e. the server decided that there was no update for any request), then a call to the callback function is skipped completely.register()
returns a handle which can be used later for unregistering these requests.In the following example two requests are registered along with a single callback function, which takes two responses as arguments:
handle = j4p.register(function(resp1, resp2) { console.log("HeapMemory used: " + resp1.value); console.log("ThreadCount: " + resp2.value); }, { "type": "read", "mbean": "java.lang:type=Memory", "attribute": "HeapMemoryUsage", "path": "used" }, { "type": "read", "mbean": "java.lang:type=Threading", "attribute": "ThreadCount" });
In the next example, a dedicated
success
anderror
callback are provided, which are called individually for each request (in the given order):j4p.register( { "success": function(resp) { console.log("MBean: " + resp.mbean + ", attr: " + resp.attribute + ", value: " + resp.value); }, "error": function(resp) { console.log("Error: " + resp.error_text); }, config: { "serializeException": true }, "onlyIfModified": true }, { "type": "list", "config": { "maxDepth": 2 } }, { "type": "read", "mbean": "java.lang:type=Threading", "attribute": "ThreadCount", "config": { "ignoreErrors": true } }, { "type": "read", "mbean": "bla.blu:type=foo", "attribute": "blubber" } );
j4p.unregister(handle)
-
Unregister one or more requests registered with
handle
so that they are no longer polled with the scheduler. j4p.jobs()
-
Return an array of handles for all registered jobs. This array can be freely manipulated, its a copy of the handle list.
j4p.start(period)
-
Startup the scheduler for requeting the agent every
period
milliseconds. If the scheduler is already running, it adapts its scheduling period according to the given argument. If noperiod
is given, the period provided during construction time (with the optionfetchInterval
) is used. The default value is 30 seconds. j4p.stop()
-
Stop the scheduler. If the scheduler is not running, nothing happens. The scheduler can be restarted after it has been stopped.
j4p.isRunning()
-
Checks whether the scheduler is running. Returns
true
if this is the case,false
otherwise.
Maven integration
For Maven users' convenience, the Jolokia JavaScript package is
also available as a JavaScript artifact. It can be easily
included with help of the
javascript-maven-plugin
.
The following example shows a sample configuration which could
be used within a pom.xml
:
<project>
...
<dependencies>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-client-javascript</artifactId>
<type>javascript</type>
<version>2.1.1</version>
</dependency>
....
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.devspan.mojo.javascript</groupId>
<artifactId>javascript-maven-plugin</artifactId>
<version>0.9.3</version>
<extensions>true</extensions>
<configuration>
<useArtifactId>false</useArtifactId>
</configuration>
<executions>
<execution>
<goals>
<goal>war-package</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>
Then, in your webapp project, jolokia.js
,
jolokia-simple.js
and
json2.js
can be found in the
scripts/lib
directory (relative to the
top level of you WAR). In order to include it in your HTML
files use something like this:
<head>
<script src="jquery-3.7.1.js"></script>
<script src="scripts/lib/jolokia.js"></script>
<script src="scripts/lib/jolokia-simple.js"></script>
</head>
jquery.js
has to be included on its own,
though and is not included within the dependency. If the
compressed version of jolokia.js
should
be used, add a
classifier="compressed"
to the
jolokia-client-javascript
dependency, and
include scripts/lib/jolokia-min.js
A full working example can be found in the Jolokia sources at
examples/client-javascript-test-app/pom.xml
.
Java Client Library
The Java client library provides an easy access to the Jolokia agent from within Java. Since JSR-160 connectors themselves provide Java based remote access to MBeans one might wonder about the benefits of a Jolokia Java binding. There are several, though:
-
It provides a typeless access to remote MBeans. The big advantage is that for any non-OpenMBean access to custom typed objects is still possible without having the type information locally in the classpath.
-
Jolokia can be used in setups where JSR-160 connectors can not be used. I.e. in firewall secured environments it is much easier to get through to a Jolokia Agent than to an JSR-160 connector using RMI as transport protocol.
-
Remoteness is explicit in this API instead of JSR-160 connector’s seeked transparent remoteness. RMI has some arguable conceptually advantages, but hiding all remote aspects proved to have quite some disadvantages when it comes to the programming model. Explicit awareness of a 'heavy-weight' remote call is better than false transparency in order to know the price tag.
The Java client library follows a strict request-response
paradigm, much like the underlying HTTP. It uses generics heavily
and can be centered around three classes:
J4pClient
is the client side agent, which
has various variants of a execute()
for
sending requests. This method takes one or more
J4pRequest
objects as arguments and returns
one or more J4pResponse
objects as result.
But before we got into the details, the next section gives a first tutorial to get a feeling how the API can be used.
Tutorial
As seen in the following example, the usage is quite easy. First
a, client object client
is created pointing
to a Jolokia agent at http://localhost:8080/jolokia
.
A read request for querying the heap memory usage from the
MemoryMXBean
is created and then send via
the execute()
to the agent. The
response returned is of type
J4pReadResponse
and holds the result
which finally is printed out to standard output.
import org.jolokia.client.J4pClient;
import org.jolokia.client.request.*;
public class MemoryDemo {
public static void main(String[] args) {
J4pClient client = J4pClient.url("http://localhost:8080/jolokia")
.user("jolokia")
.password("jolokia")
.build();
J4pReadRequest request =
new J4pReadRequest("java.lang:type=Memory", "HeapMemoryUsage");
request.setPath("used");
J4pReadResponse response = client.execute(request);
System.out.println("Memory used: " + response.getValue());
}
}
In order to compile and run this sample, jolokia-client-java.jar
library is needed (see Download) as well as
some additional support libraries:
For Maven users, the following dependency is sufficient (it will include the other two as transitive dependencies):
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-client-java</artifactId>
<version>2.1.1</version>
</dependency>
J4pClient
J4pClient
is the entry point for sending
requests to a remote Jolokia agent. It can be created in multiple
ways. For simple cases, public constructors are provided taking
the mandatory Jolokia agent URL and optionally a
org.apache.http.client.HttpClient
instance which is used for the HTTP business. The recommended style
is to use the J4pClientBuilder
, though. This way, all
parameters for the HTTP communication can easily be set:
J4pClient j4p = J4pClient.url("http://localhost:8080/jolokia")
.user("roland")
.password("s!cr!t")
.authenticator(new BasicAuthenticator().preemptive())
.connectionTimeout(3000)
.build();
The builder supports the following parameters with the given defaults:
Parameter | Description | Default |
---|---|---|
|
The URL to the Jolokia agent. This is the only mandatory parameter. |
|
|
User name when authentication is used. If not set, no
authentication is used. If set, |
|
|
Password used for authentication. Only used when
|
|
|
Implementation of |
|
|
A JMX JSR-160 ServiceURL which should be used by the agent as the real target. This parameter should be set if the client is used for accessing the agent in Proxy Mode. |
|
|
The JSR-160 user to use when using the proxy mode. If not
given (and |
|
|
JSR-160 Password to use for the proxy mode. |
|
|
The timeout in milliseconds until a connection is established. A timeout value of zero is interpreted as an infinite timeout. |
|
|
Specifies, that the underlying HttpClient should use pooled
connection manager, which is thread safe and can service
connection requests from multiples threads
simultaneously. This is important if the
|
|
|
Specifies that single connection should be used which
maintains only one active connection at a time. Even though
|
|
|
Defines the number of total connections to be pooled. It
is only used when |
|
|
Defines the number of total connections per route. It
is only used when |
|
|
Defines the timeout for waiting to obtain a connection
from the pool. This parameter is only used when
|
|
|
Defines the socket timeout ( |
|
|
Defines the charset to be used per default for encoding content body. |
|
|
Activates |
|
|
Determines whether Nagle’s algorithm is to be used. The
Nagle’s algorithm tries to conserve bandwidth by minimizing
the number of segments that are sent. When applications wish
to decrease network latency and increase performance, they
can disable Nagle’s algorithm (that is enable
|
true |
|
Determines the size of the internal socket buffer in bytes used to buffer data while receiving and transmitting HTTP messages. |
|
|
Determines http proxy server. It can be defined as
|
|
|
Set the proxy for this client based on |
|
|
A response extractor can be used for hooking into the JSON
deserialization process when a JSON response is converted
into a |
The J4pClient
provides various variants
of a execute()
method, which takes
either one single request or a list of requests. For a single
request, the preferred HTTP method (GET or POST) can be
specified optionally. The List<R>
argument can be used type only for a homogeneous bulk request,
i.e. for multiple requests of the same time. Otherwise an
untyped list must be used.
Each request can be tuned by giving a map of processing options
along with their values to the execute
method. The possible options are shown in table
Table 4, “J4pClient query parameters”.
J4pQueryParameter enum | Description |
---|---|
|
Maximum traversal depth for serialization of complex objects. Use this with a "list" request to restrict the depth of the returned meta data tree. |
|
Maximum size of collections returned during serialization. If larger, a collection is truncated to this size. |
|
Maximum number of objects returned in the response’s value. |
|
Option for ignoring errors during JMX operations and JSON
serialization. This works only for certain operations like
pattern reads and should be either |
|
Whether to include a stack trace in the response when an
error occurs. The allowed values are
|
|
Whether to include a JSON serialized version of the
exception. If set to |
|
Whether property keys of |
|
Whether the response object should contain related request object. |
Request types
For each request type a dedicated request object is provided
which all are subclasses from
J4pRequest
. For all requests it can be
specified which HTTP method is to be used by setting the
property preferredHttpMethod
to either
GET
or POST
.
Each request type has a corresponding response type which used
for the return values of the
J4pClient.execute()
.
The constructor of each kind of request can take a
J4pTargetConfig
as argument for using a
request in Proxy Mode. This
configurational object holds the JMX service url and
(optionally) credentials for JSR-160 authentication. When
given, this proxy target specification overrides any default
proxy configuration set during the initialization of the
J4pClient
.
J4pReadRequest
andJ4pReadResponse
-
J4pReadRequest
is a read request to get one or more attributes from one or more MBeans within a single request. Various constructor variants can be used to specify one or more attributes along with the ObjectName (which can be a pattern). Apath
can be set as property for specifying an inner path, too.J4pReadResponse
is the corresponding response type and allows typed access to the fetched value for a single attribute fetch or to multiple values for a multi attribute read. In the latter case, the found object and attributes names can be retrieved as well.For more information on fetching the value of multiple attributes and multiple MBeans at once, please refer to Reading attributes (read) or the Javadoc of
J4pReadResponse
. J4pWriteRequest
andJ4pWriteResponse
-
A
J4pWriteRequest
is used to set the value of an MBean attribute. Beside the mandatory object and attribute name the value must be give in the constructor as well. Optionally apath
can be provided, too. Only certain types for the given value can be serialized properly for calling the Jolokia agent as described in Request parameter serialization.The old value is returned as
J4pWriteResponse
's value. J4pExecRequest
andJ4pExecResponse
-
J4pExecRequest
's are used for executing operation on MBeans. The constructor takes as mandatory arguments the MBean’s object name, the operation name and any arguments required by the operation. Only certain types for the given arguments can be serialized properly for calling the Jolokia agent as described in Request parameter serialization.The returned
J4pExecResponse
contains the return value of the operation called. J4pSearchRequest
andJ4pSearchResponse
-
A
J4pSearchRequest
contains a valid single MBean object name pattern which is used for searching MBeans.The
J4pSearchResponse
holds a list of found object names. J4pListRequest
andJ4pListResponse
-
For obtaining meta data on MBeans a
J4pListRequest
should be used. It can be used with a inner path to obtain only a subtree of the response, otherwise the whole tree as described in List response is returned. With the query parametermaxDepth
can be used to restrict the depth of returned tree.The single value of a
J4pListResponse
is a tree (or subtree) as a JSON object, which has the format described in List response. J4pVersionRequest
andJ4pVersionResponse
-
A
J4pVersionRequest
request the Jolokia agent’s version information and takes no argument.The
J4pVersionResponse
returns the agent’s version (agentVersion
), the protocol version (protocolVersion
), the application server product name (product
), the vendor name (vendor
) and any extra info (extraInfo
) specific to the platform the Jolokia is running on.
Exceptions
In case of an error when executing a request a
J4pException
or one its subclass is
thrown.
J4pConnectException
-
Exception thrown when the connection to the server fails. It contains the original
ConnectException
as nested value. J4pTimeoutException
-
Exception thrown in case of an timeout. The nested exception is of type
ConnectTimeoutException
. J4pRemoteException
-
Generic exception thrown when an exception occurred on the remote side. This is the case when the JSON response obtained is an error response as described in Responses. The error type, error value, the status, the request leading to this error and the remote stacktrace as string) can be obtained from this exception.
J4pBulkRemoteException
-
Exception thrown when a bulk request fails on the remote side. This contains a mixed list which contains the
J4pRemoteException
occurred as well as theJ4pResponse
objects for the requests, which succeeded. The list obtained bygetResults()
contains these objects in the same order as the list of requests given toexecute
. All responses and remote exceptions can also be obtained separately in homogeneous lists. J4pException
-
Base exception thrown, when no other exception fits, i.e. when the exception happened on the client side. The original exception is contained as nested exception.
MBeanServerConnection adapter
The JMX adapter library simulates a local or remote MBeanServerConnection
by using the Jolokia protocol for connecting to a Jolokia agent.
This allows you to use tools that leverage a JSR-160 MBeanServerConnection
such as JConsole, Visual VM or Java Mission Control for connecting to a Jolokia endpoint.
JSR-160 Connection to Jolokia
The example below shows how to connect programmatically via a JSR-160 JMXConnector
to a Jolokia enabled Java process listening on localhost:8778
.
For this example to work you need the following prerequisites:
-
Jolokia’s
remote-jmx-adapter-2.1.1-javaagent.jar
must be on the classpath. See the Download page for the latest versions of this adapter jar. -
Jolokia has to be accessible running at http://localhost:8778/jolokia/. If user/password authentication is enabled for the agent, uncomment the line below and insert your credentials.
import javax.management.remote.*;
import javax.management.ObjectName;
import java.util.Arrays;
public class ConnectWithJolokiaDemo {
public static void main(String[] args) throws Exception {
Map<String, Object> options = new HashMap<>();
// Add user & password if the Agent is secured:
options.put(JMXConnector.CREDENTIALS, new String[] { "jolokia", "jolokia" });
// https will be used if port number fits the pattern *443
// or if options contains "jmx.remote.x.check.stub"->"true"
JMXConnector connector = JMXConnectorFactory.connect(
new JMXServiceURL("service:jmx:jolokia://localhost:8778/jolokia"),
options);
connector.connect();
System.out.println("Memory used: " +
connector.getMBeanServerConnection().getAttribute(
ObjectName.getInstance("java.lang:type=Memory"),"HeapMemoryUsage"));
}
}
JSR-160 Connection to a JVM running in Kubernetes
If you are running a Jolokia-enabled JVM within a Kubernetes Pod, you can directly connect to this JVM from your local machine with the Jolokia JSR-160 connector. See the runnable example below for more details.
Before compiling and running the example below, please check that the following prerequesites are met:
-
Jolokia’s
remote-jmx-adapter-2.1.1-javaagent.jar
must be on the classpath. See the Download page for the latest versions of this adapter jar. -
In addition, the Jolokia Kubernetes extension
jolokia-kubernetes-2.1.1-javaagent.jar
must be on the classpath. This can be also downloaded from the Download page. -
Configuration and authentication for the Kubernetes context setup are as usual. I.e., you must be able to run
kubectl
with the cluster to connect to. You can check this bykubectl get namespace
. -
For the example below, we assume a Java process running in a Pod
petclinic-6959c9b4cb-gk8np
in namespacedefault
that has a Jolokia agent enabled. This agent is supposed to listen on port8778
.
import javax.management.remote.*;
import javax.management.ObjectName;
import org.jolokia.kubernetes.client.KubernetesJmxConnector;
public class ConnectInKubernetesDemo {
public static void main(String[] args) {
Map options = new HashMap();
// Add the Kubernetes context from the Kubernetes configuration that
// points to your cluster. By default, the currently active context
// is used.
// options.put(KubernetesJmxConnector.KUBERNETES_CLIENT_CONTEXT,
// "docker-desktop");
JMXConnector connector = JMXConnectorFactory.connect(
new JMXServiceURL("service:jmx:kubernetes:///default/petclinic-6959c9b4cb-gk8np:8778/jolokia/"),
options);
connector.connect();
System.out.println("Memory used: " +
connector.getMBeanServerConnection().getAttribute(
ObjectName.getInstance("java.lang:type=Memory"),"HeapMemoryUsage"));
}
}
As an alternative to connecting programmatically to the Jolokia agent, you can also leverage jconsole
to explore JMX on the remote JVM.
You need to add the Jolokia connector client libraries when launching jconsole
like in:
java -cp jolokia-agent-jvm-2.1.1-javaagent.jar:\ jolokia-client-jmx-adapter-2.1.1-standalone.jar:\ jolokia-client-kubernetes-2.1.1-standalone.jar \ -Djconsole.showOutputViewer sun.tools.jconsole.JConsole
After adding these Jolokia jars to sun.tools.jconsole.JConsole
class we can then access remote server using Jolokia JMX URL: