“There are times when fear is good. It must keep its watchful place at the heart's controls. There is advantage in the wisdom won from pain.” - Aeschylus quotes
There is no single tool that WebSphere administrators can rely on for all their tasks. When I wrote about Java based JMX tool for deployment, some of you expressed your concerns on introducing yet another tool or language for day to day tasks. Though Jacl and Jython covers 99% of our day to day operations, I believe there are certain benefits to embrace Java as an utility language. Sometimes, it can take you to places, where Jython or Jacl can't go :) One such use I found was, combining WebSphere Custom Service and JMX MBean for monitoring JVM startups and shutdown events.
IBM introduced something called Custom Services in WebSphere 4.0, then there came the JMX specification which IBM began supporting it from WAS V5. IBM WAS team did a great job of integrating both, which has been useful to this day.
Links:
Creating and registering standard, dynamic, and open custom MBeans
Extending the WebSphere Application Server administrative system with custom MBeans
If you are writing your own MBean, You would have to register your MBean with the MBean Server
that runs on each JVM and the MBean needs to be activated. I picked an easy route, implemented my own JMXAgent MBean with the custom service option, so that my MBean can be activated at the server startup every time.
Here is the code template for this MBean
public class MyJMXService implements CustomService, JMXManageable {
public class Collab extends RuntimeCollaborator {
public String getIdentification() {return "MyJMXAgent"; }
// add your own method that needs to be called from wsadmin or JMX
}; // end collab class
public void initialize(Properties argProps) throws Exception {
}
public void shutdown() throws Exception {
}
}
Methods initialize() and shutdown() are implemented from CustomService interface and will be called by MBean server upon JVM startup and shutdown events. My goal is send out some email alerts on either events, also to activate my MBean in initialize() method.
If you wonder about the innerclass Collab, it's a runtime Collaborator class and it's methods are callback methods by the MBean Server. So that's the ideal place for adding methods that could be useful for administrative tasks, which could be invoked from either wsadmin or any JMX interface.
One such task that was essential with my development community was clearing JSP cache. Sometimes, some of my developers request us to clear JSP cache even when their apps don't use JSPs! They must be superstitious to think their problem will go away with a JSP cache clearing :) So I ended up implementing a method to clear the JSP temp folder for a given application, it is being called from our JMX Deployment tool by change management team from a remote server.
Word of caution, great power comes with great responsibilities, make sure you are not doing anything that sabotage your environment, implement a good validation before firing any tasks.
public class MyJMXService implements CustomService, JMXManageable {
public class Collab extends RuntimeCollaborator {
public String getIdentification() {return "MyJMXAgent"; }
public void clearFolder(String folder) throws Exception
{
String result="good";
try {
if (folder.indexOf("/WebSphere/AppServer/") > 0 ) && (folder.indexOf("/temp/") > 0 ) {
System.out.println("Clearing.."+folder);
clearFolder( (new File(folder)) );
System.out.println("Folder cleared"+folder);
}
else {
System.out.println("MyJMXAgent:"+folder+" is not a JSP cache folder error");
result="MyJMXAgent:"+folder+" is not a JSP cache folder error";
}
}
catch (Exception e) {
System.out.println("MyJMXAgent:Error in clearing JSP Cache");
result = "MyJMXAgent:Error in clearing JSP Cache";
}
if (!(result.equals("good") )) throw (new Exception(result));
}
public void clearFolder(File path) throws Exception
{
try {
File[] files = path.listFiles();
for(int i=0; i<files.length; ++i)
{
if(files[i].isDirectory()) clearFolder(files[i]);
files[i].delete();
}
}
catch (Exception e) { throw e; }
}
}; // end collab class
public void initialize(Properties argProps) throws Exception {
String propURL = argProps.getProperty(PROP_KEY);
try {
JVMName = com.ibm.websphere.runtime.ServerName.getFullName();
}
catch (Exception e) {
System.out.println(label + "JMX init error: " + e.toString());
}
loadProperties(propURL);
// Notify the admins on startup
sendMailHelper("Started");
// Let's activiate the bean
MBeanFactory mbfactory = AdminServiceFactory.getMBeanFactory();
RuntimeCollaborator collab = new Collab();
mbfactory.activateMBean("MyJMXBean",collab,"MyJMXAgent1",getProperty("MyJMXAgent.descriptor"));
}
public void shutdown() throws Exception {
String label = mainLabel + "shutdown: ";
sendMailHelper("Shutdown");
}
}
// Implement your own sendMailHelper and loadProperties
Easier way would be to register it thru WebSphere console. If you go under AppServers --> Administration Services, you will see a link for adding Custom Services. Lot of my friends here forget to click on StartUp check box when adding a new service.
The important configuration values for Custom Services
The better way: Jython
There is even a better way to do it than Admin Console, I know how much you all love Jython, here is a snippet that adds the custom service into all WebSphere processes, including dmgr and nodeagent.
attrs = []
attrs.append(["externalConfigURL","/opt/apps/webdata/config/WAS/MyJMX.properties"])
attrs.append(["classname","MyJMXService"])
attrs.append(["displayName", "MyJMXAgent"])
attrs.append(["classpath", "/opt/apps/webdata/config/WAS/MyJMXAgent.jar"])
attrs.append(["enable","true"])
nodes = AdminConfig.list('Node').split(lineSeparator)
servers = AdminTask.listServers('-serverType APPLICATION_SERVER ')
servers = AdminUtilities.convertToList(servers)
for aServer in servers:
AdminConfig.create("CustomService", aServer, attrs)
AdminConfig.save( )
There is no single tool that WebSphere administrators can rely on for all their tasks. When I wrote about Java based JMX tool for deployment, some of you expressed your concerns on introducing yet another tool or language for day to day tasks. Though Jacl and Jython covers 99% of our day to day operations, I believe there are certain benefits to embrace Java as an utility language. Sometimes, it can take you to places, where Jython or Jacl can't go :) One such use I found was, combining WebSphere Custom Service and JMX MBean for monitoring JVM startups and shutdown events.
IBM introduced something called Custom Services in WebSphere 4.0, then there came the JMX specification which IBM began supporting it from WAS V5. IBM WAS team did a great job of integrating both, which has been useful to this day.
MBeans
There are many ways to create JMX MBeans and so are many more useful ways that you could take advantage of them. Here are some of the links I found useful to get to know more about MBeans. If not, make use of your friend "google".Links:
Creating and registering standard, dynamic, and open custom MBeans
Extending the WebSphere Application Server administrative system with custom MBeans
Custom Service
You can create one or more custom services for an application server. Each custom services defines a class that is loaded and initialized whenever the server starts and shuts down. Each of these classes must implement the com.ibm.websphere.runtime.CustomService interface. After you create a custom service, you can use the administrative console to configure that custom service for your application serversJVM Monitor
If you are writing your own MBean, You would have to register your MBean with the MBean Server that runs on each JVM and the MBean needs to be activated. I picked an easy route, implemented my own JMXAgent MBean with the custom service option, so that my MBean can be activated at the server startup every time.
Here is the code template for this MBean
public class MyJMXService implements CustomService, JMXManageable {
public class Collab extends RuntimeCollaborator {
public String getIdentification() {return "MyJMXAgent"; }
// add your own method that needs to be called from wsadmin or JMX
}; // end collab class
public void initialize(Properties argProps) throws Exception {
}
public void shutdown() throws Exception {
}
}
Methods initialize() and shutdown() are implemented from CustomService interface and will be called by MBean server upon JVM startup and shutdown events. My goal is send out some email alerts on either events, also to activate my MBean in initialize() method.
If you wonder about the innerclass Collab, it's a runtime Collaborator class and it's methods are callback methods by the MBean Server. So that's the ideal place for adding methods that could be useful for administrative tasks, which could be invoked from either wsadmin or any JMX interface.
One such task that was essential with my development community was clearing JSP cache. Sometimes, some of my developers request us to clear JSP cache even when their apps don't use JSPs! They must be superstitious to think their problem will go away with a JSP cache clearing :) So I ended up implementing a method to clear the JSP temp folder for a given application, it is being called from our JMX Deployment tool by change management team from a remote server.
Word of caution, great power comes with great responsibilities, make sure you are not doing anything that sabotage your environment, implement a good validation before firing any tasks.
public class MyJMXService implements CustomService, JMXManageable {
public class Collab extends RuntimeCollaborator {
public String getIdentification() {return "MyJMXAgent"; }
public void clearFolder(String folder) throws Exception
{
String result="good";
try {
if (folder.indexOf("/WebSphere/AppServer/") > 0 ) && (folder.indexOf("/temp/") > 0 ) {
System.out.println("Clearing.."+folder);
clearFolder( (new File(folder)) );
System.out.println("Folder cleared"+folder);
}
else {
System.out.println("MyJMXAgent:"+folder+" is not a JSP cache folder error");
result="MyJMXAgent:"+folder+" is not a JSP cache folder error";
}
}
catch (Exception e) {
System.out.println("MyJMXAgent:Error in clearing JSP Cache");
result = "MyJMXAgent:Error in clearing JSP Cache";
}
if (!(result.equals("good") )) throw (new Exception(result));
}
public void clearFolder(File path) throws Exception
{
try {
File[] files = path.listFiles();
for(int i=0; i<files.length; ++i)
{
if(files[i].isDirectory()) clearFolder(files[i]);
files[i].delete();
}
}
catch (Exception e) { throw e; }
}
}; // end collab class
public void initialize(Properties argProps) throws Exception {
String propURL = argProps.getProperty(PROP_KEY);
try {
JVMName = com.ibm.websphere.runtime.ServerName.getFullName();
}
catch (Exception e) {
System.out.println(label + "JMX init error: " + e.toString());
}
loadProperties(propURL);
// Notify the admins on startup
sendMailHelper("Started");
// Let's activiate the bean
MBeanFactory mbfactory = AdminServiceFactory.getMBeanFactory();
RuntimeCollaborator collab = new Collab();
mbfactory.activateMBean("MyJMXBean",collab,"MyJMXAgent1",getProperty("MyJMXAgent.descriptor"));
}
public void shutdown() throws Exception {
String label = mainLabel + "shutdown: ";
sendMailHelper("Shutdown");
}
}
// Implement your own sendMailHelper and loadProperties
Descriptor
One last piece you would need is a MBean descriptor, a simple XML file that would be used by MBean Server to understand the MBean and to expose the appropriate methods.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE MBean SYSTEM "MbeanDescriptor.dtd">
<MBean type="MyJMXService">
<attribute name="identification" type="java.lang.String" getMethod="getIdentification"/>
<operation name="clearFolder" role="operation" type="void" targetObjectType="objectReference" impact="ACTION" description="Clears JSP Cache">
<signature>
<parameter name="folder" description ="folder name" type="java.lang.String" />
</signature>
</operation>
</MBean>
<!DOCTYPE MBean SYSTEM "MbeanDescriptor.dtd">
<MBean type="MyJMXService">
<attribute name="identification" type="java.lang.String" getMethod="getIdentification"/>
<operation name="clearFolder" role="operation" type="void" targetObjectType="objectReference" impact="ACTION" description="Clears JSP Cache">
<signature>
<parameter name="folder" description ="folder name" type="java.lang.String" />
</signature>
</operation>
</MBean>
We are exposing only method clearFolder() to users with "operation" and above access roles.
Register
Now that we have our MBean, packed in a Jar, what do we do with it? How can it be registered within WebSphere? There is an easier way and there is a better way to do it.Easier way would be to register it thru WebSphere console. If you go under AppServers --> Administration Services, you will see a link for adding Custom Services. Lot of my friends here forget to click on StartUp check box when adding a new service.
The important configuration values for Custom Services
- Startup - very important; unless this box is checked, the Custom Service will not be initialized during server startup.
- External Configuration URL - optional URL to a file that contains configuration data for this Custom Service. This data can be in any format you want, depending on the implementation of your Custom Service logic.
- Classname (required) - Provides the fully-qualified package name and class name for the class that implements the CustomService interface. The server will load this name during startup and invoke this name to initialize.
- Display Name (required) - Identifies the configuration of this service.
- Description - Any text that is useful to distinguish this Custom Service from others.
- Classpath (required) - The location of the JAR file containing the implementation code for this Custom Service.
There is even a better way to do it than Admin Console, I know how much you all love Jython, here is a snippet that adds the custom service into all WebSphere processes, including dmgr and nodeagent.
attrs = []
attrs.append(["externalConfigURL","/opt/apps/webdata/config/WAS/MyJMX.properties"])
attrs.append(["classname","MyJMXService"])
attrs.append(["displayName", "MyJMXAgent"])
attrs.append(["classpath", "/opt/apps/webdata/config/WAS/MyJMXAgent.jar"])
attrs.append(["enable","true"])
nodes = AdminConfig.list('Node').split(lineSeparator)
servers = AdminTask.listServers('-serverType APPLICATION_SERVER ')
servers = AdminUtilities.convertToList(servers)
for aServer in servers:
AdminConfig.create("CustomService", aServer, attrs)
AdminConfig.save( )
This JMX Mbean could be something which will complement your existing monitoring solution, in case if you don't have any sophisticated solution in place, it could simply be configured in all your WebSphere builds and used as a reliable alert solution.



