From JPPF 5.1 Documentation

Contents

As of JPPF v5.0, the package org.jppf.client.monitoring.topology provides an API to explore and monitor the topology of a JPPF grid, such as discovered from a JPPF client's perspective.
This API is used by the administration and monitoring console, and allows to explore the topology as well as subscribe to notifications of the changes that occur, such as new server being brought online, nodes started or terminated, etc.

1 Building and exploring the topology

The entry point for this API is the TopologyManager class.
A TopologyManager uses a JPPFClient to discover its connections to one or more drivers, and queries these drivers via the management API
to obtain information about their attached JPPF nodes and other peer drivers they are connected to. All this information is used to build a model of the JPPF grid topology as a tree.
For example, with a grid that has two drivers connected to each other, we would have a representation like this:

The dotted lines emphasize the fact that a peer is actually a "virtual" component which references a real driver. Peer objects are here to allow representing the topology as a tree rather than as a graph, which makes their usage a lot easier.

You may notice that this is very similar to the "toplogy tree" view of the administration console:

This is not a coincidence: the adminstration console indeed uses its own instance of TopologyManager and the tree view is a direct mapping of the topology
to a tree-like swing component.

The model representing the components of the JPPF toplogy is a class hierarchy whose base super class is the abtract class AbstractTopologyComponent,
which provides an API to navigate within the tree strutcture, along with ways to identify each component and methods to retrieve information that are common to drivers and nodes.

The object model is as follows:

AbtractComponent provides the API to navigate a tree of elements uniquely identified with a uuid:

public abstract class AbstractComponent<E extends AbstractComponent> {
// Get the parent of this compponent
public synchronized E getParent() {
// Get the number of children of this component
public synchronized int getChildCount()
// Get the children of this component
public synchronized List<E> getChildren()
// Get the child with the specified uuid
public synchronized E getChild(final String uuid)
// Get the uuid of this ocmponent
public synchronized String getUuid()
// Get a user-friendly representation of this topology component
public String getDisplayName()
}

public abstract class AbstractTopologyComponent
extends AbstractComponent<AbstractTopologyComponent> {
// Whether this object represents a driver
public boolean isDriver()
// Whether this object represents a node
public boolean isNode()
// Whether this object represents a peer driver
public boolean isPeer()
// Get the object describing the health of a node or driver
public HealthSnapshot getHealthSnapshot()
// Get the management information for this component
public JPPFManagementInfo getManagementInfo()
// Get a user-friendly representation of this component
public String getDisplayName()
}

public class TopologyDriver extends AbstractTopologyComponent {
// Get the JMX connection wrapper
public JMXDriverConnectionWrapper getJmx()
// Get the driver connection
public JPPFClientConnection getConnection()
// Get a proxy to the MBean that forwards node management requests
public JPPFNodeForwardingMBean getForwarder()
// Get a proxy to the jobs monitoring MBean
public DriverJobManagementMBean getJobManager()
// Get a proxy the diagnostics MBean for this driver
public DiagnosticsMBean getDiagnostics()
}

TopologyNode provides two specialized methods to query the node's state:

public class TopologyNode extends AbstractTopologyComponent {
// Get the object describing the current state of a node
public JPPFNodeState getNodeState()
// Get the number of slaves for a master node (node provisioning)
public int getNbSlaveNodes()
}

Whereas TopologyPeer does not provide any additional method, since its uuid is all that is needed:

public class TopologyManager implements ClientListener {
// Create a topology manager with a new JPPFClient
public TopologyManager()
// Create a toplogy manager with the specified JPPFClient
public TopologyManager(JPPFClient client)
// Get the JPPF client
public JPPFClient getJPPFClient()
// Get all drivers
public List<TopologyDriver> getDrivers()
// Get all nodes
public List<TopologyNode> getNodes()
// Get all peers
public List<TopologyPeer> getPeers()
// Get a driver from its uuid
public TopologyDriver getDriver(String uuid)
// Get a node from its uuid
public TopologyNode getNode(String uuid)
// Get a peer from its uuid
public TopologyPeer getPeer(String uuid)
// Get a node or peer from its uuid
public TopologyNode getNodeOrPeer(String uuid)
// Get the number of drivers
public int getDriverCount()
// Get the number of nodes
public int getNodeCount()
// Get the number of peers
public int getPeerCount()
}

According to this, the following code example can be used to visit the entire tree:

A TopologyManager instance also automatically refreshes the states of the nodes, along with the JVM health snapshots of the drivers and nodes. The interval between refreshes is determined via the value of the following configuration properties:

# refresh interval in millis for the grid topology.
# this is the interval between 2 successive runs of the task that refreshes the
# topology via JMX requests; defaults to 1000
jppf.admin.refresh.interval.topology = 1000
# refresh interval for the JVM health snapshots; defaults to 1000
# this is the interval between 2 successive runs of the task that refreshes
# the JVM health snapshots via JMX requests
jppf.admin.refresh.interval.health = 1000

These values can be set both in a configuration file and programmatically, for instance:

2 Receiving notifications of changes in the topology

It is possible to subscribe to topology change events emitted by a TopologyManager,
using an implementation of the TopologyListener interface as parameter of the related constructors and methods in TopologyManager:

public interface TopologyListener extends EventListener {
// Called when a driver is discovered
void driverAdded(TopologyEvent event);
// Called when a driver is terminated
void driverRemoved(TopologyEvent event);
// Called when the state of a driver has changed
void driverUpdated(TopologyEvent event);
// Called when a node is added to a driver
void nodeAdded(TopologyEvent event);
// Called when a node is removed from a driver
void nodeRemoved(TopologyEvent event);
// Called when the state of a node has changed
void nodeUpdated(TopologyEvent event);
}

As we can see, each notification is encapsulated in a TopologyEvent object:

public class TopologyEvent extends EventObject {
// Get the driver data
public TopologyDriver getDriver()
// Get the related node or peer
public TopologyNode getNodeOrPeer()
// Get the topology manager which emitted this event
public TopologyManager getTopologyManager()
}

Additionally, if you do not wish to override all the methods of the TopologyListener interface,
you can instead extend the class TopologyListenerAdapter, which provides an empty implementation of each method.

Here is a listener implementation that prints topology changes to the console: