この例を使用して、分散プラットフォームおよび z/OS プラットフォームの両方 で WebSphere Application Server に対して処理を行うユーザー MBean の開発について説明します。 この例では特別なハンドラーをすべて使用し、その動的プロキシー MBean の果たす役割と機能を示します。 SampleStateMBean の例では、setter メソッドを起動すると、その状態が追跡され、 状態変更イベントが生成されます。
<?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>
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 = "WebSphere Application Server 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; } }
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 you 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() + "!"; } }