JmxBuilder is a Groovy-based domain specific language for the Java Management Extension (JMX) API. It uses the builder pattern (FactoryBuilder) to create an internal DSL that facilitates the exposure of POJO's and Groovy beans as management components via the MBean server. JmxBuilder hides the complexity of creating and exporting management beans via the JMX API and provides a set of natural Groovy constructs to interact with the JMX infrastructure.
To start using JmxBuilder, simply make sure the jar file is on your class path. Then you can do the following in your code
That's it! You are now ready to use the JmxBuilder.
Once you have an instance of JmxBuilder, you are now ready to invoke any of its builder nodes.
Remote connectivity is a crucial part of the JMX architecture. JmxBuilder facilitates the creation of connector servers and connector clients with nimimal amount of coding.
JmxBuilder.connectoServer() supports the full Connector api syntax and will let you specify properties, override the URL, specify your own host, etc.
Note that the serverConnector node will accept four ServerConnector property aliases (authenticate, passwordFile,accessFile, and sslEnabled). You can use these aliases or provided any of the RMI-supported properties.
Example - Connector Server (see correction below)
The snippet above returns an RMI connector that will start listening on port 9000. By default, the builder will internally generate URL "service:jmx:rmi:///jndi/rmi://localhost:9000/jmxrmi"
NOTE: Sadly you are as likely to get something like the following when attempting to run the previous snippet of code (example is incomplete, see below):
This occurs on Mac and Linux (CentOS 5) with Groovy 1.6 installed. Perhaps there were assumptions made about the configuration of the /etc/hosts file?
NOTE: The correct example is shown below.
Connector Example (Corrected) - Connector Server
The example above does not create the RMI registry. So, in order to export, you have to first export the RMI object registry (make sure to import java.rmi.registry.LocateRegistry).
JmxBuilder.connectorClient() node lets you create JMX connector client object to connect to a JMX MBean Server.
Example - Client Connector
Creating a connector client can be done just as easily. With one line of code, you can create an instance of a JMX Connector Client as shown below.
You can then access the MBeanServerConnection associated with the connector using:
You can export a Java object or a Groovy object with minimal coding. JmxBuilder will even find and export dynamic Groovy methods injected at runtime.
When using the builder, you can let JmxBuilder implicitly generate all of your MBean descriptor info. This is useful when you want to write minimal code to quickly export your beans. You can also explicitly declare all descriptor info for the bean. This gives you total control on how you want to describe every piece of information that you want to export for the underlying bean.
The JmxBuilder.export() node provides a container where all management entities to be exported to the MBeanServer are placed. You can place one or more bean() or timer() nodes as children of the export() node. JmxBuilder will automatically batch export the entities described by the nodes to the MBean server for management (see example below).
In the code snippet above, JmxBuilder.export() will export three management beans to the MBean server.
JmxBuilder.export() node supports the registrationPolicy parameter to specify how JmxBuilder will behave to resolve bean name collision during MBean registration:
replace - JmxBuilder.export() will replance any bean already registered with the MBean during export.
ignore - The bean being exported will be ignored if the same bean is already registered.
error - JmxBuilder.export() throws an error upon bean name collision during registration.
When you export an MBean to the MBeanServer, JmxBuilder will return an instance of GroovyMBean representing the management bean that have been exported by the builder. Nodes such as bean() and timer() will return an instances of GroovyMBean when they are invoked. The export() node returns an array of all of GroovyMBean representing all managed objects exported to the MBean server.
This portion of this reference uses class RequestController to illustrate how to use JmxBuilder to export runtime management beans. The class is for illustration purpose and can be a POJO or a Groovy bean.
As mentioned earlier, you can use JmxBuilder's flexible syntax to export any POJO/POGO with no descriptor. The builder can automatically describe all aspects of the management beans using implicit defaults. These default values can easily be overridden as we'll see in this in the next section.
The simplest way to export a POJO or POGO is listed below.
What this does:
Remember, JmxBuilder.export() returns an array of GroovyMBean objects for all exported instances. So, once you call JmxBuilder.export(), you have immediate access to the underlying MBean proxy (via GroovyMBean).
The JmxBuilder.bean() node supports an extensive set of descriptors to describe your bean for management. The JMX MBeanServer uses these descriptors to expose meta data about the bean exposed for management.
Instead of describing the entire node, the following section explore each attribute separately.
Using the bean() node descriptors, you can specify your own MBean ObjectName.
The ObjectName can be specified as a String or an instance of the ObjectName.
JMX attributes are the setters and getters on the underlying bean. The JmxBuilder.bean() node provides several ways to flexibly describe and export MBean attributes. You can combine them however you want to achieve any level of attribute visibility. Let's take a look.
The following code snippet will describe and export all attributes on the bean as read-only. JmxBuilder will use default values to describe the attributes that exported for management.
JmxBuilder will let you specify a list of attributes to export.
In the snippet above, only the "Resource" and "RequestCount" attributes will be exported. Again, since no descriptors are provided, JmxBuilder will use sensible defaults to describe the exported attributes.
One of the strengths of JmxBuilder is its flexibility in describing MBean. With the builder you can describe all aspects of the MBeans attribute that you want to export to the MBeanServer (see syntax above).
In the snippet above, attribute "Resource" is fully-described using all supported descriptors (i.e. desc, readable, writable, defaultValue) for a JMX attribute. However, we use the wildcard to describe attribute RequestCount and it will be exported and described using defaults.
JmxBuilder supports the explicit description and export of constructors defined in the underlying bean. There are several options available when exporting constructors. You can combine them however you want to achieve the desired level of manageability.
You can use the builder's special `""` notation to *export all constructors declared on the underlying bean. The builder will use default values to describe the MBean constructors.
JmxBuilder lets you target specific constructor to export by describing the parameter signature. This is useful when you have several constructors with different parameter signature and you want to export specific constructors.
Here, JmxBuilder will export a constructor that takes one parameter of type "Object". Again, JmxBuilder will use default values to fill in the description of the constructor and the parameters.
JmxBuilder allows you to fully-describe the constructor that you want to target for export (see syntax above).
In the code above, JmxBuilder will target a constructor that takes one parameter for export to the MBeanServer. Notice how the constructor can be fully-described using all optional descriptor keys including parameter descriptors.
Similar to constructors, JmxBuilder supports the description and export of MBean operations using a flexible notation (see above for syntax). You can combine these notations however you want to achieve the level of operation manageability desired.
You can use the builder's special `""` notation to *export all operations defined on the bean to be exposed for management. The builder will use default descriptor values for the operations being exported.
In this snippet, JmxBuilder will export all bean operations and will use default values to describe them in the MBeanServer.
JmxBuilder has a shorthand notation that lets you quickly target operations to be exported by providing a list of methods to export.
In the snippet above, the builder will only export methods start() and stop(). All other methods will be ignored. JmxBuilder will use default descriptor values to describe the operations being exported.
Using JmxBuilder, you can target methods to export for management using the methods's parameter signature. This is useful when you want to distinguish methods with the same name that you want to export (i.e. stop() instead of stop(boolean)).
In the snipet above, JmxBuilder would select method makeRequest(String) to be exported instead of the other version makeRequest() which takes no parameter. In this shorthand context, the signature is specified as a list of type (i.e. "String").
JmxBuilder supports detailed descriptors for bean operations. You can supply deep descriptor info about any operation on your bean including a name, description, method parameters, parameter type, and parameter description.
The snippet above shows all of the ways JmxBuilder allows you to describe an operation targeted for management:
JmxBuilder supports the ability to embed descriptors directly in your Groovy class. So, instead of wrapping your description around the declared object (as we've seen here), you can ebmed your JMX descriptors directly in your class.
There are two things going on in the code above:
JMX standards mandate that the implementation of the API makes available a timer service. Since JMX is a component-based architecture, timers provide an excellent signaling mechanism to communicate to registered listener components in the MBeanServer. JmxBuilder supports the creation and export of timers using the same easy syntax we've seen so far.
The timer() node supports several attributes:
This snippet above describes, creates, and exports a standard JMX Timer component. Here, the timer() node returns a GroovyMBean that represents the registered timer MBean in the MBeanServer.
An alternative way of exporting timers is within the JmxBuilder.export() node.
The timer() node supports a flexible notation for specifying the timer period values. You can specify the time in second, minutes, hour, and day. The default is millisecond.
The node will automatically translate.
An integral part of JMX is its event model. Registered management beans can communicate with each other by broadcasting events on the MBeanServer's event bus. JmxBuilder provides several ways to easily listen and react to events broadcasted on the MBeanServer's event bus. Developers can capture any event on the bus or throw their own to be consumed by other components registered on the MBeanServer.
JmxBuilder leverages Groovy's use of closures to provide simple, yet elegant, mean of reacting to JMX events. JmxBuilder supports two closure signatures:
JmxBuilder executes the closure and passes no information about the event that was captured on the bus.
JmxBuilder will pass an "event" object to the closure using this format. The event object contains information about the event was intercepted so that it can be handled by the handler. The parameter will contain different set of info depending on the event that was captured.
When describing attributes (see bean() node section above), you can provide a closure (or method pointer) for callback to be executed when the value of the attribute is updated on the exported MBean. This gives developers an opportunity to listen to and react to state changes on the MBean.
The sample snippet above shows how to specify an "onChange" callback closure when describing MBean attributes. In this sample code, whenever attribute "Resource" is updated via the exported MBean, the onChange event will be executed.
When handling the attribute onChange event, the handler closure will receive an event object with the following info:
Similar to mbean attributes, JmxBuilder affords developers the ability to listen for operation invokation on an MBean registered in the MBeaServer. JmxBuilder accepts a callback closure that will be executed after the MBean method has invoked.
The snippet above shows how to declare an "onCall" closure to be used as listener when operation "start()" is invoked on the MBean. This sample uses the method pointer syntax to illustrate the versatility of JmxBuilder.
When handling the operation onCall event, the callback closure will receive an event object with the following info:
When you export an MBean with the bean() node, you can define events the MBean can listen and react to. The bean() node provides a "listeners:" attribute that lets you define event listeners that your bean can react to.
In the sample above, we see the syntax for adding listeners to an exported MBean.
You can also specify an event type you are interested in receiving from a broadcaster (since a broadcaster can be emitting multiple events).
In some cases, you will want to create stand-alone event listensers (not attached to exported MBeans). JmxBuilder provides the Listener() node to let you create JMX listeners that can listen to MBeanServer events. This is useful when creating JMX client applications to monitor/manage JMX agents on remote JMX MBeanServers.
Here is the description of the lisetener() node attributes:
Here is an example of JmxBuilder's listener node:
This example shows how you can use a stand alone listener (outside of an MBean export). Here, we export a timer with a 1 second resolution. Then, we specify a listener to that timer that will print "beep" every second.
JmxBuilder provides the tools needed to broadcast your own events on the MBeanServer's event bus. There are no restrictions on the event type you can broadcast. You simply declare your emitter and the event type that you want to send, then broadcast your event at any time. Any registered component in the MBeanServer can register themselves to listen to your events.
The attributes for the node Emitter() can be summarized as follows:
The snippet declares the emitter using implicit descriptor syntax. JmxBuilder will do the followings:
As with other nodes in the builder, you can override all keys in the emitter() node. You can specify the ObjectName and the event type.
Once you have declared your emitter, you can broadcast your event.
The sample above shows the emitter sending an event, once it has been declared. Any JMX component registered in the MBeanServer can register to receive message from this emitter.
You can optionally pass data to the receiver when you send the message.
If you use an event listener closure (see above) that accpets a parameter, you can access that value.