Instantiating the BuilderTo start using JmxBuilder, simply make sure the jar file is on your class path. Then you can do the following in your code def jmx = new JmxBuilder() That's it! You are now ready to use the JmxBuilder. NOTE: - You can pass in an instance of your own MBeanServer to the builder (new JmxBuilder(MBeanServer))
- If no MBeanServer is specified, the builder instance will default to the underlying platform MBeanServer.
ConnectorsRemote connectivity is a crucial part of the JMX architecture. JmxBuilder facilitates the creation of connector servers and connector clients with merely one line of code. Create a Connector Server jmx.connectorServer(port: 9000).start() 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" JmxBuilder.connectoServer() supports the full Connector api syntax and will let you specify properties, override the URL, specify your own host, etc. Create a Connector Clientdef client = jmx.clientConnector(port: 9000)
client.connect() Creating a connector client is just as easy. With one line of code, you can create an instance of a ConnectorClinet as shown above. You can then access the MBeanServerConnection associated with the connector using: client.getMBeanServerConnection()
JmxBuilder MBean ExportYou can export a Java object or a Groovy object with minimal coding. JmxBuilder will even find and export dynamic Groovy methods injected at runtime. Implicit vs Explicit DescriptorsWhen 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. JmxBuilder.export()The JmxBuilder.export() node provides a container where all management entities to be exported to the MBeanServer can be placed. You can place one or more bean() or timer() nodes in export(). Then, JmxBuilder will automatically batch and export the entities described by these nodes to the MBean server for management. def beans = jmx.export {
bean(new Foo())
bean(new Bar())
bean(new SomeBar())
} In the code snippet above, JmxBuilder.export() will export three management beans to the MBean server. Integration with GroovyMBeanWhen you export an MBean to the MBeanServer, JmxBuilder will return an instance of GroovyMBean representing the management bean that was exported. Nodes such as bean() and timer() will return an instance of GroovyMBean when export of the components they represent are completed. export() will return an array of all of GroovyMBean representing all managed objects exported to the MBean server. Example ObjectThis reference uses a class RequestController to illustrate how to use JmxBuilder to export runtime management beans. The class is for illustration purpose and how it is implemented is immaterial. RequestController public class RequestController {
public RequestCopntroller()
public RequestController(Object resource)
public void start(){ //... }
public void stop(){ //... }
public boolean isStarted() { //... }
public Object getResource(){ ... }
public void setResource(Object res) { //... }
public int getRequestCount(){ //... }
public void makeRequest(String res) { ... }
}
Implicit ExportAs 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 defaults. These default values can easily be overridden as we'll see in this in the next section. The Simplest ExportThe simplest way to export a POJO or POGO is listed below. jmx.export {
bean(new RequestController(resource:"Hello World"))
} What it does: - First, the JmxBuilder.export() node will export an MBean to the MBeanServer representing the declared POJO instance.
- The builder will generate a default ObjectName for the MBean and all other MBean descriptor information.
- JmxBuilder will automatically export all declared attributes (MBean getter/setters), constructors, and operations on the instance.
- The exported attributes will have read-only visibility.
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). JConsole view of Exported Bean
Overriding the ObjectNameThis is a variation of the implicit export. However, here the beans ObjectName is to provided to override the default name. def ctrl = new RequestController(resource:"Hello World")
def beans = jmx.export {
bean(target:ctrl, name:"jmx.tutorial:type=Object")
}This code snippet shows that you can explicitly provide a JMX ObjectName for the MBean being exported along with the object instance. The behavior is the same as before.
Attribute ExportJMX 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. Exporting All Attributes with Wildcard "*"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. def objName = new ObjectName("jmx.tutorial:type=Object")
def beans = jmx.export {
bean(target: new RequestController(), name: objName, attributes: "*")
}Export Attribute ListJmxBuilder will let you specify a list of attributes to export. def objName = new ObjectName("jmx.tutorial:type=Object")
def beans = jmx.export {
bean(target: new RequestController(), name: objName, attributes: ["Resource","RequestCount"])
}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. Export Attribute with Explicit DescriptorsOne 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. def objName = new ObjectName("jmx.tutorial:type=Object")
def beans = jmx.export {
bean(target: new RequestController(), name: objName,
attributes: [
"Resource":[desc: "The resource to request.", readable: true, writeable: true, defaultValue:"Hello"],
"RequestCount":"*"
]
)
}In this snippet, attribute "Resource" is fully-described using all supported descriptors (i.e. desc, readable, writable, defaultValue) for an attribute. RequestCount will be exported and described using defaults. Constructor ExportJmxBuilder supports the explicit description and export of constructors of declared in the underlying bean. There several options available when exporting constructors. You can combine them however you want to achieve the desired level of visibility. Export all Constructors with "*"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. def objName = new ObjectName("jmx.tutorial:type=Object")
def beans = jmx.export {
bean(target: new RequestController(), name: objName, constructors: "*")
}Export Constructors using Parameter DescriptorJmxBuilder lets you target specific constructor to export by describing their parameter signature. This is useful when you have several constructors with different parameter signature that you want to export. def objName = new ObjectName("jmx.tutorial:type=Object")
def beans = jmx.export {
bean(target: new RequestController(), name: objName,
constructors:["RequestController":["Object"]]
)
}The code above will uses a short-hand notation to describe the constructor and parameter list to export. Here, JmxBuilder will export a constructor that takes one parameter of type "Object". Export Constructor using Detailed DescriptorsJmxBuilder allows you to fully-describe the constructor that you want to target for export. def objName = new ObjectName("jmx.tutorial:type=Object")
def beans = jmx.export {
bean(target: new RequestController(), name: objName,
constructors:[
"RequestController":[
desc:"Constructor takes param",
params:["Object":[name:"Resource", desc:"Resource for controller"]]
]
]
)
}In this code snippet we see how the constructor can be fully-described using all opetional descriptor keys.
Operation ExportSimilar to constructors, JmxBuilder supports the description and export of MBean operations using flexible notations. You can combine these notations however you want to achieve the level of operation visibility desired. Export all Operations with "*"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. def objName = new ObjectName("jmx.tutorial:type=Object")
def beans = jmx.export {
bean(target: new RequestController(), name: objName, operations: "*")
}In this snippet, JmxBuilder will export all bean operations using default descriptor info. Export Operation ListJmxBuilder has a shorthand notation that lets you quickly export operations by providing a list of methods to export. def objName = new ObjectName("jmx.tutorial:type=Object")
def beans = jmx.export {
bean(target: new RequestController(), name: objName, operations: ["start","stop"])
}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. Export Operations with Detailed DescriptorJmxBuilder supports detailed descriptors for bean operations. You can supply deep descriptor info about any operation on your bean including name, description, method parameters, parameter type, and parameter description. def objName = new ObjectName("jmx.tutorial:type=Object")
def beans = jmx.export {
bean(target: new RequestController(), name: objName,
operations: [
"start": [desc:"Starts request controller"],
"stop":[desc:"Stops the request controller"],
"setResource":[params:["Object"]],
"makeRequest": [
desc:"Executes the request.",
params: [
"String":[name:"Resource",desc:"The resource to request"]
]
]
]
)
}The snippet above shows all of the ways JmxBuilder allows you to export an operation. - start() and stop() are described by the "desc" key (this is enough since there are no params).
- setResource() we see the use of a shorthand version of params: to describe the parameters for the method.
- makeRequest() uses the the extended descriptor syntax to describe all aspects of the operation.
Timer ExportPart of the JMX standard components mandated by the API is the availability of timer service. Since JMX is a component-based architecture, timers provide an excellent signaling mechanism to communicate to registered components. JmxBuilder supports the creation and export of timers using the same easy syntax we've seen so far. Exporting a Timerjmx.timer(name: "jmx.builder:type=Timer", event: "heartbeat", period: "1s").start() This snippet above will describes, creates, and exports a standard JMX Timer. The timer() node will return a GroovyMBean that represents the timer registered with the MBeanServer. An alternative way of exporting timers is within the JmxBuilder.export() node. def beans = jmx.export {
timer(name: "jmx.builder:type=Timer1", event: "event.signal", period: "1s")
timer(name: "jmx.builder:type=Timer2", event: "event.log", period: "1s")
}
beans[0].start()
beans[1].start()Timer PeriodThe 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. - timer(period: 100) = 100 millisecond
- timer(period: "1s") = 1 second
- timer(period: "1m") = 1 minute
- timer(period: "1h") = 1 hour
- timer(period: "1d") = 1 day
The node will automatically translate.
JmxBuilder and EventsAn 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. Event Handling ClosuresJmxBuilder leverages Groovy's use of closures to provide simple, yet elegant, mean of reacting to JMX events. JmxBuilder supports two closure signatures: Parameterlesscallback = {->
// handle event
}JmxBuilder executes the closure and passes no information about the event that took place. With Event Parametercallback = {event ->
// handle event
}JmxBuilder will pass an "event" object to the closure that contains information about the event was intercepted. The parameter will contain different set of info depending on the event that was capture. Attribute onChange EventWhen describing attributes (see 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. jmx.export {
bean(
target: new RequestController(), name: "jmx.tutorial:type=Object",
attributes: [
"Resource":[readable: true, writeable: true,
onChange:{e ->
println e.oldValue
println e.newValue
}]
]
)
}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 on the MBean, the onChange event will be executed and print the previous and new value of the attribute. Operation onCall EventSimilar to the attribute, JmxBuilder affords developers the ability to listen for operation invokation. JmxBuilder accepts a callback closure that will be executed after the MBean method has invoked. class EventHandler {
void handleStart(e){
println e
}
}
def handler = new EventHandler()
def beans = jmx.export {
bean(target: new RequestController(), name: "jmx.tutorial:type=Object",
operations: [
"start": [
desc:"Starts request controller"
onCall:handler.&handleStart
]
]
)
}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. JMX Event ListenersJmxBuilder supports general JMX listeners to intercept any event on the MBeanServer bus. The listener node lets you specify the JMX event type, the source of the event, and a callback closure. JmxBuilder listeners use the same closure syntax we've mentioned in earlier. Listener MBeanWhen you export your MBean, you can specify event types the bean can listen and react to. def beans = jmx.export {
timer(name: "jmx.builder:type=Timer", event: "heartbeat", period: "1s").start()
bean(target: new RequestController(), name: "jmx.tutorial:type=Object",
operations: "*",
listeners: [
heartbeat:[
from:"jmx.builder:type=Timer",
call:{e ->
println e
}
]
]
)
}In the sample above, we see the syntax for adding listeners to an exported MBean. Fist, a timer is exported and started. Then an MBean is declared that will listen to the timer event and do something useful. The "heartbeat:" key name is arbitrary and has no correlation to the timer declared above. The source of the event is specified using the "from:" key. You can also specify an even type you are interested in receiving from the broadcaster (not shown). Stand-alone ListenerIf you just want to create a listener (without exporting an MBean) you can still do it with JmxBuilder. jmx.timer(name: "jmx.builder:type=Timer", period: "1s").start()
jmx.listener(
from: "jmx.builder:type=Timer",
call: {e ->
println "beep..."
}
)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. Emitting EventJmxBuilder provides the tools needed to broadcast events on the MBeanServer's event bus. There are no restrictions on the event type you can broadcast on the bus. 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 the event you broadcast. Declare the Emitterjmx.emitter() The snippet declares the emitter using implicit descriptor syntax. JmxBuilder will do the followings: - Create an emitter MBean with a default ObjectName.
- Setup a default event type with value "jmx.builder.event.emitter".
- Return a GroovyMBean representing the emitter.
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. Send EventOnce you have declared your emitter, you can broadcast your event. def emitter = jmx.emitter(name:"jmx.builder=type=Emitter")
...
emitter.send() The sample above shows the emitter sending an event, once it has been declared. JmxBuilder will register an emitter MBean with name "jmx.builder:type=Emitter". Any component registered in the MBeanServer can register to receive message from the emitter. You can optionally pass data to the receiver when you send the message. ...
emitter.send("Hello!")
...If you use an event listener closure (see above) that accpets a parameter, you can access that value.
|