22 May 2006

Locating OC4J Instances via OPMN

A good question came to me the other day.

A partner of ours wanted to be able to establish a set of connections to each of the MBeanServer instances running in each OC4J instance contained within an Oracle Application Server cluster.

For configuration simplicity, they wanted to have administrators identify one location from which the OC4J instances (and thus the MBeanServers) could be identified.

The solution was to make use of the Cluster MBeanServer which runs when an Oracle Application Server cluster topology is created and access it via the OPMN service.

For a little background, Cluster MBeanServer in Oracle Application Server provides a view of the cluster topology via JMX -- enabling the various elements within the Cluster Topology to be discovered and acted upon. It contains a few different types of MBeans which represent the elements within to the Cluster Topology.

The hierachy of MBeans within the Cluster MBeanServer can be seen using the "Cluster MBean Browser" provided by ASC.

From this MBeans, the elements of the Cluster can be identified and acted upon. For example, the J2EEServerGroup MBean acts as a MBean Proxy over the Oc4J instances residing within the Group. Using the J2EEServerGroup MBean therefore enables attributes to be retrieved or operations to be executed on a named MBean on ALL of the OC4J instances residing in the Group.

But getting back to the problem at hand, the partner wanted to be able to identify each OC4J instance in the Cluster and establish a connection to each of the individual MBeanServers running therein.

To do this we can make use of the "JVMProxy" MBean.

This JVMProxy MBean represents an active JavaVM which is running OC4J. As such, it exposes two key attributes we can use to identify the OC4J instance -- node and rmiPort -- and therefore directly connect to the MBeanServer.



Using the Groovy work I've been mucking around with lately, I prototyped the solution in 5 minutes. Here it is in Groovy:

import demo.oc4j.jmx.*;

client = new OC4JClient()
client.connect("service:jmx:rmi:///opmn://duraace/cluster","oc4jadmin","welcome1")
helper = client.helper

println "Creating MBeanServer Collection\n"
mbeanservers = new ArrayList()
for(jvmProxy in helper.getMBeanNamesFromQuery("j2eeType=JVMProxy")) {
jvm = helper.createGroovyMBean(jvmProxy)
serviceurl = "service:jmx:rmi://$jvm.node:$jvm.rmiPort"
mbeanserver = new OC4JClient()
mbeanserver.connect(serviceurl,"oc4jadmin","welcome1")
if(mbeanserver.connected) {
println " Connected to: \"$serviceurl\""
mbeanservers.add(mbeanserver)
} else {
println " Could not connect to : \"$serviceurl\""
}
}

// Work over the MBeanServers and show we are connected, then close

println "\nChecking MBeanServer Collection\n"
for(mbeanserver in mbeanservers) {
println " $mbeanserver"
println " Is connected? : $mbeanserver.connected"
println " MBean count : $mbeanserver.connection.mBeanCount"
println " ... calling close()"
mbeanserver.close()
println " Is connected? : $mbeanserver.connected"
}

Which when executed produces the following output, showing that this approach of discovering the OC4J instances from the Cluster MBeanServer is feasible:

Creating MBeanServer Collection

Connected to: "service:jmx:rmi://duraace:12403"
Connected to: "service:jmx:rmi://duraace:12407"
Connected to: "service:jmx:rmi://duraace:12406"
Connected to: "service:jmx:rmi://duraace:12402"
Connected to: "service:jmx:rmi://duraace:12404"
Connected to: "service:jmx:rmi://duraace:12401"
Connected to: "service:jmx:rmi://duraace:12405"
Connected to: "service:jmx:rmi://dreid-lap:12401"

Checking MBeanServer Collection

Client is connected to: rmi://duraace:12403 oc4jadmin
Is connected? : true
MBean count : 198
... calling close()
Is connected? : false
Client is connected to: rmi://duraace:12407 oc4jadmin
Is connected? : true
MBean count : 144
... calling close()
Is connected? : false
...

So it worked in Groovy. The next step was to translate the above into direct Java and package for execution as a JMX client which I'll post in the next installment.

I don't want to shoot all my blog bikkies at once :)

3 comments:

Anonymous said...

Did you ever post the direct Java equivalent?

Anonymous said...

This is very nice. Is it possible in OAS to implement an MBean (and operaton) on a group that can apply an operation to each OC4J defined in the group. So one can go to the mbean cluster browser and perform the operation across all oc4js on each cluster node in that group?

Buttso said...

Sure you can do that. In fact with the way the Cluster MBeanServer has evolved since I've written this, it's something that is quite easy to do. We now have an Group level MBean (ie J2EEServerGroup) that effectively acts as a proxy MBean over all the OC4J instances within the named group. As you perform operations on the Group MBean, it is delegating the same operation (or attribute access) on the specified MBean within the OC4J instances.

The easiest way to get a handle on it is to check the Cluster MBeanServer link from Application Server Control (ASC) which will present you with the hierachy of MBeans you can use.

I will try and write something here about using the J2EEServerGroup MBean in the near future.