Administering WebSphere Using JMX

Although administering WebSphere is best done using the Wsadmin API (with scripting languages like Jython or Jacl), there may be situations when this is not a good option. One example is when your application is already using Java and calling out to an external program (wsadmin.sh) would make the application run slower or make your integration cumbersome.

If your application is already using Java, naturally, it’s best that you also use Java to administer WebSphere. And the recommended way of doing this is through the use of the JMX API for Websphere MBeans. Below is an example illustrating how to use Websphere’s JMX API to retrieve memory information of an application server JVM. The code below is composed of two classes (WASAdminClient.java,  JavaVirtualMachine.java) and a property file (soap_client.properties).

The key to the use of Websphere’s JMX API is to obtain a JMX client connection to your WebSphere’s Application Server and then use this connection to access WebSphere’s JMX MBean Interfaces.

The first step in the process is to establish a JMX client connection. This is the goal of the WASAdminClient class. This is achieved by obtaining the AdminClientFactory.createAdminClient(Properties props) object. The Properties object passed to the method contains the credentials and trustore information required to connect to your Websphere Application Server. The credentials are obtained from the soap_client.properties file while the trustore information is obtained from the files generated by Websphere.

WASAdminClient.java would have been simpler if security is not enabled. If security is not enabled in Websphere, credentials and trustore information won’t be needed to obtain the AdminClient object. However, in a real production setup, this is rarely done so I’d like to also show this process. This is probably the most crucial information you would want to hear. Using WebSphere’s JMX MBeans Interface is straightforward, however, getting the WAS AdminClient object with security enabled is what stumped a lot of people. As you can see in the code below, obtaining the adminclient is not as simple as passing the username and password. It also requires the ssl trustStore and keyStore files from a WebSphere installation. The other thing is that you just can’t get these files out of nowhere. They need to be validly generated from a WebSphere installation. Note: The WebSphere installation doesn’t need to be the server where you want to connect.

The WASAdminClient class has two options to obtain the username and password information. These can be obtained from the soap_client.properties file or from Websphere’s CONNECTOR_SOAP_CONFIG file.

Once you have an AdminClient object connection, you can now use this object to access WebSphere’s JMX MBean Interfaces. The JavaVirtualMachine class below demonstrates how to access some memory information of an application server like heap size, maximum memory, etc.

I have also included below a JUnit test case for the JavaVirtualMachine class. Several test cases are not implemented. I have only provided a couple just to show examples on how to use the two Java classes.

Alvin Abad


"WASAdminClient.java"
package admin.service;

import java.util.Properties;
import java.util.ResourceBundle;

import com.ibm.websphere.management.AdminClient;
import com.ibm.websphere.management.AdminClientFactory;
import com.ibm.websphere.management.exception.ConnectorException;

/**
 * Websphere JMX AdminClient Service
 * @author Alvin Abad
 *
 */
public class WASAdminClient {
	private String hostname = "localhost";    // default
	private String port = "8879";             // default

	private String username;
	private String password;
	private String connector_security_enabled;
	private String connector_soap_config;
	private String ssl_trustStore;
	private String ssl_keyStore;
	private String ssl_trustStorePassword;
	private String ssl_keyStorePassword;

	private ResourceBundle soapClient;
	private String soap_client_properties;

	private AdminClient adminClient;

	public WASAdminClient() throws ConnectorException {
		soap_client_properties = "soap_client";
	}

	public WASAdminClient(String soap_client_properties) throws ConnectorException {
		this.soap_client_properties = soap_client_properties;
	}

	public AdminClient getAdminClient() {
		return adminClient;
	}

