(ZOS) Example: The SampleStateMBean MBean
Use this example to guide you in developing user MBeans that work for the WebSphere Application Server on both the distributed platforms and the z/OS platform. The example uses all the special handlers to show its dynamic proxy Bean responsibilities and capabilities. The SampleStateMBean example keeps track of its state and generates state change events when it invokes setter methods.
MBeanDescriptor
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE MBean SYSTEM "MbeanDescriptor.dtd"> <MBean type="SampleStateMBean" aggregationHandlerClass="com.ibm.ws390.sample.SampleStateAggregationHandler" eventHandlerClass="com.ibm.ws390.sample.SampleStateEventHandler" invocationHandlerClass="com.ibm.ws390.sample.SampleStateInvocationHandler" stateObjectClass="com.ibm.ws390.sample.SampleState" version="6.0" platform="dynamicproxy" description="Sample State MBean for the documentation example."> <attribute description="The name of the MBean." getMethod="getMBeanName" name="mbeanName" type="java.lang.String" proxyInvokeType="unicall"/> <attribute description="The state of the MBean." name="state" getMethod="getState" setMethod="setState" type="java.lang.String" proxyInvokeType="multicall" proxySetterInvokeType="multicall"/> <operation description="Initialize the State MBean." impact="ACTION" name="initializeState" role="operation" targetObjectType="objectReference" type="void" proxyInvokeType="multicall"> <signature> <parameter description="The name of the MBean." name="mbeanName" type="java.lang.String"/> <parameter description="The initial state of the MBean." name="mbeanName" type="java.lang.String"/> </signature> </operation> <notification name="j2ee.state.starting" severity="6" log="false" description="This sample state MBean is in starting state."> <notificationType>j2ee.state.starting</notificationType> </notification> <notification name="j2ee.state.running" severity="6" log="false" description="This sample state MBean is in running state."> <notificationType>j2ee.state.running</notificationType> </notification> <notification name="j2ee.state.stopping" severity="6" log="false" description="This sample state MBean is in stopping state."> <notificationType>j2ee.state.stopping</notificationType> </notification> <notification name="j2ee.state.stopped" severity="6" log="false" description="This sample state MBean is in stopped state."> <notificationType>j2ee.state.stopped</notificationType> </notification> </MBean>SampleState implementation
package com.ibm.ws390.sample; import com.ibm.ejs.ras.Tr; import com.ibm.ejs.ras.TraceComponent; import java.io.Serializable; import com.ibm.websphere.management.dynamicproxy.StateObject; public class SampleState extends StateObject { private static TraceComponent tc = Tr.register(SampleState.class,"SampleState",null); // Package protected STATE constants. static final String STATE_STARTING = "j2ee.state.starting"; static final String STATE_RUNNING = "j2ee.state.running"; static final String STATE_STOPPING = "j2ee.state.stopping"; static final String STATE_STOPPED = "j2ee.state.stopped"; // Dynamicproxy State is initialized with STOPPED state. private String state = STATE_STOPPED; public SampleState() { if (tc.isEntryEnabled()) Tr.entry(tc,"<init>"); // State is initialized during "state" initialization above, // but can also be initialized here in the constructor as well. /* state = "WAS for z/OS ready for e-business"; */ if (tc.isEntryEnabled()) Tr.exit(tc,"<init>"); } public synchronized String getState() { if (tc.isEntryEnabled()) Tr.entry(tc,"getState"); if (tc.isEntryEnabled()) Tr.exit(tc,"getState",state); return state; } public synchronized void setState(String state) { if (tc.isEntryEnabled()) Tr.entry(tc,"setState",state); this.state = state; if (tc.isEntryEnabled()) Tr.exit(tc,"setState"); } public synchronized String getStateObjectInfo() { return state; } }SampleStateAggregationHandler implementation
package com.ibm.ws390.sample; import com.ibm.websphere.management.dynamicproxy.AggregationHandler; import com.ibm.websphere.management.dynamicproxy.StateObject; import com.ibm.ejs.ras.Tr; import com.ibm.ejs.ras.TraceComponent; public class SampleStateAggregationHandler implements AggregationHandler { private static TraceComponent tc = Tr.register(SampleStateAggregationHandler.class,"SampleState",null); /** * Return an aggregated result from a multicall Mbean operation which * compiles through all servant MBeans' results and returns a respective * single return value for an invoked method. * * @param methodName MBean method name * @param params MBean method parameters * @param signatures MBean method signatures * @param servantMBeanResults Result of each servant MBean instances * invoked by the dynamicproxy multicast * invocation. * Note: this value can be "null" OR can be * an array of "null"s in case return value * of the method is "void." Implementation * of this method MUST handle this case to * avoid a <code>NullPointerException</code>. * @param stateObject * MBean provider provided <code>StateObject</code> used by * dynamicproxy MBean in CR to manage its state. Note: this object * MAY BE null if "stateObjectClass" was not specified OR internal * error occurred during initialization of this dynamicproxy MBean. * Implmentation MUST properly handle "null" input. * * @return aggregated result as defined by MBean xml for specified * MBean operation. */ public Object aggregateResults(String methodName, Object[] params, String[] signatures, Object[] servantMBeanResults, StateObject stateObject) { if (tc.isEntryEnabled()) Tr.entry(tc,"aggregateResults",methodName); // As we can see from the MBeanDescriptor of SampleStateMBean, // it declares the following four methods: // 1. String getMBeanName() [proxyInvokeType == unicall] // 2. String getState() [proxyInvokeType == multicall] // 3. void setState(String) [proxyInvokeType == multicall] // 4. void initializeState() [proxyInvokeType == multicall] // // Looking at the above methods, only method that requires aggregation // is #2 getState method which is a multicall MBean operation AND // it returns a value that can be aggregated. // // In this example, we simply take each servants' getState MBean // request result and concatenate them into one long String that // Displays each servants' state. if (methodName.equals("getState")) { StringBuffer stateBuf = new StringBuffer(); for (int i=0; i<servantMBeanResults.length; i++) { stateBuf.append("SERVANT #" + i + " state ==|" + servantMBeanResults[i] + "|== "); } return stateBuf.toString(); } // If we also had an example method which returns say an int, // GetNumberOfMBeans(), it can take the similar approach // and to add each servants' getNumberOfMBeans() result together here. /* example added for non-existent method: int getNumberOfMBeans() else if (methodName.equals("getNumberOfMBeans")) { int aggregatedResult = 0; for (int i=0; i<servantMBeanResults.length; i++) { aggregatedResult += (int) servantMBeanResults[i]; } return aggregatedResult; } */ return methodName + " is NOT handled by " + getClass().getName() + "!"; } }
Java Management Extensions MBean multiprocess model request flow for WAS for z/OS