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.jsandjolokia-min.js-
Base library containing the Jolokia object definition which carries the
request() jolokia-simple.jsandjolokia-simple-min.js-
Library containing the Jolokia simple API and which builds up on
jolokia.jsIt must be included afterjolokia.jssince it adds methods to theJolokiaobject 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 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 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. -
READrequests for multiple attributes (i.e. theattributerequest 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
GETand only in asynchronous mode (i.e. asuccesscallback 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 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). 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
attributeof 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 attributeattributeand the value to set asvalue. The optionalpathis 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 asuccesscallback.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 ornullif 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
listcommand can be used. The optionalpathpoints 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=OperatingSystemMBean:let attributesMeta = j4p.list("java.lang/type=OperatingSystem/attr"); version(opts)-
The
versionmethod 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.5.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.
callbackcan be either a function or an object.If a function is given or an object with an attribute
callbackholding 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
successanderror, 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
configattribute with processing parameters can be given which is used as default for the registered requests. Requests with aconfigsection take precedence.Furthermore, if a
onlyIfModified: trueexists in the callback object, then thesuccessanderrorcallbacks are called only if the result changed on the server side. Currently, this is supported for thelistoperation 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 singlecallbackfunction 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
successanderrorcallback 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
handleso 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
periodmilliseconds. If the scheduler is already running, it adapts its scheduling period according to the given argument. If noperiodis 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
trueif this is the case,falseotherwise.
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.5.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.