	public AdminClient create() throws ConnectorException {
		getResourceBundle(soap_client_properties);

		Properties props = new Properties();
		props.setProperty(AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
		props.setProperty(AdminClient.CONNECTOR_HOST, hostname);
		props.setProperty(AdminClient.CONNECTOR_PORT, port);
		props.setProperty(AdminClient.CACHE_DISABLED, "false");

		if (connector_security_enabled == "false") {
			adminClient = AdminClientFactory.createAdminClient(props);
			return adminClient;
		}

		props.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "true");
		props.setProperty(AdminClient.CONNECTOR_AUTO_ACCEPT_SIGNER, "true");
		props.setProperty("javax.net.ssl.trustStore", ssl_trustStore);
		props.setProperty("javax.net.ssl.keyStore", ssl_keyStore);
		props.setProperty("javax.net.ssl.trustStorePassword", ssl_trustStorePassword);
		props.setProperty("javax.net.ssl.keyStorePassword", ssl_keyStorePassword);

		// Use username and password or soap.client.props file
		if (username == null || password == null) {
			props.setProperty(AdminClient.CONNECTOR_SOAP_CONFIG, connector_soap_config);
		} else {
			props.setProperty(AdminClient.USERNAME, username);
			props.setProperty(AdminClient.PASSWORD, password);
		}

		adminClient = AdminClientFactory.createAdminClient(props);

		return adminClient;
	}

	public ResourceBundle getResourceBundle(String properties) {
		soapClient = ResourceBundle.getBundle(properties);

		hostname = soapClient.getString("hostname");
		port = soapClient.getString("port");
		connector_security_enabled = soapClient.getString("connector_security_enabled");
		ssl_trustStore = soapClient.getString("ssl_trustStore");
		ssl_keyStore = soapClient.getString("ssl_keyStore");
		ssl_trustStorePassword = soapClient.getString("ssl_trustStorePassword");
		ssl_keyStorePassword = soapClient.getString("ssl_keyStorePassword");

		if (soapClient.containsKey("connector_soap_config")) {
		    connector_soap_config = soapClient.getString("connector_soap_config");
		}

		if (soapClient.containsKey("username")) {
		    username = soapClient.getString("username");
		}

		if (soapClient.containsKey("password")) {
			password = soapClient.getString("password");
		}

		if (soapClient.containsKey("hostname")) {
			hostname = soapClient.getString("hostname");
		}

		if (soapClient.containsKey("port")) {
			port = soapClient.getString("port");
		}

		return soapClient;
	}

}

"JavaVirtualMachine.java"

package admin.service;

import java.util.Set;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import com.ibm.websphere.management.AdminClient;
import com.ibm.websphere.management.exception.ConnectorException;

/**
 * Websphere JMX JavaVirtualMachine Service
 * @author Alvin Abad
 *
 */
public class JavaVirtualMachine {
	private String heapSize;
	private String maxMemory;
	private Integer maxHeapDumpsOnDisk;
	private String freeMemory;

	private ObjectName mBean;
	private Set mBeans;
	private AdminClient adminClient;

	public JavaVirtualMachine() {
	}

	public JavaVirtualMachine(AdminClient adminClient) {
		this.adminClient = adminClient;
	}

	public AdminClient getAdminClient() {
		return adminClient;
	}

	public void setAdminClient(AdminClient adminClient) {
		this.adminClient = adminClient;
	}

	public Set queryMBeans() throws MalformedObjectNameException,
                                         NullPointerException, ConnectorException {
		String query = "WebSphere:type=JVM,*";
		ObjectName queryName = new ObjectName(query);
		mBeans = adminClient.queryNames(queryName, null);

		return mBeans;
	}

	public Set getMBeans() {
		return mBeans;
	}

	public void setMBeans(Set mBeans) {
		this.mBeans = mBeans;
	}

	public ObjectName getMBean() {
		return mBean;
	}

	public void setMBean(ObjectName mBean) {
		this.mBean = mBean;
	}

	public String getHeapSize(ObjectName mBean) throws AttributeNotFoundException,
	                                   InstanceNotFoundException,
	                                   MBeanException, ReflectionException,
	                                   ConnectorException {
		heapSize = (String) adminClient.getAttribute(mBean, "heapSize");
		return heapSize;
	}

	public String getMaxMemory(ObjectName mBean) throws AttributeNotFoundException,
                                        InstanceNotFoundException, MBeanException,
                                        ReflectionException, ConnectorException {
		maxMemory = (String) adminClient.getAttribute(mBean, "maxMemory");
		return maxMemory;
	}

