Skip to content
Skip to breadcrumbs
Skip to header menu
Skip to action menu
Skip to quick search
Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Sign Up
Dashboard
Groovy
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Page Layout
No Layout
Two column (simple)
Two column (simple, left sidebar)
Two column (simple, right sidebar)
Three column (simple)
Two column
Two column (left sidebar)
Two column (right sidebar)
Three column
Three column (left and right sidebars)
Undo
Redo
Find/Replace
Keyboard Shortcuts Help
<h2>Introduction</h2> <p>Given that Groovy sits directly on top of Java, Groovy can leverage the tremendous amount of work already done for <a href="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/">JMX</a> with Java. In addition, Groovy provides a <code>GroovyMBean</code> class which makes an <em>MBean</em> look like a normal Groovy object. This simplifies Groovy code for interacting with MBeans. For example, the following code:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> println server.getAttribute(beanName, 'Age') server.setAttribute(beanName, new Attribute('Name', 'New name')) Object[] params = [5, 20] String[] signature = [Integer.TYPE, Integer.TYPE] println server.invoke(beanName, 'add', params, signature) </pre></td></tr></table> <p>can be simplified to:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def mbean = new GroovyMBean(server, beanName) println mbean.Age mbean.Name = 'New name' println mbean.add(5, 20) </pre></td></tr></table> <p>The remainder of this page shows you how to:</p> <ul> <li>Monitor the JVM using MXBeans</li> <li>Monitor Apache Tomcat and display statistics</li> <li>Monitor Oracle OC4J and display information</li> <li>Monitor BEA WebLogic and display information</li> <li>Leverage Spring's MBean annotation support to export your Groovy beans as MBeans</li> </ul> <p>Note: many of the examples on this page use Java 5 which incorporates JMX 1.2 (more recent versions if JMX or Java will also work). In some cases, you can run some of these examples using Java 1.4 by including a version of JMX on your CLASSPATH. MX4J is bundled with the full distribution of Groovy. In most cases, you can delete this jar from your distribution <code>lib</code> directory if you are running with Java 5 or above (in fact you might have to - see the Troubleshooting section below).</p> <h2>Monitoring the JVM</h2> <p>MBeans are not accessed directly by an application but are managed by a repository called an <em>MBean server</em>. Java 5 and above includes a special MBean server called the <em>platform MBean server</em>, which is built into the JVM. Platform MBeans are registered in this server using unique names.</p> <p>You can monitor the JVM through its platform MBeans with the following code:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> import java.lang.management.* def os = ManagementFactory.operatingSystemMXBean println """OPERATING SYSTEM: \tarchitecture = $os.arch \tname = $os.name \tversion = $os.version \tprocessors = $os.availableProcessors """ def rt = ManagementFactory.runtimeMXBean println """RUNTIME: \tname = $rt.name \tspec name = $rt.specName \tvendor = $rt.specVendor \tspec version = $rt.specVersion \tmanagement spec version = $rt.managementSpecVersion """ def cl = ManagementFactory.classLoadingMXBean println """CLASS LOADING SYSTEM: \tisVerbose = ${cl.isVerbose()} \tloadedClassCount = $cl.loadedClassCount \ttotalLoadedClassCount = $cl.totalLoadedClassCount \tunloadedClassCount = $cl.unloadedClassCount """ def comp = ManagementFactory.compilationMXBean println """COMPILATION: \ttotalCompilationTime = $comp.totalCompilationTime """ def mem = ManagementFactory.memoryMXBean def heapUsage = mem.heapMemoryUsage def nonHeapUsage = mem.nonHeapMemoryUsage println """MEMORY: HEAP STORAGE: \tcommitted = $heapUsage.committed \tinit = $heapUsage.init \tmax = $heapUsage.max \tused = $heapUsage.used NON-HEAP STORAGE: \tcommitted = $nonHeapUsage.committed \tinit = $nonHeapUsage.init \tmax = $nonHeapUsage.max \tused = $nonHeapUsage.used """ ManagementFactory.memoryPoolMXBeans.each{ mp -> println "\tname: " + mp.name String[] mmnames = mp.memoryManagerNames mmnames.each{ mmname -> println "\t\tManager Name: $mmname" } println "\t\tmtype = $mp.type" println "\t\tUsage threshold supported = " + mp.isUsageThresholdSupported() } println() def td = ManagementFactory.threadMXBean println "THREADS:" td.allThreadIds.each { tid -> println "\tThread name = ${td.getThreadInfo(tid).threadName}" } println() println "GARBAGE COLLECTION:" ManagementFactory.garbageCollectorMXBeans.each { gc -> println "\tname = $gc.name" println "\t\tcollection count = $gc.collectionCount" println "\t\tcollection time = $gc.collectionTime" String[] mpoolNames = gc.memoryPoolNames mpoolNames.each { mpoolName -> println "\t\tmpool name = $mpoolName" } } </pre></td></tr></table> <p><br class="atl-forced-newline" /> When run, you will see something like this:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> OPERATING SYSTEM: architecture = x86 name = Windows XP version = 5.1 processors = 2 RUNTIME: name = 620@LYREBIRD spec name = Java Virtual Machine Specification vendor = Sun Microsystems Inc. spec version = 1.0 management spec version = 1.0 CLASS LOADING SYSTEM: isVerbose = false loadedClassCount = 919 totalLoadedClassCount = 919 unloadedClassCount = 0 COMPILATION: totalCompilationTime = 91 MEMORY: HEAP STORAGE: committed = 3108864 init = 0 max = 66650112 used = 1994728 NON-HEAP STORAGE: committed = 9240576 init = 8585216 max = 100663296 used = 5897880 name: Code Cache Manager Name: CodeCacheManager mtype = Non-heap memory Usage threshold supported = true name: Eden Space Manager Name: MarkSweepCompact Manager Name: Copy mtype = Heap memory Usage threshold supported = false name: Survivor Space Manager Name: MarkSweepCompact Manager Name: Copy mtype = Heap memory Usage threshold supported = false name: Tenured Gen Manager Name: MarkSweepCompact mtype = Heap memory Usage threshold supported = true name: Perm Gen Manager Name: MarkSweepCompact mtype = Non-heap memory Usage threshold supported = true THREADS: Thread name = Monitor Ctrl-Break Thread name = Signal Dispatcher Thread name = Finalizer Thread name = Reference Handler Thread name = main GARBAGE COLLECTION: name = Copy collection count = 60 collection time = 141 mpool name = Eden Space mpool name = Survivor Space name = MarkSweepCompact collection count = 0 collection time = 0 mpool name = Eden Space mpool name = Survivor Space mpool name = Tenured Gen mpool name = Perm Gen </pre></td></tr></table> <p><br class="atl-forced-newline" /></p> <h2>Monitoring Tomcat</h2> <p>First start up <a href="http://tomcat.apache.org/">Tomcat</a> with JMX monitoring enabled by setting the following:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> set JAVA_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9004 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false </pre></td></tr></table> <p><br class="atl-forced-newline" /> You can do this in your startup script and may choose any available port - we used 9004.<br /> The following code uses JMX to discover the available MBeans in the running Tomcat, determine which are web modules, extract the processing time for each web module and displays the result in a graph using JFreeChart:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> import javax.management.ObjectName import javax.management.remote.JMXConnectorFactory as JmxFactory import javax.management.remote.JMXServiceURL as JmxUrl import org.jfree.chart.ChartFactory import org.jfree.data.category.DefaultCategoryDataset as Dataset import org.jfree.chart.plot.PlotOrientation as Orientation import groovy.swing.SwingBuilder import javax.swing.WindowConstants as WC def serverUrl = 'service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi' def server = JmxFactory.connect(new JmxUrl(serverUrl)).MBeanServerConnection def serverInfo = new GroovyMBean(server, 'Catalina:type=Server').serverInfo println "Connected to: $serverInfo" def query = new ObjectName('Catalina:*') String[] allNames = server.queryNames(query, null) def modules = allNames.findAll{ name -> name.contains('j2eeType=WebModule') }.collect{ new GroovyMBean(server, it) } println "Found ${modules.size()} web modules. Processing ..." def dataset = new Dataset() modules.each{ m -> println m.name() dataset.addValue m.processingTime, 0, m.path } def labels = ['Time per Module', 'Module', 'Time'] def options = [false, true, true] def chart = ChartFactory.createBarChart(*labels, dataset, Orientation.VERTICAL, *options) def swing = new SwingBuilder() def frame = swing.frame(title:'Catalina Module Processing Time', defaultCloseOperation:WC.EXIT_ON_CLOSE) { panel(id:'canvas') { rigidArea(width:600, height:250) } } frame.pack() frame.show() chart.draw(swing.canvas.graphics, swing.canvas.bounds) </pre></td></tr></table> <p><br class="atl-forced-newline" /> When run, we will see a trace of progress being made:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> Connected to: Apache Tomcat/6.0.13 Found 5 web modules. Processing ... Catalina:j2eeType=WebModule,name=//localhost/,J2EEApplication=none,J2EEServer=none Catalina:j2eeType=WebModule,name=//localhost/host-manager,J2EEApplication=none,J2EEServer=none Catalina:j2eeType=WebModule,name=//localhost/docs,J2EEApplication=none,J2EEServer=none Catalina:j2eeType=WebModule,name=//localhost/examples,J2EEApplication=none,J2EEServer=none Catalina:j2eeType=WebModule,name=//localhost/manager,J2EEApplication=none,J2EEServer=none </pre></td></tr></table> <p><br class="atl-forced-newline" /> The output will look like this:<br /> <img class="confluence-embedded-image" src="/download/attachments/231082410/catalina.gif?version=1&modificationDate=1371725511713" data-image-src="/download/attachments/231082410/catalina.gif?version=1&modificationDate=1371725511713" data-linked-resource-id="231377412" data-linked-resource-type="attachment" data-linked-resource-default-alias="catalina.gif" data-base-url="http://docs.codehaus.org" data-linked-resource-container-id="231082410" title="null > catalina.gif"></p> <p>Note: if you get errors running this script, see the <strong>Troubleshooting</strong> section below.</p> <h2>OC4J Example</h2> <p>Here is a script to access <a href="http://www.oracle.com/technology/products/oc4j">OC4J</a> and print out some information about the server, its runtime and (as an example) the configured JMS destinations:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> import javax.management.remote.* import oracle.oc4j.admin.jmx.remote.api.JMXConnectorConstant def serverUrl = new JMXServiceURL('service:jmx:rmi://localhost:23791') def serverPath = 'oc4j:j2eeType=J2EEServer,name=standalone' def jvmPath = 'oc4j:j2eeType=JVM,name=single,J2EEServer=standalone' def provider = 'oracle.oc4j.admin.jmx.remote' def credentials = [ (JMXConnectorConstant.CREDENTIALS_LOGIN_KEY): 'oc4jadmin', (JMXConnectorConstant.CREDENTIALS_PASSWORD_KEY): 'admin' ] def env = [ (JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES): provider, (JMXConnector.CREDENTIALS): credentials ] def server = JmxFactory.connect(serverUrl, env).MBeanServerConnection def serverInfo = new GroovyMBean(server, serverPath) def jvmInfo = new GroovyMBean(server, jvmPath) println """Connected to $serverInfo.node. \ Server started ${new Date(serverInfo.startTime)}. OC4J version: $serverInfo.serverVersion from $serverInfo.serverVendor JVM version: $jvmInfo.javaVersion from $jvmInfo.javaVendor Memory usage: $jvmInfo.freeMemory bytes free, \ $jvmInfo.totalMemory bytes total """ def query = new javax.management.ObjectName('oc4j:*') String[] allNames = server.queryNames(query, null) def dests = allNames.findAll{ name -> name.contains('j2eeType=JMSDestinationResource') }.collect{ new GroovyMBean(server, it) } println "Found ${dests.size()} JMS destinations. Listing ..." dests.each{ d -> println "$d.name: $d.location" } </pre></td></tr></table> <p>Here is the result of running this script:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> Connected to LYREBIRD. Server started Thu May 31 21:04:54 EST 2007. OC4J version: 11.1.1.0.0 from Oracle Corp. JVM version: 1.6.0_01 from Sun Microsystems Inc. Memory usage: 8709976 bytes free, 25153536 bytes total Found 5 JMS destinations. Listing ... Demo Queue: jms/demoQueue Demo Topic: jms/demoTopic jms/Oc4jJmsExceptionQueue: jms/Oc4jJmsExceptionQueue jms/RAExceptionQueue: jms/RAExceptionQueue OracleASRouter_store: OracleASRouter_store </pre></td></tr></table> <p>As a slight variation, this script displays a pie chart of memory usage using JFreeChart:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> import org.jfree.chart.ChartFactory import javax.swing.WindowConstants as WC import javax.management.remote.* import oracle.oc4j.admin.jmx.remote.api.JMXConnectorConstant def url = 'service:jmx:rmi://localhost:23791' def credentials = [:] credentials[JMXConnectorConstant.CREDENTIALS_LOGIN_KEY] = "oc4jadmin" credentials[JMXConnectorConstant.CREDENTIALS_PASSWORD_KEY] = "password" def env = [:] env[JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES] = "oracle.oc4j.admin.jmx.remote" env[JMXConnector.CREDENTIALS] = credentials def server = JMXConnectorFactory.connect(new JMXServiceURL(url), env).MBeanServerConnection def jvmInfo = new GroovyMBean(server, 'oc4j:j2eeType=JVM,name=single,J2EEServer=standalone') def piedata = new org.jfree.data.general.DefaultPieDataset() piedata.setValue "Free", jvmInfo.freeMemory piedata.setValue "Used", jvmInfo.totalMemory - jvmInfo.freeMemory def options = [true, true, true] def chart = ChartFactory.createPieChart('OC4J Memory Usage', piedata, *options) chart.backgroundPaint = java.awt.Color.white def swing = new groovy.swing.SwingBuilder() def frame = swing.frame(title:'OC4J Memory Usage', defaultCloseOperation:WC.EXIT_ON_CLOSE) { panel(id:'canvas') { rigidArea(width:350, height:250) } } frame.pack() frame.show() chart.draw(swing.canvas.graphics, swing.canvas.bounds) </pre></td></tr></table> <p><br class="atl-forced-newline" /> Which looks like:<br /> <img class="confluence-embedded-image" src="/download/attachments/231082410/oc4jpie.gif?version=1&modificationDate=1371725511708" data-image-src="/download/attachments/231082410/oc4jpie.gif?version=1&modificationDate=1371725511708" data-linked-resource-id="231377411" data-linked-resource-type="attachment" data-linked-resource-default-alias="oc4jpie.gif" data-base-url="http://docs.codehaus.org" data-linked-resource-container-id="231082410" title="null > oc4jpie.gif"></p> <h2>WebLogic Example</h2> <p>This script prints out information about the server followed by information about JMS Destinations (as an example). Many other mbeans are <a href="http://edocs.bea.com/wls/docs100/wlsmbeanref/index.html">available</a>.</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> import javax.management.remote.* import javax.management.* import javax.naming.Context def urlRuntime = '/jndi/weblogic.management.mbeanservers.runtime' def urlBase = 'service:jmx:t3://localhost:7001' def serviceURL = new JMXServiceURL(urlBase + urlRuntime) def h = new Hashtable() h.put(Context.SECURITY_PRINCIPAL, 'weblogic') h.put(Context.SECURITY_CREDENTIALS, 'weblogic') h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, 'weblogic.management.remote') def server = JMXConnectorFactory.connect(serviceURL, h).MBeanServerConnection def domainName = new ObjectName('com.bea:Name=RuntimeService,' + 'Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean') def rtName = server.getAttribute(domainName, 'ServerRuntime') def rt = new GroovyMBean(server, rtName) println "Server: name=$rt.Name, state=$rt.State, version=$rt.WeblogicVersion" def destFilter = Query.match(Query.attr('Type'), Query.value('JMSDestinationRuntime')) server.queryNames(new ObjectName('com.bea:*'), destFilter).each{ name -> def jms = new GroovyMBean(server, name) println "JMS Destination: name=$jms.Name, type=$jms.DestinationType"+ ", messages=$jms.MessagesReceivedCount" } </pre></td></tr></table> <p>Here is the output:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> Server: name=examplesServer, state=RUNNING, version=WebLogic Server 10.0 Wed May 9 18:10:27 EDT 2007 933139 JMS Destination: name=examples-jms!exampleTopic, type=Topic, messages=0 JMS Destination: name=examples-jms!exampleQueue, type=Queue, messages=0 JMS Destination: name=examples-jms!jms/MULTIDATASOURCE_MDB_QUEUE, type=Queue, messages=0 JMS Destination: name=examplesJMSServer!examplesJMSServer.TemporaryQueue0, type=Queue, messages=68 JMS Destination: name=examples-jms!quotes, type=Topic, messages=0 JMS Destination: name=examples-jms!weblogic.wsee.wseeExamplesDestinationQueue, type=Queue, messages=0 JMS Destination: name=examples-jms!weblogic.examples.ejb30.ExampleQueue, type=Queue, messages=0 </pre></td></tr></table> <h2>Spring Example</h2> <p>You can also use Spring to automatically register beans as JMX aware.</p> <p>Here is an example class (Calculator.groovy):</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> import org.springframework.jmx.export.annotation.* @ManagedResource(objectName="bean:name=calcMBean", description="Calculator MBean") public class Calculator { private int invocations @ManagedAttribute(description="The Invocation Attribute") public int getInvocations() { return invocations } private int base = 10 @ManagedAttribute(description="The Base to use when adding strings") public int getBase() { return base } @ManagedAttribute(description="The Base to use when adding strings") public void setBase(int base) { this.base = base } @ManagedOperation(description="Add two numbers") @ManagedOperationParameters([ @ManagedOperationParameter(name="x", description="The first number"), @ManagedOperationParameter(name="y", description="The second number")]) public int add(int x, int y) { invocations++ return x + y } @ManagedOperation(description="Add two strings representing numbers of a particular base") @ManagedOperationParameters([ @ManagedOperationParameter(name="x", description="The first number"), @ManagedOperationParameter(name="y", description="The second number")]) public String addStrings(String x, String y) { invocations++ def result = Integer.valueOf(x, base) + Integer.valueOf(y, base) return Integer.toString(result, base) } } </pre></td></tr></table> <p><br class="atl-forced-newline" /> Here is the Spring configuration file (beans.xml):</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"> <property name="locateExistingServerIfPossible" value="true"/> </bean> <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> <property name="assembler" ref="assembler"/> <property name="namingStrategy" ref="namingStrategy"/> <property name="beans"> <map> <entry key="bean:name=defaultCalcName" value-ref="calcBean"/> </map> </property> <property name="server" ref="mbeanServer"/> <property name="autodetect" value="true"/> </bean> <bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/> <!-- will create management interface using annotation metadata --> <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"> <property name="attributeSource" ref="jmxAttributeSource"/> </bean> <!-- will pick up the ObjectName from the annotation --> <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy"> <property name="attributeSource" ref="jmxAttributeSource"/> </bean> <bean id="calcBean" class="Calculator"> <property name="base" value="10"/> </bean> </beans> </pre></td></tr></table> <p><br class="atl-forced-newline" /> Here is a script which uses this bean and configuration:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> import org.springframework.context.support.ClassPathXmlApplicationContext import java.lang.management.ManagementFactory import javax.management.ObjectName import javax.management.Attribute // get normal bean def ctx = new ClassPathXmlApplicationContext("beans.xml") def calc = ctx.getBean("calcBean") Thread.start{ // access bean via JMX, use a separate thread just to // show that we could access remotely if we wanted def server = ManagementFactory.platformMBeanServer def mbean = new GroovyMBean(server, 'bean:name=calcMBean') sleep 1000 assert 8 == mbean.add(7, 1) mbean.Base = 8 assert '10' == mbean.addStrings('7', '1') mbean.Base = 16 sleep 2000 println "Number of invocations: $mbean.Invocations" println mbean } assert 15 == calc.add(9, 6) assert '11' == calc.addStrings('10', '1') sleep 2000 assert '20' == calc.addStrings('1f', '1') </pre></td></tr></table> <p><br class="atl-forced-newline" /> And here is the resulting output:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> Number of invocations: 5 MBean Name: bean:name=calcMBean Attributes: (rw) int Base (r) int Invocations Operations: int add(int x, int y) java.lang.String addStrings(java.lang.String x, java.lang.String y) int getInvocations() int getBase() void setBase(int p1) </pre></td></tr></table> <p><br class="atl-forced-newline" /> You can even attach to the process while it is running with <a href="http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html">jconsole</a>. It will look something like:<br /> !jconsole.gif!We started the Groovy application with the <code>-Dcom.sun.management.jmxremote</code> JVM argument using a Java 5 JVM.</p> <p>See also:</p> <ul> <li><a class="confluence-link" href="/display/GROOVY/Dynamic+language+beans+in+Spring" data-linked-resource-id="67574" data-linked-resource-type="page" data-linked-resource-default-alias="Dynamic language beans in Spring" data-base-url="http://docs.codehaus.org">Dynamic language beans in Spring</a></li> <li><a class="confluence-link" href="/display/GROOVY/Using+Spring+Factories+with+Groovy" data-linked-resource-id="79513" data-linked-resource-type="page" data-linked-resource-default-alias="Using Spring Factories with Groovy" data-base-url="http://docs.codehaus.org">Using Spring Factories with Groovy</a></li> <li><a href="http://static.springframework.org/spring/docs/2.1.x/reference/jmx.html">Spring JMX Documentation</a></li> </ul> <h2>Troubleshooting</h2> <h3>groovy.lang.MissingMethodException or groovy.lang.GroovyRuntimeException</h3> <p>If you get an error like this</p> <table class="wysiwyg-macro" data-macro-name="noformat" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e25vZm9ybWF0fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> groovy.lang.MissingMethodException: No signature of method: javax.management.remote.rmi.RMIConnector$RemoteMBeanServerConnection.queryMBeans() is applicable for argument types: (javax.management.ObjectName, null) values: {Catalina:*, null} </pre></td></tr></table> <p>or like this:</p> <table class="wysiwyg-macro" data-macro-name="noformat" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e25vZm9ybWF0fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> Caught: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: groovy.util.GroovyMBean(javax.management.remote.rmi.RMIConnector$RemoteMBeanServerConnection, java.lang.String) </pre></td></tr></table> <p>you have to move away or delete "mx4j-*.jar" from "$GROOVY_HOME/lib". MX4J is designed to add <code>javax.management</code> classes to 1.4 JVMs. If you already have a newer JMX jar on your classpath or are using a Java 5 or higher JVM, the MX4J classes will be incompatible with the ones from the newer Sun JVMs or newer versions of JMX.</p> <h3>java.lang.SecurityException</h3> <p>If you get the following error, your container's JMX access is password protected:</p> <table class="wysiwyg-macro" data-macro-name="noformat" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e25vZm9ybWF0fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> java.lang.SecurityException: Authentication failed! Credentials required </pre></td></tr></table> <p>To fix that, add an environment with the credentials when connecting, like this (password has to be set before that):</p> <table class="wysiwyg-macro" data-macro-name="noformat" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e25vZm9ybWF0fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def jmxEnv = null if (password != null) jmxEnv = [(JMXConnector.CREDENTIALS): (String[])["monitor", password]] def connector = JMXConnectorFactory.connect(new JMXServiceURL(serverUrl), jmxEnv) </pre></td></tr></table> <p>Details for the software you are trying to monitor/manage may differ slightly. Check out the other examples using credentials above if appropriate (e.g. OC4J and WebLogic). If you still have troubles, you will have to consult the documentation for the software you are trying to monitor/manage for details on how to provide credentials.</p> <h2>Further JMX Information</h2> <ul> <li><a class="confluence-link" href="/display/GROOVY/Groovy+JmxBuilder" data-linked-resource-id="114787596" data-linked-resource-type="page" data-linked-resource-default-alias="Groovy JmxBuilder" data-base-url="http://docs.codehaus.org">Groovy JmxBuilder</a></li> <li><a href="http://www.ddj.com/dept/java/184406481?pgno=1">Monitoring the Java Virtual Machine</a></li> <li><a href="http://buttso.blogspot.com/2006/05/using-groovy-for-system-management.html">Using Groovy for System Management</a></li> <li><a href="http://jmesnil.net/weblog/2007/03/23/jmx-scripts-using-jruby/">JMX Scripts using JRuby - Part I</a></li> <li><a href="http://jmesnil.net/weblog/2007/04/03/jmx-scripts-using-jruby-part-ii/">JMX Scripts using JRuby - Part II</a></li> <li><a href="http://blogs.sun.com/sundararajan/entry/groovier_jconsole">Groovier jconsole!</a></li> <li><a href="http://jmesnil.net/weblog/2007/05/23/jmx-scripts-with-eclipse-monkey/">JMX Scripts with Eclipse Monkey</a></li> <li><a href="http://activemq.apache.org/jmx.html">Using JMX to monitor Apache ActiveMQ</a></li> <li><a href="http://jagger.berlios.de/">Jagger project (JMX application monitoring with Groovy)</a></li> </ul>
Please type the word appearing in the picture.
Attachments
Labels
Location
Watch this page
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced