The JMXConnectionWrapper API
From JPPF 6.3 Documentation
|
Main Page > Management and monitoring > JMXConnectionWrapper |
The JPPF API to connect to a local or remote JMX server, and to access the MBeans it provides, is made of the general JMXConnectionWrapper class and its subclasses JMXDriverConnectionWrapper and JMXNodeConnectionWrapper.
1 Connecting to an MBean server
1.1 Manually establishing a connection
To establish a JMX connection with a JPPF driver or node, use one of the constructors in JMXDriverConnectionWrapper or JMXNodeConnectionWrapper, respectively, then call the connect() or connectAndWait(timeout) method:
try (JMXDriverConnectionWrapper driver = new JMXDriverConnectionWrapper("myhost.org", 11111, false)) { if (!driver.connectAndWait(5000L)) { throw new RuntimeException("could not connect to " + driver.toString()); } // use the JMX connection ... } catch(Exception e) { e.printStackTrace(); }
Note that the JMXDriverConnectionWrapper and JMXNodeConnectionWrapper can be used in a try-with-resource statement, as shown above, since their superclass implements AutoCloseable.
The connectAndWait(timeout) method will return true if the connection can be established within the specified timeout (5 seconds in our example), otherwise it returns false.
On the other hand, the connect() method attempts to connect in the background and does not return a value. You can then determine the connection state by calling the isConnected() method. Thus, we can replace the call to connectAndWait() with this roughly equivalent code:
try (JMXNodeConnectionWrapper node = new JMXNodeConnectionWrapper("my_node_01.org", 12001, false)) { long start = System.currentTimeMillis(); while (!node.isConnected()) { long elapsed = System.currentTimeMillis() - start; if (elapsed > 5000L) throw new RuntimeException("could not connect to node JMX " + Node.toString()); Thread.sleep(50L); } // use the JMX connection ... } catch(Exception e) { e.printStackTrace(); }
You can also receive an asynchronous notification of the connection's success or failure by registering a JMX connection listener, detailed in the next section.
The no-args constructors, JMXDriverConnectionWrapper() and JMXNodeConnectionWrapper() allow a connection to the local (in-JVM) MBean server of a driver or a node, respectively. You still need to call the connect() method, to preserve the API semantics, however it is guaranted that the connection is immediately established. In other words, if you call isConnected() immediately after a call to connect() on a local connection, it is guaranteed to return true.
Local JMX connections are useful if you need access to the MBeans of a JPPF driver or node from a plugin or add-on, such as a node life cycle listener or a startup class. Here is an example in a node startup class:
public class TestNodeStartup implements JPPFNodeStartupSPI { @Override public void run() { try (JMXNodeConnectionWrapper node = new JMXNodeConnectionWrapper()) { node.connect(); assert node.isConnected(); // use the JMX connection ... } catch (Exception e) { e.printStackTrace(); } } }
1.2 JMX connection listeners
You can receive asynchronous notifications of the success or failure of the connection, by adding a JMXConnectionWrapperListener to the JMXConnectionWrapper, before calling one of its connect*() methods:
public class JMXConnectionWrapper extends AbstractJMXConnectionWrapper { // Add a listener to this connection wrapper public void addJMXConnectionWrapperListener(JMXConnectionWrapperListener listener) // Remove a listener from this connection wrapper public void removeJMXConnectionWrapperListener(JMXConnectionWrapperListener listener) }
The JMXConnectionWrapperListener interface is defined as follows:
public interface JMXConnectionWrapperListener extends EventListener { // Notify listeners that a JMX connection wrapper successfully connected to the JMX server void onConnected(JMXConnectionWrapperEvent event); // Notify listeners that a JMX connection wrapper failed to connect // before the timeout specified in connectAndWait() method void onConnectionTimeout(JMXConnectionWrapperEvent event); }
It receives events of type JMXConnectionWrapperEvent, defined as follows:
public class JMXConnectionWrapperEvent extends EventObject { // Get the jmx connection wrapper source of this event public JMXConnectionWrapper getJMXConnectionWrapper() }
Example usage:
try (JMXNodeConnectionWrapper node = new JMXNodeConnectionWrapper("mynode.org", 12001, false)) { node.addJMXConnectionWrapperListener(new JMXConnectionWrapperListener() { @Override public void onConnected(JMXConnectionWrapperEvent event) { // do something with the connection if and whenever it is established ... try { JPPFNodeState state = ((JMXNodeConnectionWrapper) event.getJMXConnectionWrapper()).state(); } catch (Exception e) { e.printStackTrace(); } } @Override public void onConnectionTimeout(JMXConnectionWrapperEvent event) { } }); // go on with the application... }
1.3 Obtaining a driver JMX connection from a JPPF client
We have seen earlier that each client connection pool has an associated pool of JMX connection wrappers. It is therefore very convenient to obtain an already connected JMXDriverConnectionWrapper from a JPPFClient, as in this example:
JPPFClient client = new JPPFClient(); JMXDriverConnectionWrapper driver = client.awaitWorkingConnectionPool().awaitWorkingJMXConnection();
2 Accessing and using the MBeans
2.1 Using MBean proxies
An MBean proxy is an object which implements the interface of an MBean, and relays JMX requests and notifications as if the implementation were local. Thus, it hides the remote connection and protocol details. To obtain a proxy to a remote MBean, you can use one of the dediciated methods in JMXConnectionWrapper:
public class JMXConnectionWrapper extends AbstractJMXConnectionWrapper { // Obtain a proxy to the specified remote MBean public <T> T getProxy(final String name, final Class<T> inf) throws Exception // Obtain a proxy to the specified remote MBean public <T> T getProxy(final ObjectName objectName, final Class<T> inf) throws Exception }
For instance, to obtain a proxy to the JPPFNodeTaskMonitorMBean, you could write the following code:
try (JMXConnectionWrapper jmx = new JMXNodeConnectionWrapper("mynode.org", 12001, false)) { jmx.connectAndWait(5000L); // create a JPPFNodeTaskMonitorMBean proxy JPPFNodeTaskMonitorMBean taskMonitor = jmx.getProxy(JPPFNodeTaskMonitorMBean.MBEAN_NAME, JPPFNodeTaskMonitorMBean.class); // now use the proxy int nbTasks = taskMonitor.getTotalTasksExecuted(); }
The class JMXDriverConnectionWrapper provides convenience methods to obtain proxies to the built-in driver MBeans:
public class JMXDriverConnectionWrapper extends JMXConnectionWrapper implements JPPFDriverAdminMBean { // Create a proxy to the driver's mbean which forwards requests to its nodes public NodeForwardingMBean getForwarder() throws Exception // Create a proxy to the driver's mbean which manages and monitors jobs public DriverJobManagementMBean getJobManager() throws Exception // Create a proxy to the driver's mbean that manages the load-balancers persisted states public LoadBalancerPersistenceManagement getLoadBalancerPersistenceManagement() throws Exception // Get a proxy to the diagnostics/JVM health MBean @Override public DiagnosticsMBean getDiagnosticsProxy() throws Exception // Get a proxy to the dependency manager MBean in the driver public JobDependencyManagerMBean getJobDependencyManager() throws Exception }
Also, note that JMXDriverConnectionWrapper implements the JPPFDriverAdminMBean interface, which de facto makes it a proxy for this MBean.
Similarly, JMXNodeConnectionWrapper provides convenient methods to obtain proxies to the built-in MBeans of a node:
public class JMXNodeConnectionWrapper extends JMXConnectionWrapper implements JPPFNodeAdminMBean { // Get a dynamic proxy implementing the JPPFNodeTaskMonitorMBean interface public JPPFNodeTaskMonitorMBean getNodeTaskMonitor() throws Exception // Get a dynamic proxy implementing the JPPFNodeProvisioningMBean interface public JPPFNodeProvisioningMBean getNodeProvisioner() throws Exception // Get a dynamic proxy implementing the JPPFNodeMaintenanceMBean interface public JPPFNodeMaintenanceMBean getNodeMaintenance() throws Exception }
It also implements the JPPFNodeAdminMBean interface, which makes it a proxy for this node MBean.
The previous example could then be rewritten as:
try (JMXNodeConnectionWrapper node = new JMXNodeConnectionWrapper("mynode.org", 12001, false)) { node.connectAndWait(5000L); // create and use a JPPFNodeTaskMonitorMBean proxy int nbTasks = node.getNodeTaskMonitor().getTotalTasksExecuted(); }
Some of the JPPF built-in MBeans can emit notifications. In this case, they extend the NotificationEmitter interface, which allows them to register and unregister one or more NotificationListener that will receive and handle the notifications.
The following example shows the registration and removal of a notification listener which prints out the notifications emitted by the tasks executed in a node:
try (JMXNodeConnectionWrapper node = new JMXNodeConnectionWrapper("mynode.org", 12001)) { node.connectAndWait(5000L); JPPFNodeTaskMonitorMBean taskMonitor = node.getNodeTaskMonitor(); NotificationListener listener = (notif, handback) -> System.out.println("received " + notif + " from " + handback); taskMonitor.addNotificationListener(listener, null, node.getId()); // ... execute tasks ... // when the listener is no longer needed, remove it taskMonitor.removeNotificationListener(listener, null, node.getId()); }
2.2 Reflective invocations
Management and monitoring requests can also be performed even if the MBean interfaces are not in the local classpath, using dedicated generic methods to get or set MBen attributes or call MBean methods:
public class JMXConnectionWrapper extends AbstractJMXConnectionWrapper { // Invoke a method on the specified MBean public Object invoke(String mbeanName, String methodName, Object[] params, String[] signature) throws Exception // Invoke a method with no argument on the specified MBean public Object invoke(String mbeanName, String methodName) throws Exception // Get the value of an attribute of the specified MBean public Object getAttribute(String mbeanName, String attribute) throws Exception // Set the value of an attribute of the specified MBean public void setAttribute(String mbeanName, String attribute, Object value) throws Exception }
To continue with the previous example, we can now also obtain the number of executed atsks by explicitely getting the value of the "TotalTasksExecuted" attribute of the JPPFNodeTaskMonitorMBean:
try (JMXNodeConnectionWrapper node = new JMXNodeConnectionWrapper("mynode.org", 12001, false)) { node.connectAndWait(5000L); // get the "TotalTasksExecuted" attribute of the JPPFNodeTaskMonitorMBean int nbTasks = (Integer) node.getAttribute(JPPFNodeTaskMonitorMBean.MBEAN_NAME, "TotalTasksExecuted"); }
Another example, this time invoking an update of the priority of a job in the driver:
try (JMXDriverConnectionWrapper driver = new JMXDriverConnectionWrapper("mydriver.org", 11111)) { driver.connectAndWait(5000L); // invoke DriverJobManagementMBean.updatePriority(jobUuid, 100) Object[] params = { myJob.getUuid(), 100 }; String[] signature = { String.class.getName(), Integer.class.getName() }; driver.invoke(DriverJobManagementMBean.MBEAN_NAME, "updatePriority", params, signature); }
JMXConnectionWrapper also has addNotificationListener() and removeNotificationListener() methods, which are used to register or unregister notification listeners with the MBeans that can emit notifications:
public class JMXConnectionWrapper extends AbstractJMXConnectionWrapper { // Add a notification listener to the specified MBean public void addNotificationListener(String mBeanName, NotificationListener listener) throws Exception // Add a notification listener to the specified MBean public void addNotificationListener(String mBeanName, NotificationListener listener, NotificationFilter filter, Object handback) throws Exception // Remove a notification listener from the specified MBean public void removeNotificationListener(String mBeanName, NotificationListener listener) throws Exception // Remove a notification listener from the specified MBean public void removeNotificationListener(String mBeanName, NotificationListener listener, NotificationFilter filter, Object handback) throws Exception }
The following notification example does the same thing as the one of the previous sectrion, but uses reflective methods to add and remove the notification listener:
try (JMXNodeConnectionWrapper node = new JMXNodeConnectionWrapper("mynode.org", 12001)) { node.connectAndWait(5000L); NotificationListener listener = (notif, id) -> System.out.println("received " + notif + " from " + id); node.addNotificationListener(JPPFNodeTaskMonitorMBean.MBEAN_NAME, listener, null, node.getId()); // ... execute tasks ... // when the listener is no longer needed, remove it node.removeNotificationListener( JPPFNodeTaskMonitorMBean.MBEAN_NAME, listener, null, node.getId()); }
2.3 Getting a raw MBean server connection
Since JMXConnectionWrapper and its subclasses are dedicated to the management and monitoring of JPPF grids, they do not replicate all the JMX features available with a standard JMX connection. To access these features, you can use the getMbeanConnection() method in JMXConnectionWrapper, which returns a MBeanServerConnection. The following example queries the remote MBean server for all the JPPF MBeans:
try (JMXDriverConnectionWrapper driver = new JMXDriverConnectionWrapper("mydriver.org", 11111)) { driver.connectAndWait(5000L); MBeanServerConnection mbsc = driver.getMbeanConnection(); // Get the names of all JPPF MBeans Set<ObjectName> jppfNames = mbsc.queryNames(new ObjectName("org.jppf:*"), null); }
Main Page > Management and monitoring > JMXConnectionWrapper |