Wednesday, 4 April 2012

Weblogic - Accessing Server Runtime details using JMX

We had a requirement to access certain runtime info on the Weblogic server to carry out some admin tasks.

One way to do this is via the JMX API, which in Weblogic is available as an extensive set of MBeans

There are plenty of tutorials and examples of using these on the net.

Now within your Weblogic domain, if you run as part of a Cluster then you would access Domain information on the Admin server if you need to identify the running servers in the cluster.

This uses
weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean
object which is bound only on the Admin server.
One full example of this is at http://middlewaremagic.com/weblogic/?p=210

If you try this on a managed server directly, you will get this error

java.io.IOException: Unable to resolve 'weblogic.management.mbeanservers.domainruntime'. Resolved 'weblogic.management.mbeanservers'
        at weblogic.management.remote.common.ClientProviderBase.makeConnection(ClientProviderBase.java:195)
        at weblogic.management.remote.common.ClientProviderBase.newJMXConnector(ClientProviderBase.java:83)
        at javax.management.remote.JMXConnectorFactory.newJMXConnector(JMXConnectorFactory.java:338)
        at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:247)


So if you do not have the Admin server IP address and port, how can you still identify the other members in the cluster?

A use case for this is if you want to run and access Cluster details from one of the managed servers. But you only have the current running server IP and Port and not that of the Admin server - which is usually the case

There is an MBean for this which is available on the individual managed server as well,
weblogic.management.mbeanservers.runtime.RuntimeServiceMBean

Using this you can get the details of the Admin server and then from there get access to the DomainRuntimeServiceMBean.

A working code example is below

This runs from a JSP where we are able to access the server IP and port via request variables


<%@page import="javax.xml.bind.DatatypeConverter"%>
<%@page import="java.io.IOException"%>
<%@page import="java.net.MalformedURLException"%>
<%@page import="java.util.Hashtable"%>
<%@page import="javax.management.MBeanServerConnection"%>
<%@page import="javax.management.MalformedObjectNameException"%>
<%@page import="javax.management.ObjectName"%>
<%@page import="javax.management.remote.JMXConnector"%>
<%@page import="javax.management.remote.JMXConnectorFactory"%>
<%@page import="javax.management.remote.JMXServiceURL"%>
<%@page import="javax.naming.Context"%>
<%@page import="java.net.URLConnection"%>
<%@page import="java.net.HttpURLConnection"%>
<%@page import="java.net.URL"%>
<%@page import="sun.misc.BASE64Encoder"%>
<%@page import="java.io.InputStream"%>
<%@page import="javax.management.MBeanServer"%>
<%@page import="javax.management.ObjectName"%>
<%@page import="javax.naming.InitialContext"%>

 MBeanServer mBeanServer = null;
 InitialContext ctx = null;
 String administrationURL = null;
 int adminPort = 0;
 try {
  ctx = new InitialContext();
  mBeanServer = (MBeanServer) ctx.lookup("java:comp/env/jmx/runtime");
  
  //Get Admin Server and Port
  ObjectName runtimeService = new ObjectName(
     "com.bea:Name=RuntimeService,Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean");
  String managedServerName = (String) mBeanServer.getAttribute(runtimeService, "ServerName");
  ObjectName msServerRuntime = new ObjectName("com.bea:Name="+ managedServerName + ",Type=ServerRuntime");
  administrationURL = (String) mBeanServer.getAttribute(msServerRuntime, "AdminServerHost");
  adminPort = (Integer) mBeanServer.getAttribute(msServerRuntime, "AdminServerListenPort");
  System.out.println(administrationURL + adminPort);
 } catch (Exception ex) {
  System.out.println("Caught Exception while fetching Admin Server information : "+ ex);
  ex.printStackTrace();
 } finally {
  if (ctx != null) {
   try {
    ctx.close();
   } catch (Exception ex) {
    ex.printStackTrace();
   }
  }
 }

 //Connect via JMX using Admin Server credentials
 String protocol = "t3";
 Integer portInteger = Integer.valueOf(request.getServerPort());
 int port = portInteger.intValue();

 String jndiroot = "/jndi/";
 String mserver = "weblogic.management.mbeanservers.domainruntime";
 JMXServiceURL serviceURL = new JMXServiceURL(protocol, administrationURL, adminPort, jndiroot + mserver);
 Hashtable h = new Hashtable();
 h.put(Context.SECURITY_PRINCIPAL, weblogicuser);
 h.put(Context.SECURITY_CREDENTIALS, weblogicpassword);
 h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,"weblogic.management.remote");
 JMXConnector connector = JMXConnectorFactory.connect(serviceURL, h);
 MBeanServerConnection connection = connector.getMBeanServerConnection();

 ObjectName domainRuntimeService = new ObjectName(
 "com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
 ObjectName[] serverRT = (ObjectName[]) connection.getAttribute(domainRuntimeService, "ServerRuntimes");
 Hashtable server_states = new Hashtable();
 for (ObjectName ser : serverRT) {
  server_states.put((String) connection.getAttribute(ser,"Name"), (String) connection.getAttribute(ser,"State"));
 }

 ObjectName domain1 = (ObjectName) connection.getAttribute(
    domainRuntimeService, "DomainConfiguration");
 ObjectName[] cluster_list = (ObjectName[]) connection
    .getAttribute(domain1, "Clusters");
 for (ObjectName cl : cluster_list) {

  System.out.println("

 Cluster Name: "
    + (String) connection.getAttribute(cl, "Name"));
  try {
   System.out.println("

");
   ObjectName[] servers = (ObjectName[]) connection.getAttribute(cl, "Servers");
   for (ObjectName ser : servers) {
    String server_name = (String) connection.getAttribute(ser, "Name");
   
    try {
     String server_URL = (String) connection.getAttribute(ser, "ListenAddress");
     Integer server_port = (Integer) connection.getAttribute(ser, "ListenPort");
     System.out.println("Server Name: " + server_name + ", Server State: "
        + server_states.get(server_name)
        + ", :" + server_URL + ":"
        + server_port);

   
    }
   }
  }
  connector.close();
 }