Search This Blog

Showing posts with label MBeanServer. Show all posts
Showing posts with label MBeanServer. Show all posts

Friday, 22 October 2010

Generic MBean client for FMW JVM's (Coherence, WLS etc)

Having done some work with MBeans in OC4J 10.1.3.x I decided with the help of steve to create a query tool which allowed you to view the properties/attributes of any MBean from the command line. The JMX API makes it easy to write a generic tool so in the end I can query any JVM with an MBean Server using the tool. In short this is what I did using spring to ensure it was easy to setup with XML and of course run with ANT. Whats good about this is I can just query the MBeans I want to see rather then all of them. Early days but it does what I need it to do at this stage. Different output methods is what I want to do next, currently it just goes to standard out / console.

Step 1 - Define a connection Interface
package oracle.support.rda.server;

import java.util.Hashtable;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXServiceURL;

public interface ServerConnection 
{
  public void doConnection(String url) throws Exception;
  public void doConnection(JMXServiceURL jmxServiceURL, Hashtable env) throws Exception;
  public MBeanServerConnection getConnection();
  public boolean isConnected();
  public void close ();
}

Step 2 - Create an abstract class which implements the interface , pretty much does everything you need to connect to a MBean Server.
package oracle.support.rda.server;

import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;


public abstract class ServerConnectionBase implements ServerConnection
{
  private JMXConnector jmxCon = null;
  private Logger logger = Logger.getLogger(this.getClass().getName());
  
  public ServerConnectionBase()
  {
  }

  public void doConnection(String url) throws Exception
  {
    logger.log(Level.INFO, "JMX Service URL = " + url);
    JMXServiceURL serviceURL = new JMXServiceURL(url);

    jmxCon = JMXConnectorFactory.connect(serviceURL);
  }

  public void doConnection(JMXServiceURL jmxServiceURL, Hashtable env) throws Exception
  {
    logger.log(Level.INFO, "Service URL Path = " + jmxServiceURL.getURLPath());
    jmxCon = JMXConnectorFactory.connect(jmxServiceURL, env);    
  }
  
  public MBeanServerConnection getConnection()
  {
    MBeanServerConnection mbs = null;

    if (jmxCon != null) 
    {
        try 
        {
            mbs = jmxCon.getMBeanServerConnection();
        } 
        catch (Throwable t) 
        {
            logger.log(Level.SEVERE,
                      "** FMW-RDA [ServerConnectionBase.getConnection] : Unable to retrieve MBeanServerConnection");
        }
    }

    return mbs;
  }

  public boolean isConnected()
  {
    boolean ret = false;
    if (jmxCon == null) 
    {
        return false;
    } 
    else 
    {
        try 
        {
            jmxCon.getConnectionId();
            return true;
        } 
        catch (Throwable t) 
        {
            // no need to do anything here
        }
    }

    return ret;
  }

  public void close()
  {
    if (jmxCon != null) 
    {
        try 
        {
            jmxCon.close();
            jmxCon = null;
        } 
        catch (Throwable t) 
        {
        }
    }
  }

}

Step 3 -Finally a class which connects to a WLS 11g instance
package oracle.support.rda.server.connections.wls;

import java.net.URL;

import java.util.Hashtable;
import java.util.Properties;
import java.util.logging.Logger;

import javax.management.remote.JMXConnectorFactory;

import javax.management.remote.JMXServiceURL;

import javax.naming.Context;

import oracle.support.rda.server.ServerConnectionBase;
import oracle.support.rda.server.connections.coherence.CohJMXConnection;

public class WLSJMXConnection extends ServerConnectionBase
{
  private static WLSJMXConnection instance = null;
  private Logger logger = Logger.getLogger(this.getClass().getName());
  private String serviceURL = null;
  
  static
  {
    try
    {
      instance = new WLSJMXConnection();
    }
    catch (Exception e)
    {
      throw new RuntimeException(e.getMessage(), e);
    }
  }
  
  private WLSJMXConnection() throws Exception
  {
    JMXServiceURL jmxServiceURL = null;
    Hashtable h = new Hashtable();
    
    if (instance == null)
    {
      Properties props = new Properties();
      
      URL url = ClassLoader.getSystemResource("server.properties");
      props.load(url.openStream());

      h.put(Context.SECURITY_PRINCIPAL, props.getProperty("wls.username"));
      h.put(Context.SECURITY_CREDENTIALS, props.getProperty("wls.password"));
      h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
         "weblogic.management.remote");
      h.put("jmx.remote.x.request.waiting.timeout", new Long(10000));

      serviceURL = (String) props.getProperty("serviceurl");
      
      jmxServiceURL = 
        new JMXServiceURL(serviceURL);
      
    }
    
    super.doConnection(jmxServiceURL, h);
  }

  public static WLSJMXConnection getInstance() throws Exception
  { 
    return instance;
  }

  public String getServiceURL()
  {
    return serviceURL;
  }
}

