Hi All,

Jay SenSharma

Jay SenSharma

Here is a very simple JMSX code which we can use to monitor any JMS resource deployed on our Server. Most of the time we face issues while writing the E-Mail Notification codes or some sort of notifications for health checking routine of our JMS Servers. This code will really help us.

The best part of this code is …This code is going to display all the JMS attribute and statistics in a Tabular format.

import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.management.AttributeList;

import weblogic.management.MBeanHome;
import weblogic.management.WebLogicMBean;

public class JMSStats
{
private final static String JNDI_FACTORY = “weblogic.jndi.WLInitialContextFactory”;
private final static int MAX_OUTPUTBUFFER_SIZE = 8096;

private String beanTypeFilter;
private String beanNameFilter;
private String url = “t3://localhost:7001”;
private String password = “weblogic”;
private String username = “weblogic”;
private boolean useLocalMBeanHome;
private boolean wantParentName = true;

String EOL;
private MBeanHome mbh;
private StringBuffer outputBuffer = new StringBuffer(8096);
private JMSStats(String [] args) throws Exception
{
EOL = System.getProperty(“line.separator”);
if (EOL == null) EOL = “n”;
String usage =
EOL +
” Usage: java JMSStats [-url URL ]” + EOL +
” [-user username] [-pass password]” + EOL +
” [-local]” + EOL +
” [-noparent]” + EOL +
” [-type bean-type-filter] ” + EOL +
” [-name bean-name-filter] ” + EOL +
EOL +
” -url URL URL to contact server. Default ” + url + EOL +
” -user username Username. Default ” + username + EOL +
” -pass password Password. Default ” + password + EOL +
” -type filter Only get stats from bean types containing filter.”
+ EOL +
” -name filter Only get stats from bean names containing filter.”
+ EOL +
” -local Only query local statistics (faster). ” + EOL +
” -noparent Do not print bean’s parent name (faster).” + EOL +
“” + EOL +
” Example, show destination statistics local to server1:” + EOL +
EOL +
” java JMSStats -url t3://server1:7001 -local -bean dest” +
EOL + EOL;

// parse command line

int i = 0;
try {
for (; i < args.length; i++) {
if (args[i].equals(“-url”)) {
url = args[++i];

} else if (args[i].startsWith(“-user”)) {
username = args[++i];

} else if (args[i].startsWith(“-pass”)) {
password = args[++i];

} else if (args[i].equals(“-name”)) {
beanNameFilter = args[++i].toLowerCase();

} else if (args[i].equals(“-bean”)) {
beanTypeFilter = args[++i].toLowerCase();

} else if (args[i].equals(“-type”)) {
beanTypeFilter = args[++i].toLowerCase();

} else if (args[i].equals(“-local”)) {
useLocalMBeanHome = true;

} else if (args[i].equals(“-noparent”)) {
wantParentName = false;

} else if (args[i].equals(“-help”)) {
output(usage);
outputFlush();
return;

} else {
throw new Exception(EOL + “Unknown argument ‘” + args[i] + “‘”
+ EOL + usage);
}
}
} catch (ArrayIndexOutOfBoundsException aio) {
throw new Exception(EOL + “Missing argument for ‘” + args[–i] + “‘”
+ EOL + usage);
}

output(“JMS statistics for url=” + url
+ “, user=” + username
+ “, type=” + beanTypeFilter
+ “, name=” + beanNameFilter
+ “, local=” + useLocalMBeanHome
+ “, parent=” + wantParentName
+ “.” + EOL);

// get our context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, url);
env.put(Context.SECURITY_PRINCIPAL, username);
env.put(Context.SECURITY_CREDENTIALS, password);
InitialContext ctx = new InitialContext(env);

// get our bean home
if (useLocalMBeanHome)
mbh = (MBeanHome)ctx.lookup(MBeanHome.LOCAL_JNDI_NAME);
else
mbh = (MBeanHome)ctx.lookup(MBeanHome.ADMIN_JNDI_NAME);
}

private void printAll() throws Exception {
printTables(“JMSRuntime”, true, new Column [][] {
{ new Column(“conn.”, “cur”, “count”, 5, “ConnectionsCurrentCount”),
new Column(“conn.”, “high”, “count”, 5, “ConnectionsHighCount”),
new Column(“conn.”, “total”, “count”, 5, “ConnectionsTotalCount”),
new Column(“srvrs”, “cur”, “count”, 5, “JMSServersCurrentCount”),
new Column(“srvrs”, “high”, “count”, 5, “JMSServersHighCount”),
new Column(“srvrs”, “total”, “count”, 5, “JMSServersTotalCount”)}});

printTables(“JMSServerRuntime”, true, new Column [][] {
{ new Column(“dests”, “cur”, “count”, 6, “DestinationsCurrentCount”),
new Column(“dests”, “high”, “count”, 6, “DestinationsHighCount”),
new Column(“dests”, “total”, “count”, 6, “DestinationsTotalCount”)},

{ new Column(“msgs”, “cur”, “count”, 8, “MessagesCurrentCount”),
new Column(“msgs”, “pndng”, “count”, 8, “MessagesPendingCount”),
new Column(“msgs”, “high”, “count”, 8, “MessagesHighCount”),
new Column(“msgs”, “rcvd”, “count”, 8, “MessagesReceivedCount”),
new Column(“msgs”, “thresh”, “time”, 8, “MessagesThresholdTime”)},

{ new Column(“bytes”, “cur”, “count”, 8, “BytesCurrentCount”),
new Column(“bytes”, “pndng”, “count”, 8, “BytesPendingCount”),
new Column(“bytes”, “high”, “count”, 8, “BytesHighCount”),
new Column(“bytes”, “rcvd”, “count”, 8, “BytesReceivedCount”),
new Column(“bytes”, “thresh”, “time”, 8, “BytesThresholdTime”)}});

printTables(“JMSDestinationRuntime”, true, new Column [][] {
{ new Column(“consumers”, “cur”, “count”, 9, “ConsumersCurrentCount”),
new Column(“consumers”, “high”, “count”, 9, “ConsumersHighCount”),
new Column(“consumers”, “total”, “count”, 9, “ConsumersTotalCount”)},

{ new Column(“msgs”, “cur”, “count”, 8, “MessagesCurrentCount”),
new Column(“msgs”, “pndng”, “count”, 8, “MessagesPendingCount”),
new Column(“msgs”, “high”, “count”, 8, “MessagesHighCount”),
new Column(“msgs”, “rcvd”, “count”, 8, “MessagesReceivedCount”),
new Column(“msgs”, “thresh”, “time”, 8, “MessagesThresholdTime”)},

{ new Column(“bytes”, “cur”, “count”, 8, “BytesCurrentCount”),
new Column(“bytes”, “pndng”, “count”, 8, “BytesPendingCount”),
new Column(“bytes”, “high”, “count”, 8, “BytesHighCount”),
new Column(“bytes”, “rcvd”, “count”, 8, “BytesReceivedCount”),
new Column(“bytes”, “thresh”, “time”, 8, “BytesThresholdTime”)}});

printTables(“JMSConnectionRuntime”, true, new Column [][] {
{ new Column(“sessions”, “cur”, “count”, 9, “SessionsCurrentCount”),
new Column(“sessions”, “high”, “count”, 9, “SessionsHighCount”),
new Column(“sessions”, “total”, “count”, 9, “SessionsTotalCount”)}});

printTables(“JMSSessionRuntime”, false, new Column [][] {
{ new Column(“ack”, “mode”, 9, “AcknowledgeMode”),
new Column(“consumers”, “cur”, “count”, 9, “ConsumersCurrentCount”),
new Column(“consumers”, “high”, “count”, 9, “ConsumersHighCount”),
new Column(“producers”, “cur”, “count”, 9, “ProducersCurrentCount”),
new Column(“producers”, “high”, “count”, 9, “ProducersHighCount”)},

{ new Column(“msgs”, “sent”, “count”, 6, “MessagesSentCount”),
new Column(“msgs”, “rcvd”, “count”, 6, “MessagesReceivedCount”),
new Column(“msgs”, “pndng”, “count”, 6, “MessagesPendingCount”),
new Column(“bytes”, “sent”, “count”, 8, “BytesSentCount”),
new Column(“bytes”, “rcvd “, “count”, 8, “BytesReceivedCount”),
new Column(“bytes”, “pndng”, “count”, 8, “BytesPendingCount”)}});

printTables(“JMSProducerRuntime”, false, new Column [][] {
{ new Column(“msgs”, “sent”, “count”, 6, “MessagesSentCount”),
new Column(“msgs”, “pndng”, “count”, 6, “MessagesPendingCount”),
new Column(“bytes”, “sent”, “count”, 8, “BytesSentCount”),
new Column(“bytes”, “pndng”, “count”, 8, “BytesPendingCount”)}});

printTables(“JMSConsumerRuntime”, false, new Column [][] {
{ new Column(“dest”, 20, “DestinationName”),
new Column(“durab”, 5, “Durable”),
new Column(“activ”, 5, “Active”),
new Column(“selector”, 20, “Selector”)},

{ new Column(“msgs”, “sent”, “count”, 6, “MessagesReceivedCount”),
new Column(“msgs”, “pndng”, “count”, 6, “MessagesPendingCount”),
new Column(“bytes”, “sent”, “count”, 8, “BytesReceivedCount”),
new Column(“bytes”, “pndng”, “count”, 8, “BytesPendingCount”)}});

// “JMSDurableSubscriberRuntime” is new as of 6.1, not available in 6.0.
printTables(“JMSDurableSubscriberRuntime”, false, new Column [][] {
{ new Column(“clientid”, 20, “ClientID”),
new Column(“noloc”, 5, “NoLocal”),
new Column(“activ”, 5, “Active”),
new Column(“selector”, 20, “Selector”)},

{ new Column(“msgs”, “curr”, “count”, 6, “MessagesCurrentCount”),
new Column(“msgs”, “pndng”, “count”, 6, “MessagesPendingCount”),
new Column(“bytes”, “curr”, “count”, 8, “BytesCurrentCount”),
new Column(“bytes”, “pndng”, “count”, 8, “BytesPendingCount”)}});

printTables(“JMSSessionPoolRuntime”, false, new Column [][] {
{ new Column(“sessions”, “cur”, “count”, 9,
“ConnectionConsumersCurrentCount”),
new Column(“sessions”, “high”, “count”, 9,
“ConnectionConsumersHighCount”),
new Column(“sessions”, “total”, “count”, 9,
“ConnectionConsumersTotalCount”)}});
}

/**
* Print the values for the given mbean, one table per array of columns.
*/
private void printTables(String beanName,boolean printEmptyTable,Column [][] tables) throws Exception {
// skip tables for beans we are filtering out
if (beanTypeFilter != null
&& -1 == beanName.toLowerCase().indexOf(beanTypeFilter)) return;

// build up an array of attribute names
int numAtts = 0;

for (int i = 0; i < tables.length; i++) {
numAtts+=tables[i].length;
}

String [] atts = new String[numAtts + 1]; // one for the name
int currAtt = 0;
atts[currAtt++] = “Name”;

for (int i = 0; i < tables.length; i++) {
for (int j = 0; j < tables[i].length; j++) {
atts[currAtt++] = tables[i][j].getAttributeName();
}
}

// get sorted list of beans with the given type
Vector exceptions = new Vector();
StatBean[] beans = getStatBeans(beanName, atts, exceptions);
if (exceptions.size() == 0 &&
!printEmptyTable &&
beans.length == 0) {
return;
}

// print the results
for (int i = 0; i < tables.length; i++) {
printTable(beans, beanName, tables[i]);
}

for (int i = 0; i < exceptions.size(); i++) {
Exception exc = (Exception)exceptions.elementAt(i);
output(EOL + “Exc” + (i+1) + ” ” + ” ” + exc.toString());
output(EOL + “JMSStats may have requested an unknown attribute.” + EOL);
outputFlush();
exc.printStackTrace();
}
}

/**
* Print a table, including its column headers and its data.
*/
private void printTable(StatBean [] beans,String beanName, Column [] column) throws Exception {

// insert the first column — its always the name of the object
Column [] hold = new Column[column.length+1];
System.arraycopy(column, 0, hold, 1, column.length);
hold[0] = new Column(beanName, 50, “”);
column = hold;

// print the table headers
output(EOL);
int maxTitles = 0;
for (int i = 0; i < column.length; i++) { if (column[i].numTitles() > maxTitles)
maxTitles = column[i].numTitles();
}

for (int h = maxTitles; h > 0; h–) {
for (int i = 0; i < column.length; i++) { if (column[i].numTitles() >= h)
column[i].print(column[i].getTitle(column[i].numTitles() – h));
else
column[i].print(“”);
}
output(EOL);
}

for (int i=0; i < column.length; i++) {
column[i].printSeparator();
}

output(EOL);

// print the data, row by row
for (int row = 0; row < beans.length; row++) {
// skip rows for bean names we are filtering out
if (beanNameFilter != null &&
-1 == beans[row].getName().toLowerCase().indexOf(beanNameFilter))
continue;

column[0].print(beans[row].getName());
for (int i = 1; i < column.length; i++) {
column[i].print(beans[row].getValue(column[i].getAttributeName()));
}

output(EOL);
}
outputFlush();
output(EOL);
}

/**
* This method returns a sorted array of “wrapped” mbeans of the given type.
* Any exceptions that occur are appended to the passed-in exceptions vector.
*/
private StatBean[] getStatBeans(String typeName,String [] atts,Vector exceptions) {
Set mbeans;
try {
mbeans = mbh.getMBeansByType(typeName);
} catch (Exception e) {
outputFlush();
exceptions.add(e);
return new StatBean[0];
}

if (mbeans == null) {
exceptions.add(new Exception(
“WARNING: Can not find MBean of type <” + typeName + “>” + EOL +
“This type of mbean may not exist for this version of WebLogic.”
));
return new StatBean[0];
}

// turn the set of mbeans into an array and sort it
StatBean [] statBeans = new StatBean[mbeans.size()];
int i = 0;

for (Iterator iter = mbeans.iterator(); iter.hasNext(); i++) {
WebLogicMBean mbean = (WebLogicMBean)iter.next();
// the StatBean wrapper class will invoke the mbean
// in order to cache all of its attribute values
statBeans[i] = new StatBean(mbean, atts, exceptions);
}

Arrays.sort(statBeans);
return statBeans;
}

private void outputFlush() {
System.out.println(outputBuffer.toString());
outputBuffer.setLength(0);
}

private void output(String s) {
outputBuffer.append(s);
if (outputBuffer.length() > MAX_OUTPUTBUFFER_SIZE) outputFlush();
}

private void output(char c) {
outputBuffer.append(c);
if (outputBuffer.length() > MAX_OUTPUTBUFFER_SIZE) outputFlush();
}

public static void main(String[] args)
throws Exception {
JMSStats s = new JMSStats(args);
if (s.mbh == null) return; // if -help specified
s.printAll();
}

/**
* The StatBean inner class wraps an instance of a runtime-mbean.
* Its purpose is to cache the mbean’s attribute values in order
* to reduce the number of network calls to the server.
*/
private class StatBean implements Comparable {
String name = “Unknown”;

private WebLogicMBean mbean;

private HashMap values = new HashMap();

private String getValue(String attName) {
return (String)values.get(attName);
}

private StatBean(WebLogicMBean m, String [] atts, Vector exceptions) {
mbean = m;

// In order to reduce the number of remote calls to the server,
// get all requested attribute values in one call and cache them
// in the “values” hashmap.

AttributeList al;
try {
// a remote call
al = mbean.getAttributes(atts);
} catch (Exception exc) {
exceptions.addElement(exc);

for (int i = 0; i < atts.length; i++) {
values.put(atts[i], “Exc” + exceptions.size());
}

return;
}

int i = 0;

for (Iterator iter = al.iterator(); iter.hasNext(); i++) {

javax.management.Attribute att =
(javax.management.Attribute)iter.next();

if (att.getValue() == null)
values.put(atts[i], “null”);
else
values.put(atts[i], att.getValue().toString());

}

name = (String)values.get(“Name”);

if (wantParentName) {
try {
WebLogicMBean parent = mbean.getParent();
if (parent != null)
name = parent.getName() + “.” + name;
} catch (Exception exc) {
exceptions.addElement(exc);
}
}
}

private String getName() {
return name;
}

public int compareTo(Object o) {
if (o == null) return 1;
return name.compareTo(o.toString());
}

public boolean equals(Object o) {
if (o == null) return false;
return name.equals(o.toString());
}

public String toString() {
return name;
}
}

/**
* The Column inner class stores the title, width and
* mbean attribute name for a particular column within a table.
*/
private class Column {
private int width;
private String [] title;
private String attributeName;

private Column(String [] title, int width,
String attributeName) {
this.title = title;
this.width = width;
this.attributeName = attributeName;
}

private Column(String t1, int width,
String attributeName) {
this(new String [] { t1 }, width, attributeName);
}

private Column(String t1, String t2, int width,
String attributeName) {
this(new String [] { t1, t2 }, width, attributeName);
}

private Column(String t1, String t2, String t3, int width,
String attributeName) {
this(new String [] { t1, t2, t3 }, width, attributeName);
}

private int numTitles() {
return title.length;
}

private String getTitle(int i) {
return title[i];
}

private String getAttributeName() {
return attributeName;
}

// print right aligned string
private void print(String s) {
if (s == null) s = “”;
for (int i = width – s.length(); i > 0; i–) output(‘ ‘);
output(s);
output(‘ ‘);
}

// print a separator between column title and column values
private void printSeparator() {
for (int i = 0; i < width; i++) output(‘-‘);
output(‘ ‘);
}
} // end private class column
}

regards
Jay SenSharma

If you enjoyed this post, please considerleaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.