package uk.nhs.kch.rassyeyanie.common.testing.integration;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.management.MBeanServerConnection;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.commons.lang.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Code examples of how to connect to and query the JMX beans exposed by Fuse.
*/
public class JmxTest {
private static final Logger logger = LoggerFactory.getLogger(JmxTest.class);
private MBeanServerConnection connection;
/**
* The starting point for querying the JMX properties is the serviceUrl. It is unique to the Fuse
* instance you want to connect to and configured in several files in the fuse etc directory. The
* defaults are shown below:
*
* org.apache.karaf.management.cfg
* rmiRegistryPort = 1099
* rmiServerPort = 44444
* serviceUrl = service:jmx:rmi://localhost:${rmiServerPort}/jndi/rmi://localhost:${rmiRegistryPort}/karaf-${karaf.name}
*
* system.properties
* karaf.name=root
*/
private JMXServiceURL getServiceURL() throws MalformedURLException {
String serviceURL = "service:jmx:rmi://localhost:44444/jndi/rmi://localhost:1099/karaf-root";
return new JMXServiceURL(serviceURL);
}
/**
* The only required environment information is a username and password for the fuse instance. By default
* there is a user called 'smx' with the password 'smx'. This should be different in a live Fuse instance.
*/
private Map<String,Object> getEnvironment() {
Map<String,Object> env = new HashMap<String, Object>();
env.put(JMXConnector.CREDENTIALS, new String[] {"smx", "smx"});
return env;
}
private MBeanServerConnection connect() throws IOException {
Map<String,Object> env = getEnvironment();
JMXServiceURL jmxUrl = getServiceURL();
JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxUrl, env);
return jmxConnector.getMBeanServerConnection();
}
@Before
public void setUp() throws IOException {
connection = connect();
}
/**
* To find JMX beans you need to specify a domain and a list of attributes to match. As shown in the code below,
* these can use wildcards. To reduce the number of results you can specify a type or the name
* of a bean you are interested in. In the example below we are only interested in camel routes.
* <br/>
* See the JavaDoc on {@link ObjectName} for more info on the name string
*/
@Test
public void testListAllRoutes() throws Exception {
ObjectName objName = new ObjectName("*:*,type=routes");
Set<ObjectInstance> mbeans = connection.queryMBeans(objName, null);
printRouteNames(mbeans);
}
/**
* Wildcards can also be used in the type and name elements. Below is an example of searching
* for all routes that contain the word "Transform" in their name.
*/
@Test
public void testListAllTransformRoutes() throws Exception {
ObjectName objName = new ObjectName("*:*,type=routes,name=*Transform*");
Set<ObjectInstance> mbeans = connection.queryMBeans(objName, null);
printRouteNames(mbeans);
}
/**
* For some reason the Spring configuration wraps route names in quotes. To find a specific
* route name you will have to add the quotes to the search string (or use wildcards).
*/
@Test
public void testFindSpecificRoute() throws Exception {
ObjectName objName = new ObjectName("*:*,type=routes,name=\"ApasListenerRoute\"");
Set<ObjectInstance> mbeans = connection.queryMBeans(objName, null);
printRouteNames(mbeans);
}
@Test
public void testListeningPortStatus() throws Exception {
// Find all the routes that contain the word Listener in the name
ObjectName listenerRouteQuery = new ObjectName("*:*,type=routes,name=*Listener*");
Set<ObjectInstance> listenerRoutes = connection.queryMBeans(listenerRouteQuery, null);
logger.debug("+------------------------------+------------+---------------------------------------------------------+");
logger.debug("| Route | Status | Endpoint |");
logger.debug("+------------------------------+------------+---------------------------------------------------------+");
for (ObjectInstance listenerRoute : listenerRoutes) {
ObjectName listenerRouteInfo = listenerRoute.getObjectName();
// Build an ObjectName using information from the listener context and domain to
// find any mina consumers used by the listener.
String consumerLocation = listenerRouteInfo.getDomain() + ":*,context=" + listenerRouteInfo.getKeyProperty("context") + ",type=consumers,name=MinaConsumer*";
ObjectName consumerQuery = new ObjectName(consumerLocation);
Set<ObjectInstance> consumers = connection.queryMBeans(consumerQuery, null);
for (ObjectInstance consumer : consumers) {
ObjectName consumerInfo = consumer.getObjectName();
String routeId = StringUtils.rightPad(connection.getAttribute(listenerRouteInfo, "RouteId").toString(), 28);
String status = StringUtils.rightPad(connection.getAttribute(consumerInfo, "State").toString(), 10);
String endpoint = connection.getAttribute(consumerInfo, "EndpointUri").toString();
logger.debug("| " + routeId + " | " + status + " | " + endpoint + " |");
}
}
logger.debug("+------------------------------+------------+---------------------------------------------------------+\n");
}
@Test
public void testListTopLevelObjects() throws Exception {
String[] domains = connection.getDomains();
logger.debug("+------------------------------+");
logger.debug("| Domain |");
logger.debug("+------------------------------+");
for (String domain : domains) {
logger.debug("| " + StringUtils.rightPad(domain, 28) + " |");
}
logger.debug("+------------------------------+\n");
}
private void printRouteNames(Set<ObjectInstance> mbeans) throws Exception {
logger.debug("+------------------------------+");
logger.debug("| Route |");
logger.debug("+------------------------------+");
for (ObjectInstance objInstance : mbeans) {
String routeId = StringUtils.rightPad(connection.getAttribute(objInstance.getObjectName(), "RouteId").toString(), 28);
logger.debug("| " + routeId + " |");
}
logger.debug("+------------------------------+\n");
}
}