So we would then use this connection in a spring XML file as follows using a Factory Class which defines the connections we wish to use. At the time of this post I had an OC4J 10.1.3.x, WLS 10.3.x and Coherence connection implementation classes which extend ServerConnectionBase.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

  <bean id="serverConnection" 
        class="oracle.support.rda.server.ConnectionFactory" 
        factory-method="getWLSConnection" 
        singleton="true">
  </bean> 

Step 4 - Define an interface which allows us to invoke queries against the MBeans and view there attributes

package oracle.support.rda.spring.queries;

import javax.management.MBeanServerConnection;

import oracle.support.rda.spring.exception.RDAQueryException;

public interface RDAQuery 
{
    public Object invoke(MBeanServerConnection mbs) throws RDAQueryException;
    public void setMBeanName(String mbeanName);
}

Step 5 - Define a implementation class for the query interface. The abstract class has been left out here but that's what does all the work of viewing the MBean attributes etc..
package oracle.support.rda.spring.queries;

import java.util.logging.Logger;

import javax.management.MBeanServerConnection;

import oracle.support.rda.spring.exception.RDAQueryException;

public class GenericQuery extends RDAQueryBase
{
  Logger logger = Logger.getLogger(this.getClass().getName());
  
  @Override
  public Object invoke(MBeanServerConnection mbs) throws RDAQueryException 
  {
      logger.info("Generic Query called");
      return super.invoke(mbs);
  }
}


Step 6 - Define the MBeans I wish to query as shown in the example below.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

  <bean id="serverConnection" 
        class="oracle.support.rda.server.ConnectionFactory" 
        factory-method="getWLSConnection" 
        singleton="true">
  </bean>
  
  <bean id="machineQuery" class="oracle.support.rda.spring.queries.GenericQuery">
    <property name="MBeanName">
      <value>com.bea:Name=machine1,Type=Machine</value>
    </property>
  </bean>

  <bean id="nodeMgrQuery" class="oracle.support.rda.spring.queries.GenericQuery">
    <property name="MBeanName">
      <value>com.bea:Name=machine1,Type=NodeManager,Machine=machine1</value>
    </property>
  </bean>
  
  <bean id="appleJVMQuery" class="oracle.support.rda.spring.queries.GenericQuery">
    <property name="MBeanName">
      <value>
        com.bea:ServerRuntime=apple,Name=apple,Type=JVMRuntime      
      </value>
    </property>
    <!--
    The following properties will not be displayed, giving you
    control over what information you show.
    -->
    <property name="nukedAttributes">
      <list>
        <value>ThreadStackDump</value>  
      </list>
    </property>
  </bean>
  
  <bean id="jdbcResourceQuery" class="oracle.support.rda.spring.queries.GenericQuery">
    <property name="MBeanName">
      <value>
        com.bea:Name=jdbc/scottDS,Type=JDBCSystemResource    
      </value>
    </property>
  </bean>

  <bean id="jdbcPropertiesQuery" class="oracle.support.rda.spring.queries.GenericQuery">
    <property name="MBeanName">
      <value>
        com.bea:Name=user,Type=weblogic.j2ee.descriptor.wl.JDBCPropertyBean,Parent=[pastest_dom]/JDBCSystemResources[jdbc/scottDS],Path=JDBCResource[jdbc/scottDS]/JDBCDriverParams/Properties/Properties[user]  
      </value>
    </property>
  </bean>

  <!--  
    This defines the Invoker object, which gets passed 
    a reference to the ServerConnection AND the list of queries
   -->
  <bean id="queryInvoker" class="oracle.support.rda.spring.invoker.QueryInvoker">
    <property name="serverConnection" ref="serverConnection"/>
    <property name="rdaQueries">
      <list>
        <ref bean="machineQuery"/>
        <ref bean="nodeMgrQuery"/>
        <ref bean="appleJVMQuery"/>
        <ref bean="jdbcResourceQuery"/>
        <ref bean="jdbcPropertiesQuery"/>
      </list>
    </property>
  </bean>    

  <!--  
   Bean used to list of MBeans available for use
   -->
  <bean id="showMBeans" class="oracle.support.rda.spring.invoker.MBeanViewer">
    <property name="serverConnection" ref="serverConnection"/>
  </bean> 
  
</beans> 

I provided the ability to remove properties you really don't wish to view for the MBean itself. The name nukedAttributes came from steve.

The queryInvoker bean is what actually invokes the queries themselves which takes a List of query beans themselves and uses the MBean Server Connection we defined at the start. That class is as follows

package oracle.support.rda.spring.invoker;
package oracle.support.rda.spring.invoker;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import oracle.support.rda.server.ServerConnection;
import oracle.support.rda.spring.exception.RDAQueryException;
import oracle.support.rda.spring.queries.RDAQuery;

@SuppressWarnings("unchecked")
public class QueryInvoker {

    private final Logger logger = Logger.getLogger(this.getClass().getName());
    private ServerConnection serverConnection;
    private List<RDAQuery> rdaQueries = new ArrayList<RDAQuery>();
    