	public Integer getMaxHeapDumpsOnDisk(ObjectName mBean) throws AttributeNotFoundException,
                                       InstanceNotFoundException, MBeanException,
                                       ReflectionException, ConnectorException {
		maxHeapDumpsOnDisk = (Integer) adminClient.getAttribute(mBean, "maxHeapDumpsOnDisk");
		return maxHeapDumpsOnDisk;
	}

	public String getFreeMemory(ObjectName mBean) throws AttributeNotFoundException,
                                        InstanceNotFoundException, MBeanException,
                                        ReflectionException, ConnectorException {
		freeMemory = (String) adminClient.getAttribute(mBean, "freeMemory");
		return freeMemory;
	}

}

"soap_client.properties"

# Optional parameters
username = wasuser
password = secret
hostname = localhost
port = 8879

connector_security_enabled = true
#connector_soap_config = build/soap.client.props
ssl_trustStore = /usr/IBM/WebSphere/profiles/my_dmgr/etc/DummyClientTrustFile.jks
ssl_keyStore = /usr/IBM/WebSphere/profiles/my_dmgr/etc/DummyClientKeyFile.jks

ssl_trustStorePassword = WebAS
ssl_keyStorePassword = WebAS

"JavaVirtualMachineTest.java"

package admin.service;

import static org.junit.Assert.*;

import java.util.Set;

import javax.management.MalformedObjectNameException;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.ibm.websphere.management.AdminClient;
import com.ibm.websphere.management.exception.ConnectorException;

/**
 * JavaVirtualMachine Test Case
 * @author Alvin Abad
 */
public class JavaVirtualMachineTest {
	AdminClient adminClient;
	JavaVirtualMachine jvm;

	@Before
	public void setUp() throws Exception {
		WASAdminClient wasAdminClient = new WASAdminClient();
		adminClient = wasAdminClient.create();
	}

	@After
	public void tearDown() throws Exception {
	}

	@Test
	public void testJavaVirtualMachine() {
		jvm = new JavaVirtualMachine();
		assertNull(jvm.getAdminClient());
	}

	@Test
	public void testJavaVirtualMachineAdminClient() {
		jvm = new JavaVirtualMachine(adminClient);
		assertNotNull(jvm.getAdminClient());
		assertTrue(jvm.getAdminClient() instanceof AdminClient);
	}

	@Test
	public void testGetAdminClient() {
		jvm = new JavaVirtualMachine(adminClient);
		assertEquals(jvm.getAdminClient(), adminClient);
	}

	@Test
	public void testSetAdminClient() {
		jvm = new JavaVirtualMachine();
		jvm.setAdminClient(adminClient);
		assertEquals(jvm.getAdminClient(), adminClient);
	}

	@Test
	public void testQueryMBeans() throws MalformedObjectNameException,
                                   NullPointerException, ConnectorException {
		jvm = new JavaVirtualMachine();
		Set mBeans = jvm.queryMBeans();
		assertTrue(mBeans.size() > 0);
	}

	@Test
	public void testGetMBeans() {
		fail("Not yet implemented");
	}

	@Test
	public void testSetMBeans() {
		fail("Not yet implemented");
	}

	@Test
	public void testGetMBean() {
		fail("Not yet implemented");
	}

	@Test
	public void testSetMBean() {
		fail("Not yet implemented");
	}

	@Test
	public void testGetHeapSize() {
		fail("Not yet implemented");
	}

	@Test
	public void testGetMaxMemory() {
		fail("Not yet implemented");
	}

	@Test
	public void testGetMaxHeapDumpsOnDisk() {
		fail("Not yet implemented");
	}

	@Test
	public void testGetFreeMemory() {
		fail("Not yet implemented");
	}

}

Advertisements

