Introducing JMX Builder for Groovy

After I attended the Groovy/Grails Experience in February this year, I realize that the Groovy builder pattern can be used to façade many other API's (not just Swing). So, I decide to create, yet another builder, for the JMX API and here it is!

http://code.google.com/p/groovy-jmx-builder/

Jmx Builder is a DSL designed to work with the Java Management Extension (JMX) API. Jmx Builder uses the builder pattern to facilitate the capturing and exposing of beans for runtime control and management via the MBean server.The Groovy JMX Builder DSL hides the complexity of working with the JMX API by providing a set of natural constructs to decorate your beans for management via JMX.

Features

  • Ability to expose any class instance for management including Java and Groovy classes.
  • No need to implement a specific management interface.
  • Shield developer from complexity of JMX API
  • Uses familiar Groovy builder pattern
  • Exposes attribute, constructors, operations, parameters

Example

The following example shows how you can use Groovy JMX Builder to expose a regular Java class for management into the MBean Server.

Suppose you have a Java class that represent a Greeting service and want to expose it for management:

public class Greeter {
private String name;
private String language = "en";

// ... code omitted

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

// ... code omitted

public String greet(){
String greet = (String) (langs.containsKey(getLanguage()) ?
langs.get(getLanguage()) : langs.get("en"));
return greet + " " + getName();
}

String greet(String person){
return langs.get(language) + " " + person
}
}

 

Now, to expose the instance as a management bean using JmxBuilder()

def greeter = new Greeter()
JmxBuilder jmx = new JmxBuilder()
def server = jmx.export(svr){
bean(greeter){
name("greeterDemo:service=greeting")
desc("This service prints a greeting on console")
attribute(name:"name", desc:"name of person to greet", writable:true)
attribute(name:"language", desc:"the language to use", editable:true)
operation(name:"greet", desc:"Sends greeting to user")
operation(name:"greet", desc:"Send greeting to user"){
parameter(type:"java.lang.String", name:"Person", desc:"The person to send greeting to")
}
}

bean(object:greeter, name:"greeterDemo:service=greeting2")
}

 

Using JmxBuilder

The code above shows two ways to expose your bean for management. The first one is the explicit way where all manageable members of the bean instance is declared for management.

  1. The export() node is the top outer most node and takes an optional MBean server instance as parameter
  2. The bean() takes the instance of the object being exposed as parameter
  3. In this context, the builder requires a valid JMX name
  4. Each line specifies either an attribute, constructor, and operation
  5. Both constructor and operation support parameter nodes to describe method params.

The second way is to simply declare the bean with

bean(object:greeter, name:"greeterDemo:service=greeting2")

JmxBuilder() will automatically expose all public members of the bean for managment.

JConsole

Once the bean is exposed, you can see how the information captured with JmxBuilder() is represented in the MBeanServer using a JMX client like JConsole

JConsole

 

Download JmxBuilder

So, visit the project's website and download the binary at http://code.google.com/p/groovy-jmx-builder/. Report all bugs or issues at the project's site under the "Issues" tab.

More to come...

0

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Andres Almiray replied on Wed, 2008/04/09 - 6:40pm

Seems like the last bean() call creates a clone of greeter an assigns it to a new name. It looks kind of odd that the first definition requires a nested name() node, while the second uses a 'name' property. I think both beans should use the same approach (nested name node, name property) unless your plan is to support both versions.

Also, now that you have a builder in place you can eliminate some repetition, like allowing nested attributes, operations nodes

bean( target: greeter, // or simply bean(greeter)
name: "greeterDemo:service=greeting",
desc: "This service prints a greeting on console" ) {
attributes {
name( desc: "name of person to greet", writable:true )
// perhaps make desc the default attribute, allowing thus
language( "the language to use", editable:true )
}
operations {
greet( desc:"Sends greeting to user" )
// sames as above
greet( "Sends greeting to user" ){
// if parameters are the only nodes that can be nested in an operation then
Person( "The person to send greeting to", type: "java.lang.String" )
// type may also be a fqn Class, the node should convert it to a String if needed
// note that the parameter name is capitalized
}
}
}

If the builder is based in FBS then the factories will handle all contextual information. One more thing, what is the output of export()? it looks like srv == server

Vladimir replied on Thu, 2008/04/10 - 9:06am in response to: aalmiray

Andres, thanks for the feedback.  Your suggestion on reducing the verbosity of the nodes is great.  I will definately incorporate your input into the api for its next release.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.