Controlling WSO2 Enterprise Service Bus programmatically using JMX

A few weeks ago I started working with WSO2‘s Enterprise Service Bus software, which is a lightweight and extremely high performance, open source enterprise service bus (ESB). One reason it’s so lightweight and fast is that it doesn’t have to be run in a bloated application server environment (although it can, but where’s the point). Instead, it’s running in an OSGi container. While the ESB itself still needs some polishing, especially in the area of deployment in large company environments, it looks extremely promising. We even flew in a few guys from HQ in Sri Lanka to help us with the initial setup of the product. Judging from the guys I’ve met, there must be a lot of talent in that company! Support is top notch and fairly priced.

One thing I was working on over the last few days is a command line remote control utility for the WSO2 ESB. It supports deployment and undeployment of the Eclipse Carbon Studio .car files and many other features, which at the time are only available through the web based user interface. The utility comes with an awesome name too: Carbonara :) We need this command line functionality for our fully automated change and configuration management processes. There’s no point in releasing the whole thing to the public because it’s tailor-made for the staging processes in my company.

Here’s a small Carbonara excerpt that shows how to send administrative commands like shutdown or entering/exiting maintenance mode to any WSO2 product using JMX. You can also use JConsole to remotely control any WSO2 product by the way. You will have to activate the JMX registry in the carbon.xml file in order to be able to use JMX. The supplied username and password will have to match a user with administrative privileges in the user store.

package com.trick77.wso2.carbonara.client;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Hashtable;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class JmxAdminClient {

	private static final String CMD_START_MAINTENANCE = "startMaintenance";

	private static final String CMD_END_MAINTENANCE = "endMaintenance";

	private static final String CMD_RESTART = "restart";

	private static final String CMD_SHUTDOWN = "shutdown";

	private static final String GRACEFULLY = "Gracefully";

	private JMXServiceURL jmxUrl;

	private Hashtable<String, String[]> config;

	public JmxAdminClient(final String aHostnameAndPort, final String aUserName, final String aPassword)
			throws MalformedURLException {
		jmxUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + aHostnameAndPort + "/jmxrmi");
		config = new Hashtable<String, String[]>();
		String[] _credentials = new String[] {aUserName, aPassword};
		config.put("jmx.remote.credentials", _credentials);
	}

	public void shutdown(boolean aGracefully) throws IOException, MalformedObjectNameException, NullPointerException,
			InstanceNotFoundException, MBeanException, ReflectionException {
		if (aGracefully) {
			sendAdminCommand(CMD_SHUTDOWN + GRACEFULLY);
		}
		else {
			sendAdminCommand(CMD_SHUTDOWN);
		}
	}

	public void restart(boolean aGracefully) throws IOException, MalformedObjectNameException, NullPointerException,
			InstanceNotFoundException, MBeanException, ReflectionException {
		if (aGracefully) {
			sendAdminCommand(CMD_RESTART + GRACEFULLY);
		}
		else {
			sendAdminCommand(CMD_RESTART);
		}
	}

	public void startMaintenance() throws IOException, MalformedObjectNameException, NullPointerException,
			InstanceNotFoundException, MBeanException, ReflectionException {
		sendAdminCommand(CMD_START_MAINTENANCE);
	}

	public void endMaintenance() throws IOException, MalformedObjectNameException, NullPointerException,
			InstanceNotFoundException, MBeanException, ReflectionException {
		sendAdminCommand(CMD_END_MAINTENANCE);
	}

	protected void sendAdminCommand(String aCommand) throws IOException, MalformedObjectNameException,
			NullPointerException, InstanceNotFoundException, MBeanException, ReflectionException {
		JMXConnector _jmxc = null;
		try {
			_jmxc = JMXConnectorFactory.connect(jmxUrl, config);
			MBeanServerConnection _mbsc = _jmxc.getMBeanServerConnection();
			ObjectName _mBeanName = new ObjectName("org.wso2.carbon:type=ServerAdmin");
			// Let's see if the MBean is really there
			ObjectInstance _mBean = _mbsc.getObjectInstance(_mBeanName);

			// The call
			_mbsc.invoke(_mBeanName, aCommand, null, null);
		}
		finally {
			if (_jmxc != null) {
				_jmxc.close();
			}
		}
	}


}

One thought on “Controlling WSO2 Enterprise Service Bus programmatically using JMX

Comments are closed.