In
my previous posts, I explained how to connect to JMX application using
jconsole. In this post, I am going to build a JMX client programatically.
Below
step-by-step procedure explains how to create custom JMX client.
Step 1: Create an RMI
Connector client and connect it to the RMI connector server.
JMXServiceURL
url = new
JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
JMXConnector
jmxc = JMXConnectorFactory.connect(url, null);
9999
is port number, where RMI connector server is listening to.
Step 2: Get an instance of
MBeanServerConnection from JMXConnector
MBeanServerConnection
mbsc = jmxc.getMBeanServerConnection();
Step 3: Get the MBean
instance using the object name.
ObjectName
mbeanName = new ObjectName("com.sample.mbeans:type=SystemStatisticsMBean");
SystemStatisticsMBean mbeanProxy =
JMX.newMBeanProxy(mbsc, mbeanName,
SystemStatisticsMBean.class, true);
That’s
it, now you can perform operations on SystemStatisticsMBean object.
Find
the below working application.
package com.sample.model; import java.io.Serializable; /** * Since it is consumed by JMX client, we need to serialize it. * * @author Krishna * */ public class CRUDStatistics implements Serializable { private static final long serialVersionUID = 1L; private int readCount = 0; private int writeCount = 0; public int getReadCount() { return readCount; } public void setReadCount(int readCount) { this.readCount = readCount; } public int getWriteCount() { return writeCount; } public void setWriteCount(int writeCount) { this.writeCount = writeCount; } }
SystemStatisticsMBean.java
package com.sample.mbeans; import com.sample.model.CRUDStatistics; public interface SystemStatisticsMBean { public void setReadCount(int readCount); public void setWriteCount(int writeCount); public CRUDStatistics getAppStats(); }
SystemStatistics.java
package com.sample.mbeans; import javax.management.Notification; import javax.management.NotificationBroadcasterSupport; import com.sample.model.CRUDStatistics; public class SystemStatistics extends NotificationBroadcasterSupport implements SystemStatisticsMBean { private CRUDStatistics appStats = new CRUDStatistics(); private static int sequenceNumber = 0; @Override public void setReadCount(int readCount) { Notification notification = new Notification("com.sample.mbeans.SystemStatistics", this, ++sequenceNumber, System.currentTimeMillis(), "Read Count is set to " + readCount); sendNotification(notification); appStats.setReadCount(readCount); } @Override public void setWriteCount(int writeCount) { Notification notification = new Notification("com.sample.mbeans.SystemStatistics", this, ++sequenceNumber, System.currentTimeMillis(), "Write Count is set to " + writeCount); sendNotification(notification); appStats.setWriteCount(writeCount); } @Override public CRUDStatistics getAppStats() { return appStats; } }
StatsAgent.java
package com.sample.agents; import java.io.IOException; import java.lang.management.ManagementFactory; import javax.management.InstanceAlreadyExistsException; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import com.sample.mbeans.SystemStatistics; public class StatsAgent { private MBeanServer mbs; private SystemStatistics mbean; public StatsAgent() throws MalformedObjectNameException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, IOException { ObjectName name = new ObjectName("com.sample.mbeans:type=SystemStatisticsMBean"); mbean = new SystemStatistics(); mbs = ManagementFactory.getPlatformMBeanServer(); mbs.registerMBean(mbean, name); } }
Application.java
package com.sample.app; import com.sample.agents.StatsAgent; public class Application { public static void main(String[] args) throws Exception { new StatsAgent(); System.out.println("Waiting forever..."); Thread.sleep(Long.MAX_VALUE); } }
JMXClient.java
package com.sample.clients; import java.io.IOException; import java.util.Arrays; import java.util.Set; import java.util.TreeSet; import javax.management.JMX; import javax.management.MBeanServerConnection; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; import com.sample.mbeans.SystemStatisticsMBean; public class JMXClient { public static class ClientListener implements NotificationListener { public void handleNotification(Notification notification, Object handback) { System.out.println("***********************************"); System.out.println(notification.getMessage()); System.out.println("***********************************"); } } private static void printAvailableDomains(MBeanServerConnection mbsc) throws IOException { System.out.println("\nDomains:"); String domains[] = mbsc.getDomains(); Arrays.sort(domains); for (String domain : domains) { System.out.println("\tDomain = " + domain); } System.out.println("\nMBeanServer default domain = " + mbsc.getDefaultDomain()); } private static void printAllMBeans(MBeanServerConnection mbsc) throws IOException { int totalMBeans = mbsc.getMBeanCount(); System.out.println("Total MBeans : " + totalMBeans); System.out.println("\nQuering MBeanServer MBeans:"); Set<ObjectName> names = new TreeSet<ObjectName>(mbsc.queryNames(null, null)); for (ObjectName name : names) { System.out.println("\tObjectName = " + name); } } public static void main(String[] args) throws Exception { /* Create an RMI Connector client and connect it to the RMI connector server */ JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi"); JMXConnector jmxc = JMXConnectorFactory.connect(url, null); System.out.println("\nGetting an MBeanServerConnection"); MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); printAvailableDomains(mbsc); printAllMBeans(mbsc); /* Get SystemStatisticsMBean */ ObjectName mbeanName = new ObjectName("com.sample.mbeans:type=SystemStatisticsMBean"); SystemStatisticsMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, SystemStatisticsMBean.class, true); /* Add notification listener */ ClientListener listener = new ClientListener(); mbsc.addNotificationListener(mbeanName, listener, null, null); System.out.println("\nRead Count = " + mbeanProxy.getAppStats().getReadCount()); System.out.println("\nWrite Count = " + mbeanProxy.getAppStats().getWriteCount()); System.out.println("Setting readCount to 50 and writeCount to 100"); mbeanProxy.setReadCount(50); mbeanProxy.setWriteCount(100); /* Wait for 2 seconds to receive notification */ Thread.sleep(2000); System.out.println("\nRead Count = " + mbeanProxy.getAppStats().getReadCount()); System.out.println("\nWrite Count = " + mbeanProxy.getAppStats().getWriteCount()); jmxc.close(); System.out.println("\nBye! Bye!"); } }
Run
Application.java, using below VM arguments.
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
If
you are running in Eclipse, follow below steps to pass above arguments.
Right
click on Application.java.
Run
As -> Run Configurations…
In
VM arguments: filed, add below arguments.
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
Click
on Run button.
Run
JMXClient.java, you can able to see below messages in console.
Getting an MBeanServerConnection Domains: Domain = JMImplementation Domain = com.sample.mbeans Domain = com.sun.management Domain = java.lang Domain = java.nio Domain = java.util.logging MBeanServer default domain = DefaultDomain Total MBeans : 23 Quering MBeanServer MBeans: ObjectName = JMImplementation:type=MBeanServerDelegate ObjectName = com.sample.mbeans:type=SystemStatisticsMBean ObjectName = com.sun.management:type=DiagnosticCommand ObjectName = com.sun.management:type=HotSpotDiagnostic ObjectName = java.lang:type=ClassLoading ObjectName = java.lang:type=Compilation ObjectName = java.lang:type=GarbageCollector,name=PS MarkSweep ObjectName = java.lang:type=GarbageCollector,name=PS Scavenge ObjectName = java.lang:type=Memory ObjectName = java.lang:type=MemoryManager,name=CodeCacheManager ObjectName = java.lang:type=MemoryManager,name=Metaspace Manager ObjectName = java.lang:type=MemoryPool,name=Code Cache ObjectName = java.lang:type=MemoryPool,name=Compressed Class Space ObjectName = java.lang:type=MemoryPool,name=Metaspace ObjectName = java.lang:type=MemoryPool,name=PS Eden Space ObjectName = java.lang:type=MemoryPool,name=PS Old Gen ObjectName = java.lang:type=MemoryPool,name=PS Survivor Space ObjectName = java.lang:type=OperatingSystem ObjectName = java.lang:type=Runtime ObjectName = java.lang:type=Threading ObjectName = java.nio:type=BufferPool,name=direct ObjectName = java.nio:type=BufferPool,name=mapped ObjectName = java.util.logging:type=Logging Read Count = 0 Write Count = 0 Setting readCount to 50 and writeCount to 100 *********************************** Read Count is set to 50 *********************************** *********************************** Write Count is set to 100 *********************************** Read Count = 50 Write Count = 100 Bye! Bye!
No comments:
Post a Comment