    /**
     * @param rdaQueries the rdaQueries to set
     */
    public void setRdaQueries(List rdaQueries) 
    {
      System.out.println(rdaQueries.toString());
      this.rdaQueries = rdaQueries;
    }

    /**
     * @param mbeanServerConnection the mbeanServerConnection to set
     */
    public void setServerConnection(ServerConnection serverConnection) 
    {
      this.serverConnection = serverConnection;
    }

    public QueryInvoker() 
    {
      // TODO Auto-generated constructor stub
      logger.setLevel(Level.ALL);
    }
    
    public int getQueryCount() 
    {
      return rdaQueries.size();
    }
    
    public void run() 
    {
      for(RDAQuery query: rdaQueries) 
      {
          
        try 
        {
            System.out.println(query.invoke(serverConnection.getConnection()));    
        } 
        catch (RDAQueryException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      }
    }
       
}

Output of this running is as follows against OC4J 10.1.3.x in an OPMN managed environment.

C:\jdev\ant-demos\11gFMW\fmw-rda>ant run-rda
Buildfile: build.xml

init:
    [mkdir] Created dir: C:\jdev\ant-demos\11gFMW\fmw-rda\dist
    [mkdir] Created dir: C:\jdev\ant-demos\11gFMW\fmw-rda\classes

compile:
    [javac] Compiling 17 source files to C:\jdev\ant-demos\11gFMW\fmw-rda\classes
    [javac] Note: Some input files use unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.
     [copy] Copying 1 file to C:\jdev\ant-demos\11gFMW\fmw-rda\classes

package:
      [jar] Building jar: C:\jdev\ant-demos\11gFMW\fmw-rda\dist\fmwrda.jar

run-rda:
     [java] 17/10/2010 8:17:48 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
     [java] INFO: Loading XML bean definitions from class path resource [query-beans.xml]
     [java] 17/10/2010 8:17:49 PM oracle.support.rda.server.ServerConnectionBase doConnection
     [java] INFO: Service URL Path = /opmn://beast.au.oracle.com:6003/home
     [java] [oracle.support.rda.spring.queries.GenericQuery@6401d98a, oracle.support.rda.spring.queries.GenericQuery@35712651]
     [java] Queries: 2
     [java] 17/10/2010 8:17:54 PM oracle.support.rda.spring.queries.GenericQuery invoke
     [java] INFO: Generic Query called
     [java]
     [java] [MBean: oc4j:j2eeType=ThreadPool,name=http,J2EEServer=standalone]
     [java] 17/10/2010 8:17:55 PM oracle.support.rda.spring.queries.GenericQuery invoke
     [java] INFO: Generic Query called
     [java]
     [java] *** Attributes ***
     [java]                             (int) minPoolSize                   : 0
     [java]                            (long) poolSize                      : 11
     [java]             ([Ljava.lang.String;) executingThreadNames          : com.evermind.util.ReleasableResourcePooledExecutor$MyWorker@93
c4f1=Thread[JMSServer[beast.au.oracle.com:12601],5,HTTPThreadGroup], com.evermind.util.ReleasableResourcePooledExecutor$MyWorker@1e2299d=Thr
ead[RMIClientConnectionThread-HTTPThreadGroup-10,5,HTTPThreadGroup], com.evermind.util.ReleasableResourcePooledExecutor$MyWorker@d844a9=Thre
ad[RMIServer [/0.0.0.0:12401] count:1,5,HTTPThreadGroup], com.evermind.util.ReleasableResourcePooledExecutor$MyWorker@aa3e6e=Thread[RMIServe
rConnectionThread-7,5,HTTPThreadGroup], com.evermind.util.ReleasableResourcePooledExecutor$MyWorker@56cf01=Thread[RMICallHandler-41,5,HTTPTh
readGroup], com.evermind.util.ReleasableResourcePooledExecutor$MyWorker@83e5f1=Thread[RMIServer [/0.0.0.0:12701] count:1,5,HTTPThreadGroup],
 com.evermind.util.ReleasableResourcePooledExecutor$MyWorker@3de6df=Thread[RMIClientConnectionThread-HTTPThreadGroup-8,5,HTTPThreadGroup], c
om.evermind.util.ReleasableResourcePooledExecutor$MyWorker@12cc81d=Thread[RMIServerConnectionThread-39,5,HTTPThreadGroup], com.evermind.util
.ReleasableResourcePooledExecutor$MyWorker@e834e4=Thread[RMIClientConnectionThread-RMICallHandler-21,5,HTTPThreadGroup], com.evermind.util.R
eleasableResourcePooledExecutor$MyWorker@1a04c26=Thread[RMIClientConnectionThread-RMICallHandler-4,5,HTTPThreadGroup], com.evermind.util.Rel
easableResourcePooledExecutor$MyWorker@ca22a=Thread[RMIServerConnectionThread-9,5,HTTPThreadGroup],
     [java]                (java.lang.String) name                          : http
     [java]                             (int) queueCapacity                 : 0
     [java]                (java.lang.String) objectName                    : oc4j:j2eeType=ThreadPool,name=http,J2EEServer=standalone
     [java]                             (int) maxPoolSize                   : 1024
     [java]                         (boolean) stateManageable               : false
     [java]                            (long) keepAliveTime                 : 600000
     [java]                         (boolean) eventProvider                 : false
     [java]     (javax.management.ObjectName) ObjectName                    : oc4j:j2eeType=ThreadPool,name=http,J2EEServer=standalone
     [java]                             (int) queueSize                     : 0
     [java]                         (boolean) statisticsProvider            : false
     [java]                         (boolean) debug                         : false
     [java]
     [java]
     [java] [MBean: oc4j:j2eeType=J2EEServer,name=standalone]
     [java]
     [java] *** Attributes ***
     [java]  ([Ljavax.management.ObjectName;) DeployedObjects               : [Ljavax.management.ObjectName;@30e34726
     [java]                (java.lang.String) serverBuildDate               : 090727
     [java]  ([Ljavax.management.ObjectName;) J2eeWebSites                  : [Ljavax.management.ObjectName;@1b980630
     [java]  ([Ljavax.management.ObjectName;) Resources                     : [Ljavax.management.ObjectName;@1b45e2d5
     [java]  ([Loracle.oc4j.admin.management.shared.SharedLibrary;) sharedLibraries               : [Loracle.oc4j.admin.management.shared.Sh
aredLibrary;@581de498
     [java]                             (int) state                         : 1
     [java]                         (boolean) dmsOn                         : true
     [java]             ([Ljava.lang.String;) deployedObjects               : oc4j:j2eeType=EJBModule,name="admin_ejb",J2EEApplication=syste
m,J2EEServer=standalone, oc4j:j2eeType=EJBModule,name="jmsrouter_ejb",J2EEApplication=default,J2EEServer=standalone, oc4j:j2eeType=EJBModule
,name="SessionEJB",J2EEApplication=SessionEJB,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=web,J2EEApplication=mapviewer,J2EEServer=s
tandalone, oc4j:j2eeType=WebModule,name=WebServices,J2EEApplication=WSRocks,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=petercrap,J2
EEApplication=petercrap,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=wsil-ias,J2EEApplication=WSIL-App,J2EEServer=standalone, oc4j:j2
eeType=WebModule,name=webapp1,J2EEApplication=testhtml,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=sunilcrap,J2EEApplication=sunilcr
ap,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=WebServices,J2EEApplication=AdrianTest-Project1-WS,J2EEServer=standalone, oc4j:j2eeTy
pe=WebModule,name=javasso-web,J2EEApplication=javasso,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=JMXSoapAdapter-web,J2EEApplication
=system,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=webapp,J2EEApplication=datatags,J2EEServer=standalone, oc4j:j2eeType=WebModule,n
ame=dms,J2EEApplication=system,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=defaultWebApp,J2EEApplication=default,J2EEServer=standalo
ne, oc4j:j2eeType=WebModule,name=SupportWar,J2EEApplication=Support,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=jmsrouter_web,J2EEAp
plication=default,J2EEServer=standalone, oc4j:j2eeType=WebModule,name=webapp1,J2EEApplication=secDemo,J2EEServer=standalone, oc4j:j2eeType=W
ebModule,name=ascontrol,J2EEApplication=ascontrol,J2EEServer=standalone, oc4j:j2eeType=ResourceAdapterModule,name=simpleOemsRA,J2EEApplicati
on=default,J2EEServer=standalone, oc4j:j2eeType=ResourceAdapterModule,name=OracleASjms,J2EEApplication=default,J2EEServer=standalone, oc4j:j
2eeType=J2EEApplication,name=system,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name=WSIL-App,J2EEServer=standalone, oc4j:j2eeType=
J2EEApplication,name=petercrap,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name=default,J2EEServer=standalone, oc4j:j2eeType=J2EEAp
plication,name=mapviewer,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name=Support,J2EEServer=standalone, oc4j:j2eeType=J2EEApplicat
ion,name=secDemo,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name=javasso,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name
=WSRocks,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name=datatags,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name=sunilc
rap,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name=AdrianTest-Project1-WS,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,na
me=testhtml,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name=SessionEJB,J2EEServer=standalone, oc4j:j2eeType=J2EEApplication,name=a
scontrol,J2EEServer=standalone,
     [java]     (javax.management.ObjectName) ObjectName                    : oc4j:j2eeType=J2EEServer,name=standalone
     [java]             ([Ljava.lang.String;) j2eeWebSites                  : oc4j:j2eeType=J2EEWebSite,name=default-web-site,J2EEServer=sta
ndalone,
     [java]                (java.lang.String) serverVendor                  : Oracle Corp.
     [java]                (java.lang.String) serverVersion                 : 10.1.3.5.0
     [java]                         (boolean) statisticsProvider            : false
     [java]                            (long) startTime                     : 1286851282887
     [java]                (java.lang.String) instanceName                  : home
     [java]                (java.lang.String) defaultRoutingId              : g_rt_id
     [java]  ([Ljavax.management.ObjectName;) JavaVMs                       : [Ljavax.management.ObjectName;@edc86eb
     [java]  ([Loracle.oc4j.admin.management.shared.InstalledLibrary;) installedLibraries            : [Loracle.oc4j.admin.management.shared
.InstalledLibrary;@6f7918f0
     [java]                (java.lang.String) oracleHome                    : /home/u01/app/oracle/product/1013AS_blue
     [java]                (java.lang.String) objectName                    : oc4j:j2eeType=J2EEServer,name=standalone
     [java]             ([Ljava.lang.String;) resources                     : oc4j:j2eeType=JDBCResource,name="jdev-connection-pool-scott-11
gr2",J2EEApplication=sunilcrap,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="jdev-connection-pool-scott-11gr1",J2EEApplication=pet
ercrap,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="jdev-connection-pool-scott-11gr1",J2EEApplication=AdrianTest-Project1-WS,J2EE
Server=standalone, oc4j:j2eeType=JDBCResource,name="jdev-connection-pool-scott-11gr2",J2EEApplication=petercrap,J2EEServer=standalone, oc4j:
j2eeType=JDBCResource,name="jdev-connection-pool-srs-10g",J2EEApplication=sunilcrap,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="
jdev-connection-pool-coherence-11gr2",J2EEApplication=sunilcrap,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="jdev-connection-pool
-scott-11gr2",J2EEApplication=AdrianTest-Project1-WS,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="jdev-connection-pool-scott-11gr
1",J2EEApplication=sunilcrap,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="Example OCI Connection Pool",J2EEApplication=default,J2
EEServer=standalone, oc4j:j2eeType=JDBCResource,name="jdev-connection-pool-pas-11gr2",J2EEApplication=sunilcrap,J2EEServer=standalone, oc4j:
j2eeType=JDBCResource,name="jdev-connection-pool-srs-10g",J2EEApplication=AdrianTest-Project1-WS,J2EEServer=standalone, oc4j:j2eeType=JDBCRe
source,name="jdev-connection-pool-srs-10g",J2EEApplication=petercrap,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="oemsdbPool",J2E
EApplication=default,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="jdev-connection-pool-scott-10g",J2EEApplication=sunilcrap,J2EES
erver=standalone, oc4j:j2eeType=JDBCResource,name="jdev-connection-pool-pas-11gr2",J2EEApplication=petercrap,J2EEServer=standalone, oc4j:j2e
eType=JDBCResource,name="jdev-connection-pool-pas-11gr2",J2EEApplication=AdrianTest-Project1-WS,J2EEServer=standalone, oc4j:j2eeType=JDBCRes
ource,name="jdev-connection-pool-scott-10g",J2EEApplication=AdrianTest-Project1-WS,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="s
cottPool",J2EEApplication=default,J2EEServer=standalone, oc4j:j2eeType=JDBCResource,name="jdev-connection-pool-scott-10g",J2EEApplication=pe
tercrap,J2EEServer=standalone, oc4j:j2eeType=JNDIResource,name="AdrianTest-Project1-WS",J2EEServer=standalone,applicationName=AdrianTest-Pro
ject1-WS, oc4j:j2eeType=JNDIResource,name="ascontrol",J2EEServer=standalone,applicationName=ascontrol, oc4j:j2eeType=JNDIResource,name="pete
rcrap",J2EEServer=standalone,applicationName=petercrap, oc4j:j2eeType=JNDIResource,name="javasso",J2EEServer=standalone,applicationName=java
sso, oc4j:j2eeType=JNDIResource,name="sunilcrap",J2EEServer=standalone,applicationName=sunilcrap, oc4j:j2eeType=JNDIResource,name="Support",
J2EEServer=standalone,applicationName=Support, oc4j:j2eeType=JNDIResource,name="datatags",J2EEServer=standalone,applicationName=datatags, oc
4j:j2eeType=JNDIResource,name="WSRocks",J2EEServer=standalone,applicationName=WSRocks, oc4j:j2eeType=JNDIResource,name="WSIL-App",J2EEServer
=standalone,applicationName=WSIL-App, oc4j:j2eeType=JNDIResource,name="secDemo",J2EEServer=standalone,applicationName=secDemo, oc4j:j2eeType
=JNDIResource,name="default",J2EEServer=standalone,applicationName=default, oc4j:j2eeType=JNDIResource,name="testhtml",J2EEServer=standalone
,applicationName=testhtml, oc4j:j2eeType=JNDIResource,name="mapviewer",J2EEServer=standalone,applicationName=mapviewer, oc4j:j2eeType=JNDIRe
source,name="SessionEJB",J2EEServer=standalone,applicationName=SessionEJB, oc4j:j2eeType=JTAResource,name="oc4j-tm",J2EEServer=standalone, o
c4j:j2eeType=JMSResource,name="JMS",J2EEServer=standalone, oc4j:j2eeType=JMSAdministratorResource,name="JMSAdministrator",J2EEServer=standal
one, oc4j:j2eeType=JCAResource,name=JCAResource,ResourceAdapter=OJMS RA,ResourceAdapterModule=simpleOemsRA,J2EEApplication=default,J2EEServe
r=standalone, oc4j:j2eeType=JCAResource,name=JCAResource,ResourceAdapter=OracleASjms,ResourceAdapterModule=OracleASjms,J2EEApplication=defau
lt,J2EEServer=standalone,
     [java]                         (boolean) stateManageable               : true
     [java]     (javax.management.ObjectName) defaultApplication            : oc4j:j2eeType=J2EEApplication,name=default,J2EEServer=standalo
ne
     [java]             ([Ljava.lang.String;) javaVMs                       : oc4j:j2eeType=JVM,name=single,J2EEServer=standalone,
     [java]                (java.lang.String) node                          : beast.au.oracle.com
     [java]                         (boolean) eventProvider                 : true
     [java]

BUILD SUCCESSFUL
Total time: 15 seconds
C:\jdev\ant-demos\11gFMW\fmw-rda>

If you wanted to create queries against a Coherence Server your query-beans.xml file would look like this. The idea here is to specifically query only the MBeans your interested in so you could easily tailor it to meet your needs such as monitoring a JDBC connection pool. The bean with id "showMBean" is used to view all available MBeans you can use.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

  <!--  This creates a a basic ServerConnection object using no username/password -->
  <bean id="serverConnection"
        class="oracle.support.rda.coherence.ConnectionFactory"
        factory-method="getCoherenceConnection"
        singleton="true">
  </bean>
 
  <!--  This section defines the set of Queries to execute, add/remove easily!-->
  <bean id="clusterQuery" class="oracle.support.rda.spring.queries.GenericQuery">
    <property name="MBeanName">
      <value>Coherence:type=Cluster</value>
    </property>
    <!--
    The following properties will not be displayed, giving you
    control over what information you show.
    -->
    <property name="nukedAttributes">
      <list>
        <value>MembersDeparted</value> 
      </list>
    </property>
  </bean>

  <bean id="managementQuery" class="oracle.support.rda.spring.queries.GenericQuery">
    <property name="MBeanName">
      <value>Coherence:type=Management</value>
    </property>
  </bean>

  <bean id="reporterQuery" class="oracle.support.rda.spring.queries.GenericQuery">
    <property name="MBeanName">
      <value>Coherence:type=Reporter</value>
    </property>
  </bean>

  <bean id="runtimeQuery1" class="oracle.support.rda.spring.queries.GenericQuery">
    <property name="MBeanName">
      <value>Coherence:type=Platform,Domain=java.lang,subType=Runtime,nodeId=1</value>
    </property>
    <property name="nukedAttributes">
      <list>
        <value>SystemProperties</value> 
      </list>
    </property>   
  </bean>
 
  <!-- 
    This defines the Invoker object, which gets passed
    a reference to the ServerConnection AND the list of queries
   -->
  <bean id="queryInvoker" class="oracle.support.rda.spring.invoker.QueryInvoker">
    <property name="serverConnection" ref="serverConnection"/>
    <property name="rdaQueries">
      <list>
        <ref bean="clusterQuery"/>
        <ref bean="managementQuery"/>
        <ref bean="reporterQuery"/>
        <ref bean="runtimeQuery1"/>
      </list>
    </property>
  </bean>  

  <!-- 
   Bean used to list of MBeans available for use
   -->
  <bean id="showMBeans" class="oracle.support.rda.spring.invoker.MBeanViewer">
    <property name="serverConnection" ref="serverConnection"/>
  </bean>
 
</beans>

Thursday, 4 September 2008

Displaying OC4J JVM MBean Statistics from a JMX Client

The JVM Mbean within an OC4J 10.1.3.x container has some useful statistic which are displayed in ASC MBean browser. Here is some code which shows how to obtain those from a JMX client.

So the MBean we want to access is as follows:

oc4j:j2eeType=JVM,name=single,J2EEServer=standalone

And the statistics we want to display which ASC shows for us are as follows:
  • FreeHeapSize
  • ActiveThreads
  • HeapSize
So here is the code we will use from a JMX Client. The method which obtains the statistics we need is called "showStats(ObjectName)"


package oracle.support.oc4j.standalone;

import java.text.DateFormat;

import java.util.Date;
import java.util.logging.Logger;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.j2ee.statistics.JVMStats;
import javax.management.j2ee.statistics.Statistic;
import javax.management.j2ee.statistics.BoundedRangeStatistic;

public class JVMMonitor implements Runnable
{
private final Logger logger = Logger.getLogger(this.getClass().getName());
private static final DateFormat DATEFORMAT = DateFormat.getInstance();
private OC4JConnection con = null;
private MBeanServerConnection mbs = null;
private String targetMBean = "oc4j:j2eeType=JVM,name=single,J2EEServer=standalone";
private ObjectName mbean = null;

public JVMMonitor() throws Exception
{
// retrieve an OC4JConnection object this is a singleton class
con = OC4JConnection.getInstance();
mbs = con.getConnection();
mbean = new ObjectName(targetMBean);
System.out.println("** JVM Details **");
System.out.printf("Opmn Managed: %s\n",
mbs.getAttribute(mbean, "opmnEnabled"));
System.out.printf("Java Version: %s\n",
mbs.getAttribute(mbean, "javaVersion"));
System.out.printf("Java Vendor: %s\n",
mbs.getAttribute(mbean, "javaVendor"));
System.out.printf("Host Node: %s\n",
mbs.getAttribute(mbean, "node"));
System.out.printf("RMI Port: %s\n",
mbs.getAttribute(mbean, "rmiPort"));
System.out.printf("RMIS Port: %s\n",
mbs.getAttribute(mbean, "rmisPort"));
System.out.printf("RMI IP: %s\n",
mbs.getAttribute(mbean, "rmiServerAddress"));

}

public void run ()
{

System.out.println("\n");
try
{
System.out.printf("--> Current JVM Details [%s]\n\n",
DATEFORMAT.format(new Date()));


showStats(mbean);
System.out.printf("\n<-- End...\n");
}
catch (Exception e)
{
System.out.println("Error in run()");
e.printStackTrace();
}
finally
{
//con.close();
}
}

private void showStats(ObjectName cp) throws Exception
{

JVMStats stats =
(JVMStats) mbs.getAttribute(cp, "stats");

Object mem = null;
mem = mbs.getAttribute(cp, "totalMemory");
Long memLong = null;
memLong = (Long) mem;

System.out.printf("Total Memory: %s\n", memLong.intValue()/1024/1024 + "M");

mem = mbs.getAttribute(cp, "freeMemory");
memLong = (Long) mem;
System.out.printf("Free Memory: %s\n",
memLong.intValue()/1024/1024 + "M");

System.out.printf("HeapSize: %s\n",
stats.getHeapSize().getCurrent()/1024 + "M");
System.out.printf("HighWaterMark: %s\n",
stats.getHeapSize().getHighWaterMark()/1024 + "M");
System.out.printf("LowWaterMark: %s\n",
stats.getHeapSize().getLowWaterMark()/1024 + "M");

Statistic[] allStats = stats.getStatistics();

for (Statistic s: allStats)
{
if (!s.getName().equalsIgnoreCase("UpTime"))
{
System.out.println("\n--");
System.out.printf("JVM Statistic [%s]\n", s.getName());
System.out.printf("Description : %s\n", s.getDescription());
System.out.printf("Unit : %s\n", s.getUnit());
System.out.printf("Last Sample Time : %s\n", new Date(s.getLastSampleTime()));

BoundedRangeStatistic brs = (BoundedRangeStatistic) s;

if (s.getUnit().equals("THREADS"))
{
System.out.printf("High WaterMark : %s\n", brs.getHighWaterMark());
System.out.printf("Low WaterMark : %s\n", brs.getLowWaterMark());
System.out.printf("Current : %s\n", brs.getCurrent());
}
else
{
System.out.printf("High WaterMark : %s\n", brs.getHighWaterMark()/1024 + "M");
System.out.printf("Low WaterMark : %s\n", brs.getLowWaterMark()/1024 + "M");
System.out.printf("Current : %s\n", brs.getCurrent()/1024 + "M");
}

}
}


}

}



So the output would then be as follows:

** JVM Details **
Opmn Managed: true
Java Version: 1.5.0_06
Java Vendor: Sun Microsystems Inc.
Host Node: beast.au.oracle.com
RMI Port: 12406
RMIS Port: 12706
RMI IP: 10.187.80.70

JVMMonitor
Period to report results in seconds is : 5

** Started [4/09/08 11:29] with 5(sec) interval between reports **


--> Current JVM Details [4/09/08 11:29]

Total Memory: 515M
Free Memory: 453M
HeapSize: 515M
HighWaterMark: 550M
LowWaterMark: 504M

--
JVM Statistic [FreeHeapSize]
Description : The amount of free heap memory
Unit : KILO BYTES
Last Sample Time : Thu Sep 04 11:06:44 EST 2008
High WaterMark : 515M
Low WaterMark : 433M
Current : 453M

--
JVM Statistic [ActiveThreads]
Description : The number of active thread(s)
Unit : THREADS
Last Sample Time : Thu Sep 04 11:06:44 EST 2008
High WaterMark : 64
Low WaterMark : 4
Current : 64

--
JVM Statistic [HeapSize]
Description : The size of the JVM's heap
Unit : KILO BYTES
Last Sample Time : Thu Sep 04 11:06:44 EST 2008
High WaterMark : 550M
Low WaterMark : 504M
Current : 515M

<-- End...

Few people asked for this class itself.

OC4JConnection.java


  
package oracle.support.oc4j.standalone;

import java.io.FileInputStream;

import java.util.Hashtable;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import oracle.oc4j.admin.jmx.remote.api.JMXConnectorConstant;

public class OC4JConnection
{
private static Properties myProperties = new Properties();
private JMXConnector jmxCon = null;
private static OC4JConnection instance = null;
private final Logger logger = Logger.getLogger(this.getClass().getName());
private String username = null;
private String password = null;
private String url = null;

private OC4JConnection
(Properties inProps) throws Exception
{

try
{
processProps(inProps);

logger.log
(Level.INFO, "Username = " + username);
logger.log
(Level.INFO, "Service URL = " + url);

// Define the connection target
JMXServiceURL serviceUrl = new JMXServiceURL(url);

Hashtable env = new Hashtable();

env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
"oracle.oc4j.admin.jmx.remote");

Hashtable credentials = new Hashtable();

credentials.put
(JMXConnectorConstant.CREDENTIALS_LOGIN_KEY, username);
credentials.put(JMXConnectorConstant.CREDENTIALS_PASSWORD_KEY,
password);

env.put(JMXConnector.CREDENTIALS, credentials);

jmxCon = JMXConnectorFactory.newJMXConnector(serviceUrl, env);
// Connect to the target OC4J instance defined in the JMXServiceURL
jmxCon.connect();
logger.log
(Level.INFO, "Connected to OC4J");
}
catch (Exception e)
{
logger.log
(Level.SEVERE,
"** [OC4JConnection()] : Unable to obtain Stand Alone Connection",
e);
e.printStackTrace();
}
}

public static OC4JConnection getInstance() throws Exception
{
if(instance == null)
{
myProperties.load(new FileInputStream("build.properties"));
instance = new OC4JConnection(myProperties);
}

return instance;
}

private void processProps(Properties inProps)
{
username = inProps.getProperty("username");
password = inProps.getProperty("password");
url = inProps.getProperty("serviceurl");

}

public MBeanServerConnection getConnection ()
{
MBeanServerConnection mbs = null;

if (jmxCon != null)
{
try
{
mbs = jmxCon.getMBeanServerConnection();
}
catch (Throwable t)
{
logger.log
(Level.SEVERE,
"**[getConnection] : Unable to retrieve MBeanServerConnection");
}
}

return mbs;
}

/**
* Determine if the client is currently connected
* @return true if connected
*/
public boolean isConnected ()
{
boolean ret = false;
if (jmxCon == null)
{
return false;
}
else
{
try
{
jmxCon.getConnectionId();
return true;
}
catch (Throwable t)
{
//
}
}

return ret;
}

/**
* Close the JMXConnector.
*/
public void close ()
{
if (jmxCon != null)
{
try
{
jmxCon.close();
jmxCon = null;
logger.log
(Level.INFO, "Closed Connection to OC4J");
}
catch (Throwable t)
{
}
}
}
}

Monday, 14 April 2008

Obtaining statistics on a Message Driven Bean from a JMX Client connecting to OC4J 10.1.3.x

A while ago steve showed me a few code demos on how to access OC4J Mbeans within OC4J 10.1.3.x. Since then I have created a few command line clients to perform tasks which admin_client.jar doesn't expose. A few for example include these.
  • View application statuses
  • Stop/Start a Message Driven Bean
While doing this I noticed that if you ever need to access a MDB statistics you would do it with code as follows.


private void showStats(ObjectName cp) throws Exception
{

EJBStats stats =
(EJBStats) mbs.getAttribute(cp, "stats");



When you run this with say with a 10.1.3.3 OAS client side distribution home you will get a runtime exception as follows.

[java] 14/04/2008 12:05:27 oracle.j2ee.rmi.RMIMessages
EXCEPTION_ORIGINATES_FROM_THE_REMOTE_SERVER
[java] WARNING: Exception returned by remote server: {0}
[java] java.lang.NoClassDefFoundError:
Loracle/oc4j/admin/management/callbackinterfaces/MessageDrivenBeanCallBackIf;


In order to get around this add the following JAR to your classpath, which can be obtained from the OAS server home or a stand alone OC4J home.

$ORACLE_HOME\j2ee\home\lib\oc4j-internal.jar

Wednesday, 18 July 2007

Connecting to the OC4J MBeanServer Doc Issue

I was attempting to connect to the OC4J MBeanServer in my opmn managed OC4J instance and was using the online documentation below.

http://download.oracle.com/docs/cd/B31017_01/web.1013/b28952/mbeans.htm#CIHFDJBJ

I found that in the example the service URL was specified incorrectly.
// Create a variable for a URL containing data needed to access 
// the connection target; in this case, an OPMN-managed OC4J instance
String url="service:jmx:rmi///opmn://opmnhost1.company.com:6003/home"

It is missing the : in the service URL. The correct way is shown below you will see the : added after rmi. A documentation bug has been filed.

Eg:

private String url="service:jmx:rmi:///opmn://papicell-au2.au.oracle.com:6003/home";