Glassfish: JMX + VisualVM + Java

1. Glassfish konfigurieren

Um die Abfrage über JMX im Glassfish zu aktivieren, muss in der Admin-Konsole das Monitoring aktiviert werden. In der domain.xml landet es dann unter "monitoring-service":

<monitoring-service>
  <module-monitoring-levels jdbc-connection-pool="HIGH" />
</monitoring-service>
Bei dem Beispiel werden die JDBC-Connections in das Monitoring aufgenommen. Weiterhin muss der JMX-Connector unter "admin-service" konfiguriert werden.
<jmx-connector port="9876" accept-all="true" address="0.0.0.0" security-enabled="false" name="system" auth-realm-name="admin-realm" />

2. Auslesen mit VisualVM

Ohne Neustart können dann die Werte direkt ausgelesen werden. Will man dafür VisualVM nutzen, muss dafür noch das Plugin "VisualVM-MBeans Plugin" installiert werden.

Dann kann man sich auf den konfigurierten JMX-Port verbinden und die MBeans abfragen. Sofern für den Glassfish ein Passwort vergeben wurde, muss dieses natürlich noch bei den Credentials mit angegeben werden.

3. Auslesen mit Java

Es besteht aber auch die Möglichkeit, die MBeans direkt mit Java Boardmitteln auszulesen. Ein kleines Beispiel habe ich mal hier angefügt, welches das Attribut "numconnacquired" aus den JDBC-Connections ausliest und ausgibt:

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

/**
 * @author Ronny Friedland
 */
public class SimpleJmxClient {

    private static final String HOST = "localhost";
    private static final String PORT = "9876";
    private static final String USERNAME = "admin";
    private static final String PASSWORD = "admin123";

    private static final String QUERY_PATH = "amx:pp=/mon/server-mon[server],type=jdbc-connection-pool-mon,name=resources/Oracle-Pool";
    private static final String QUERY_ATTRIBUTE = "numconnacquired";

    public void read() throws IOException, MalformedObjectNameException, NullPointerException,
            InstanceNotFoundException, ReflectionException {
        Map env = new HashMap();
        String[] creds = { USERNAME, PASSWORD };
        env.put(JMXConnector.CREDENTIALS, creds);

        String url = String.format("service:jmx:rmi:///jndi/rmi://%1$s:%2$s/jmxrmi", HOST, PORT);
        JMXServiceURL serviceUrl = new JMXServiceURL(url);
        JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceUrl, env);
        try {
            MBeanServerConnection mbeanConn = jmxConnector.getMBeanServerConnection();
            ObjectName objName = new ObjectName(QUERY_PATH);
            AttributeList attrs = mbeanConn.getAttributes(objName, new String[] { QUERY_ATTRIBUTE });

            for (Object attr : attrs) {
                Attribute value = (Attribute) attr;
                if (value.getValue() instanceof CompositeDataSupport) {
                    CompositeDataSupport data = (CompositeDataSupport) value.getValue();
                    System.err.println(data.get("count"));
                }
            }
        } finally {
            jmxConnector.close();
        }
    }

    public static void main(final String[] args) throws Exception {
        new SimpleJmxClient().read();
    }
}