10 thoughts on “Administering WebSphere Using JMX

  1. Hi,

    The information provided is very helpful. I have been trying similar thing with
    String query = “WebSphere:*,type=FailedEventManager”;
    I am able to retrieve all the failed event details but when i registered a listener with this adminClient.addNotificationListenerExtended(nodeagent, this, null, null);, the handleNotification(Notification ntfyObj, Object handback) is vener invoked.

    The same concept works for Runtime errors in Websphere Process Server but not for failed events. I need to read all the failed events as and when they occur and log them in a different place.

    Any help of this handleNotification() for FailedEventManager would be greatly helpful.

    Regards
    KK

  2. Alvin,

    Here’s the error I’m receiving when I try to run the ClientAdminSample Program. Can you please shed some light on this issue?

    BEGIN ERROR

    Exception in thread “main” java.lang.NoClassDefFoundError: com.ibm.websphere.security.WebSphereRuntimePermission
    at java.lang.J9VMInternals.verifyImpl(Native Method)
    at java.lang.J9VMInternals.verify(J9VMInternals.java:68)
    at java.lang.J9VMInternals.initialize(J9VMInternals.java:129)
    at AdminClientExample.createAdminClient(AdminClientExample.java:68)
    at AdminClientExample.main(AdminClientExample.java:32)
    Caused by: java.lang.ClassNotFoundException: com.ibm.websphere.security.WebSphereRuntimePermission
    at java.net.URLClassLoader.findClass(URLClassLoader.java:496)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:631)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:597)

    END ERROR

    Thanks,
    FP

    • Hi fprogrammer,

      I saw the same problem and simply put the class into an Application Client EAR (called with launchClient.sh) so I got all WebSphere classes included right away…

  3. Hi,

    will it work for WPS information too?
    I want to retrieve portal server information in java code, was womdering if this wud help.

    Thanks!

  4. I want to unconfigure one library for an application on Websphere, but i didn’t found any information about it.
    Can you put an example? Thanks.

  5. This code does not work for me,

    I get the following error

    com.ibm.websphere.management.exception.ConnectorException: ADMC0053E: The system cannot create a SOAP connector to connect to host localhost at port 8879 with SOAP connector security enabled.
    at com.ibm.websphere.management.AdminClientFactory.createAdminClient(AdminClientFactory.java:476)
    at admin.service.WASAdminClient.create(WASAdminClient.java)
    at admin.service.WASAdminClient.main(WASAdminClient.java)
    Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:67)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:521)
    at com.ibm.websphere.management.AdminClientFactory.createAdminClient(AdminClientFactory.java:331)
    … 2 more
    Caused by: com.ibm.websphere.management.exception.ConnectorNotAvailableException: [SOAPException: faultCode=SOAP-ENV:Client; msg=Error opening socket: javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.h: No trusted certificate found; targetException=java.lang.IllegalArgumentException: Error opening socket: javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.h: No trusted certificate found]
    at com.ibm.ws.management.connector.soap.SOAPConnectorClient.reconnect(SOAPConnectorClient.java:338)
    at com.ibm.ws.management.connector.soap.SOAPConnectorClient.(SOAPConnectorClient.java:175)
    … 7 more
    Caused by: [SOAPException: faultCode=SOAP-ENV:Client; msg=Error opening socket: javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.h: No trusted certificate found; targetException=java.lang.IllegalArgumentException: Error opening socket: javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.h: No trusted certificate found]
    at org.apache.soap.transport.http.SOAPHTTPConnection.send(Unknown Source)
    at org.apache.soap.rpc.Call.invoke(Unknown Source)
    at com.ibm.ws.management.connector.soap.SOAPConnectorClient$4.run(SOAPConnectorClient.java:303)
    at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
    at com.ibm.ws.management.connector.soap.SOAPConnectorClient.reconnect(SOAPConnectorClient.java:296)
    … 8 more

    • I had the same problem and wanted to share my solution. I could see “No trusted certificate found” in stack trace.

      Resolution for this is for your JKS keystore import the server certifikate.

      Easiest way to do this is to use keytool provided in java and import the server certifikate.

      Easiest way to find the certifikate is to use internet explorer and copy the Base64 encoded .cer certifikate file to somedir on your computer. Then issue following keytool command;

      keytool -import -trustcacerts -alias yourserveralias -file cretificatename.cer -keystore yourJksFile.jks

      Accept the certifikate when you get the question. – Done.. you should now be able to establish the SSL connection to the server.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s