The following example uses of AMX are discussed in this document:
The connection to the DAS is shown in the following code.
[...] public static AppserverConnectionSource connect( final String host, final int port, final String user, final String password, final TLSParams tlsParams ) throws IOException { final String info = "host=" + host + ", port=" + port + ", user=" + user + ", password=" + password + ", tls=" + (tlsParams != null); SampleUtil.println( "Connecting...:" + info ); final AppserverConnectionSource conn = new AppserverConnectionSource( AppserverConnectionSource.PROTOCOL_RMI, host, port, user, password, tlsParams, null); conn.getJMXConnector( false ); SampleUtil.println( "Connected: " + info ); return( conn ); } [...]
A connection to the DAS is obtained via an instance of the com.sun.appserv.management.client.AppserverConnectionSource class. For the connection to be established, you must know the name of the host and port number on which the DAS is running, and have the correct user name, password and TLS parameters.
Once the connection to the DAS is established, DomainRoot is obtained as follows:
DomainRoot domainRoot = appserverConnectionSource.getDomainRoot();
This DomainRoot instance is a client-side dynamic proxy to the MBean amx:j2eeType=X-DomainRoot,name=amx.
See the API documentation for com.sun.appserv.management.client.AppserverConnectionSource for further details about connecting to the DAS using the AppserverConnectionSource class.
However, if you prefer to work with standard JMX, instead of getting DomainRoot, you can get the MBeanServerConnection or JMXConnector, as shown:
MBeanServerConnection conn = appserverConnectionSource.getMBeanServerConnection( false ); JMXConnector jmxConn = appserverConnectionSource.getJMXConnector( false );
The startServer() method demonstrates how to start an Application Server.
[...] startServer( final String serverName ) { final J2EEServer server = getJ2EEServer( serverName ); server.start(); } [...]
This method retrieves and starts an application server instance named server. The server is an instance of the com.sun.appserv.management.j2see.J2EEServer interface, and is obtained by calling another method, getJ2EEServer(), shown in the following code.
[...] getJ2EEServer( final String serverName ) { final J2EEDomain j2eeDomain = getDomainRoot().getJ2EEDomain(); final Map servers = j2eeDomain.getServerMap(); final J2EEServer server = (J2EEServer)servers.get( serverName ); if ( server == null ) { throw new IllegalArgumentException( serverName ); } return( server ); } [...]
To obtain a J2EE server instance, the getJ2EEServer() method first of all obtains an instance of the J2EEDomain interface by calling the com.sun.appserv.management.base.AMX.getDomainRoot() and com.sun.appserv.management.DomainRoot.getJ2EEDomain() methods. The two methods called establish the following:
AMX.getDomainRoot() obtains the Application Server domain to which j2eeDomain belongs.
DomainRoot.getJ2EEDomain() obtains the J2EE domain for j2eeDomain.
The J2EEServer instance is then started by a call to the start() method. The com.sun.appserv.management.j2ee.StateManageable.start() method can be used to start any state manageable object.
The uploadArchive() and deploy() methods demonstrate how to upload and deploy a J2EE archive file.
[...] uploadArchive ( final File archive ) throws IOException { final FileInputStream input = new FileInputStream( archive ); final long length = input.available(); final DeploymentMgr mgr = getDomainRoot().getDeploymentMgr(); final Object uploadID = mgr.initiateFileUpload( length ); try { [...] } finally { input.close(); } return( uploadID ); } [...]
The uploadArchive() method creates a standard Java FileInputStream instance called input, to upload the archive archive. It then obtains the AMX deployment manager running in the application server domain, by calling the DomainRoot.getDeploymentMgr() method.
A call to com.sun.appserv.management.deploy.initiateFileUpload starts the upload of archive. The initiateFileUpload() method automatically issues an upload ID, that uploadArchive() returns when it is called by deploy().
[...] deploy ( final File archive ) throws IOException { final Object uploadID = uploadArchive(archive); final DeploymentMgr mgr = getDomainRoot().getDeploymentMgr(); final Object deployID = mgr.initDeploy( ); final DeployNotificationListener myListener = new DeployNotificationListener( deployID); mgr.addNotificationListener( myListener, null, null); try { final Map options = new HashMap(); options.put( DeploymentMgr.DEPLOY_OPTION_VERIFY_KEY, Boolean.TRUE.toString() ); options.put( DeploymentMgr.DEPLOY_OPTION_DESCRIPTION_KEY, "description" ); mgr.startDeploy( deployID, uploadID, null, null); while ( ! myListener.isCompleted() ) { try { println( "deploy: waiting for deploy of " + archive); Thread.sleep( 1000 ); } catch( InterruptedException e ) { } } final DeploymentStatus status = myListener.getDeploymentStatus(); println( "Deployment result: " + getStageStatusString( status.getStageStatus() ) ); if ( status.getStageThrowable() != null ) { status.getStageThrowable().printStackTrace(); } } finally { try { mgr.removeNotificationListener( myListener ); } catch( Exception e ) { } } } [...]
The deploy() method calls uploadArchive to get the upload ID for archive. It then identifies the deployment manager by calling DomainRoot.getDeploymentMgr(). A call to DeploymentMgr.initDeploy() initializes the deployment and obtains a deployment ID, which is used to track the progress of the deployment.
A JMX notification listener, myListener, is created and activated to listen for notifications regarding the deployment of deployID.
Deployment is started by calling the DeploymentMgr.startDeploy() method and providing it with the deployID and uploadID.
While the deployment is continuing, myListener listens for the completion notification and DeploymentStatus keeps you informed of the status of the deployment by regularly calling its getStageStatus() method. Once the deployment is complete, the listener is closed down.
Some of the behavior of the com.sun.appserv.management.deploy API is unpredictable, and it should be used with caution.
The displayAMX() method demonstrates how to display the AMX MBean hierarchy.
[...] displayAMX( final AMX amx, final int indentCount ) { final String indent = getIndent( indentCount ); final String j2eeType = amx.getJ2EEType(); final String name = amx.getName(); if ( name.equals( AMX.NO_NAME ) ) { println( indent + j2eeType ); } else { println( indent + j2eeType + "=" + name ); } } private void displayHierarchy( final Collection amxSet, final int indentCount ) { final Iterator iter = amxSet.iterator(); while ( iter.hasNext() ) { final AMX amx = (AMX)iter.next(); displayHierarchy( amx, indentCount ); } } public void displayHierarchy( final AMX amx, final int indentCount ) { displayAMX( amx, indentCount ); if ( amx instanceof Container ) { final Map m = ((Container)amx).getMultiContaineeMap( null ); final Set deferred = new HashSet(); final Iterator mapsIter = m.values().iterator(); while ( mapsIter.hasNext() ) { final Map instancesMap = (Map)mapsIter.next(); final AMX first = (AMX)instancesMap.values().iterator().next(); if ( first instanceof Container ) { deferred.add( instancesMap ); } else { displayHierarchy( instancesMap.values(), indentCount + 2); } } // display deferred items final Iterator iter = deferred.iterator(); while ( iter.hasNext() ) { final Map instancesMap = (Map)iter.next(); displayHierarchy( instancesMap.values(), indentCount + 2); } } } public void displayHierarchy() { displayHierarchy( getDomainRoot(), 0); } public void displayHierarchy( final String j2eeType ) { final Set items = getQueryMgr().queryJ2EETypeSet( j2eeType ); if ( items.size() == 0 ) { println( "No {@link AMX} of j2eeType " + SampleUtil.quote( j2eeType ) + " found" ); } else { displayHierarchy( items, 0); } } [...]
The displayAMX() method obtains the J2EE type and the name of an AMX MBean by calling AMX.getJ2EEType and AMX.getName respectively.
The displayHierarchy() method defines a standard Java Collection instance, amxSet, which collects instances of AMX MBeans.
To display the hierarchy of MBeans within a particular MBean in the collection, displayHierarchy() checks whether the MBean is an instance of Container. If so, it creates a set of the MBeans it contains by calling the com.sun.appserv.management.base.Container.getMultiContaineeMap() method.
The MBean hierarchy for a particular J2EE type is displayed by calling the com.sun.appserv.management.base.QueryMgr.queryJ2EETypeSet(), and passing the result to displayHierarchy().
To display the entire AMX MBean hierarchy in a domain, displayHierarchy() calls getDomainRoot() to obtain the root AMX MBean in the domain.
The setMonitoring() method demonstrates how to set monitoring states.
[...] private static final Set LEGAL_MON = Collections.unmodifiableSet( SampleUtil.newSet( new String[] { ModuleMonitoringLevelValues.HIGH, ModuleMonitoringLevelValues.LOW, ModuleMonitoringLevelValues.OFF, } )); public void setMonitoring( final String configName, final String state ) { if ( ! LEGAL_MON.contains( state ) ) { throw new IllegalArgumentException( state ); } final ConfigConfig config = (ConfigConfig)getDomainConfig(). getConfigConfigMap().get( configName ); final ModuleMonitoringLevelsConfig mon = config.getMonitoringServiceConfig(). getModuleMonitoringLevelsConfig(); mon.setConnectorConnectionPool( state ); mon.setThreadPool( state ); mon.setHTTPService( state ); mon.setJDBCConnectionPool( state ); mon.setORB( state ); mon.setTransactionService( state ); mon.setWebContainer( state ); mon.setEJBContainer( state ); } [...]
The AMX API defines three levels of monitoring in com.sun.appserv.management.config.ModuleMonitoringLevelValues, namely, HIGH, LOW, and OFF.
In this example, the configuration element being monitored is named configName. The com.sun.appserv.management.config.ConfigConfig interface is used to configure the config element for configName in the domain.xml file.
An instance of com.sun.appserv.management.config.ModuleMonitoringLevelsConfig is created to configure the module-monitoring-levels element for configName in the domain.xml file.
The ModuleMonitoringLevelsConfig instance created then calls each of its set methods to change their states to state.
The above is performed by running the set-monitoring command when you run SimpleMain, stating the name of the configuration element to be monitored and the monitoring state to one of HIGH, LOW or OFF.
The handleList() method demonstrates how to access many (but not all) configuration elements.
[...] handleList() { final DomainConfig dcp = getDomainConfig(); println( "\n--- Top-level --- \n" ); displayMap( "ConfigConfig", dcp.getConfigConfigMap() ); displayMap( "ServerConfig", dcp.getServerConfigMap() ); displayMap( "StandaloneServerConfig", dcp.getStandaloneServerConfigMap() ); displayMap( "ClusteredServerConfig", dcp.getClusteredServerConfigMap() ); displayMap( "ClusterConfig", dcp.getClusterConfigMap() ); println( "\n--- DeployedItems --- \n" ); displayMap( "J2EEApplicationConfig", dcp.getJ2EEApplicationConfigMap() ); displayMap( "EJBModuleConfig", dcp.getEJBModuleConfigMap() ); displayMap( "WebModuleConfig", dcp.getWebModuleConfigMap() ); displayMap( "RARModuleConfig", dcp.getRARModuleConfigMap() ); displayMap( "AppClientModuleConfig", dcp.getAppClientModuleConfigMap() ); displayMap( "LifecycleModuleConfig", dcp.getLifecycleModuleConfigMap() ); println( "\n--- Resources --- \n" ); displayMap( "CustomResourceConfig", dcp.getCustomResourceConfigMap() ); displayMap( "PersistenceManagerFactoryResourceConfig", dcp.getPersistenceManagerFactoryResourceConfigMap() ); displayMap( "JNDIResourceConfig", dcp.getJNDIResourceConfigMap() ); displayMap( "JMSResourceConfig", dcp.getJMSResourceConfigMap() ); displayMap( "JDBCResourceConfig", dcp.getJDBCResourceConfigMap() ); displayMap( "ConnectorResourceConfig", dcp.getConnectorResourceConfigMap() ); displayMap( "JDBCConnectionPoolConfig", dcp.getJDBCConnectionPoolConfigMap() ); displayMap( "PersistenceManagerFactoryResourceConfig", dcp.getPersistenceManagerFactoryResourceConfigMap() ); displayMap( "ConnectorConnectionPoolConfig", dcp.getConnectorConnectionPoolConfigMap() ); displayMap( "AdminObjectResourceConfig", dcp.getAdminObjectResourceConfigMap() ); displayMap( "ResourceAdapterConfig", dcp.getResourceAdapterConfigMap() ); displayMap( "MailResourceConfig", dcp.getMailResourceConfigMap() ); final ConfigConfig config = (ConfigConfig)dcp.getConfigConfigMap().get( "server-config" ); println( "\n--- HTTPService --- \n" ); final HTTPServiceConfig httpService = config.getHTTPServiceConfig(); displayMap( "HTTPListeners", httpService.getHTTPListenerConfigMap() ); displayMap( "VirtualServers", httpService.getVirtualServerConfigMap() ); } [...]
The handleList() method makes use of the displayMap() method, which simply prints out the key value pairs.
The handleList() method identifies the configuration for a domain by calling the DomainRoot.getDomainConfig() method. This DomainConfig instance then calls each of its getXXXMap() methods in turn, to obtain a Map for each type of AMX MBean. The Map returned by each getter is displayed by displayMap().
Similarly, the AMX MBeans representing the http-service element are displayed as Maps by calling the getXXXMap() methods of the com.sun.appserv.management.config.HTTPServiceConfig interface, and passing them to displayMap().
The displayAllAttributes() method demonstrates how to access and display the attributes of an AMX MBean.
[...] displayAllAttributes( final AMX item ) { println( "\n--- Attributes for " + item.getJ2EEType() + "=" + item.getName() + " ---" ); final Extra extra = Util.getExtra( item ); final Map attrs = extra.getAllAttributes(); final Iterator iter = attrs.keySet().iterator(); while ( iter.hasNext() ) { final String name = (String)iter.next(); final Object value = attrs.get( name ); println( name + "=" + toString( value ) ); } } public void displayAllAttributes( final String j2eeType ) { final Set items = queryForJ2EEType( j2eeType ); if ( items.size() == 0 ) { println( "No {@link AMX} of j2eeType " + SampleUtil.quote( j2eeType ) + " found" ); } else { final Iterator iter= items.iterator(); while ( iter.hasNext() ) { final AMX amx = (AMX)iter.next(); displayAllAttributes( amx ); println( "" ); } } } [...]
The displayAllAttributes() method calls the AMX.getName() and AMX.getJ2EEType() methods for an AMX MBean and prints the results onscreen. It then gets all the attributes for that MBean by calling com.sun.appserv.management.base.Extra.getAllAttributes() on the Extra instance returned by com.sun.appserv.management.base.Util.getExtra(). This is repeated for every MBean.
The attributes of AMX MBeans of a certain J2EE type can be displayed by specifying the J2EE type when the command is run. In this case, displayAllAttributes() calls queryForJ2EEType(). The queryForJ2EEType() method calls the com.sun.appserv.management.base.QueryManager.queryPropSet() method on the specified J2EE type to identify all elements of that type in the domain.
The displayAllProperties() demonstrates how to list AMX MBean properties.
[...] getProperties( final PropertiesAccess pa ) { final HashMap m = new HashMap(); final String[] names = pa.getPropertyNames(); for( int i = 0; i < names.length; ++i ) { m.put( names[ i ], pa.getPropertyValue( names[ i ] ) ); } return( m ); } public void displayAllProperties( ) { final Iterator iter = getQueryMgr().queryAllSet().iterator(); while ( iter.hasNext() ) { final AMX amx = (AMX)iter.next(); if ( amx instanceof PropertiesAccess ) { final PropertiesAccess pa = (PropertiesAccess)amx; final Map props = getProperties( pa ); if ( props.keySet().size() != 0 ) { println( "\nProperties for: " + Util.getObjectName( AMX)pa ) ); println( SampleUtil.mapToString(getProperties(pa), "\n") ); } } } } [...]
The displayAllProperties() method uses another Samples method, getProperties(). This method creates an instance of the com.sun.appserv.management.config.PropertiesAccess interface, and calls its getPropertyNames() method to obtain the names of all the properties for a given AMX MBean. For each property name obtained, its corresponding value is obtained by calling PropertiesAccess.getPropertyValue().
The displayAllProperties() method calls the com.sun.appserv.management.base.QueryMgr.queryAllSet() method to obtain a set of all the AMX MBeans present in the domain. All AMX MBeans that have properties obligatorily extend the PropertiesAccess interface. Any MBean found to extend PropertiesAccess is passed to the getProperties() method, and the list of property values returned is printed onscreen.
The demoQuery() method demonstrates how to issue queries.
The demoQuery() method uses other methods that are defined by Samples, namely displayWild(), and displayJ2EEType(). The displayWild() method is shown in the following code.
[...] queryWild( final String propertyName, final String propertyValue) { final String[] propNames = new String[] { propertyName }; final String[] propValues = new String[]{ propertyValue }; final Set amxs = getQueryMgr().queryWildSet( propNames, propValues ); return( amxs ); } public Set displayWild( final String propertyName, final String propertyValue) { final Set items = queryWild( propertyName, propertyValue ); println( "\n--- Queried for " + propertyName + "=" + propertyValue + " ---" ); final Iterator iter = items.iterator(); while ( iter.hasNext() ) { final AMX item = (AMX)iter.next(); println( "j2eeType=" + item.getJ2EEType() + ", " + "name=" + item.getName() ); } } [...]
The displayWild() method calls queryWild(), to obtain all the AMX MBeans that have object names matching propertyName and propertyValue. To do so, queryWild() calls the com.sun.appserv.management.base.QueryMgr.queryWildSet() method. The queryWildSet() method returns the list of AMX MBeans with object names matching the wild card strings.
For each MBean returned, the displayWild() calls AMX.getJ2EEType() to identify its J2EE type, and prints the result onscreen.
In code that is not shown here, the displayJ2EEType() method calls the queryForJ2EEType() method, which was seen in Accessing and Displaying the Attributes of an AMX MBean, to identify MBeans of a certain J2EE type and print their object names onscreen.
[...] demoQuery() { displayWild( AMX.J2EE_TYPE_KEY, "X-*ResourceConfig" ); displayWild( AMX.J2EE_TYPE_KEY, "X-*ServerConfig" ); displayJ2EEType( XTypes.SSL_CONFIG ); displayJ2EEType( XTypes.CLUSTER_CONFIG ); } [...]
In the demoQuery() method, the displayWild() and displayJ2EEType() methods are called to find the following MBeans:
J2EE_TYPE_KEY MBeans called ResourceConfig
J2EE_TYPE_KEY MBeans called ServerConfig
All SSL_CONFIG MBeans
All CLUSTER_CONFIG MBeans
The demoJMXMonitor() demonstrates how to monitor attribute changes.
[...] demoJMXMonitor() throws InstanceNotFoundException, IOException { final JMXMonitorMgr mgr = getDomainRoot().getJMXMonitorMgr(); final String attrName = "SampleString"; final String attrValue = "hello"; final SampleListener sampleListener = new SampleListener(); final MBeanServerConnection conn = Util.getExtra( mgr ).getConnectionSource() .getExistingMBeanServerConnection(); conn.addNotificationListener( getMBeanServerDelegateObjectName(), sampleListener, null, null ); final Sample sample = (Sample)getDomainRoot() .getContainee( XTypes.SAMPLE ); final String monitorName = "SampleStringMonitor"; AMXStringMonitor mon = null; try { try { mgr.remove( monitorName ); } catch( Exception e ) {} mon = mgr.createStringMonitor( monitorName ); waitMBeanServerNotification( sampleListener, MBeanServerNotification.REGISTRATION_NOTIFICATION, Util.getObjectName( mon ) ); sample.addAttribute( attrName, attrValue ); mon.addNotificationListener( sampleListener, null, null); mon.setObservedAttribute( attrName ); mon.setStringToCompare( attrValue ); mon.setNotifyDiffer( true ); mon.setNotifyMatch( true ); mon.addObservedObject( Util.getObjectName( sample ) ); final StdAttributesAccess attrs = Util.getExtra( sample); attrs.setAttribute( new Attribute(attrName, "goodbye") ); attrs.setAttribute( new Attribute(attrName, attrValue) ); sample.removeAttribute( attrName ); final Map notifs = sampleListener.getNotifsReceived(); waitNumNotifs( notifs, AttributeChangeNotification.ATTRIBUTE_CHANGE, 4 ); } catch( Throwable t ) { t.printStackTrace(); } finally { try { mon.removeNotificationListener( sampleListener ); if ( mon != null ) { mgr.remove( mon.getName() ); waitMBeanServerNotification( sampleListener, MBeanServerNotification .UNREGISTRATION_NOTIFICATION, Util.getObjectName( mon ) ); } conn.removeNotificationListener( getMBeanServerDelegateObjectName(), sampleListener ); } catch( ListenerNotFoundException e ) { } } } [...]
The demoJmx() method demonstrates the implementation of a JMX monitor MBean, that listens for changes in a certain attribute. This is achieved in the following stages:
A com.sun.appserv.management.monitor.JMXMonitorMgr instance is obtained using the DomainRoot.getJMXMonitorMgr() method.
A SampleListener JMX notification listener that is provided in the sample package is instantiated.
A connection to the domain’s MBean server is obtained by calling com.sun.appserv.management.client.ConnectionSource. getExistingMBeanServerConnection() on the JMXMonitorMgr instance’s Extra information.
The SampleListener notification listener is added to the MBean server connection, with an MBean server delegate obtained from getMBeanServerDelegateObject(). The notification listener is now in place on the MBean server connection.
An AMX MBean, sample, of the type SAMPLE is obtained by calling the com.sun.appserv.management.base.Container.getContainee() method on an instance of the Sample interface. The Sample interface defines a basic AMX MBean.
An AMXStringMonitor, an AMX-compatible JMX StringMonitorMBean, is instantiated by calling createStringMonitor on the JMXMonitorMgr instance created above. The AMXStringMonitor instance then calls waitMBeanServerNotification(). The waitMBeanServerNotification() method waits for MBean server notifications of the type REGISTRATION_NOTIFICATION from the SampleListener instance that is listening on the MBean server connection.
An attribute of name attrName and value attrValue is added to the AMX MBean sample.
Various methods of the AMXStringMonitor instance are called, to add a listener, and to set the value to be observed, the object to be observed, and so on.
Access to the sample MBean’s attributes is obtained by passing the sample MBean’s Extra information to an instance of com.sun.appserv.management.base.StdAttributesAccess. The StdAttributesAccess.setAttribute() method is then called to change the values of these attributes.
The AMXStringMonitor then calls the sample notification listener’s getNotifsReceived() method to retrieve the notifications that resulted from the calls to setAttribute() above. The waitNumNotifs() method waits until four ATTRIBUTE_CHANGE notifications have been received before exiting.
The notification listener is then removed and the monitor is closed down.
The undeploy() method demonstrates how to undeploy a module.
[...] undeploy ( final String moduleName ) throws IOException { final DeploymentMgr mgr = getDomainRoot().getDeploymentMgr(); final Map statusData = mgr.undeploy( moduleName, null ); final DeploymentStatus status = DeploymentSupport.mapToDeploymentStatus( statusData ); println( "Undeployment result: " + getStageStatusString(status.getStageStatus())); if ( status.getStageThrowable() != null ) { status.getStageThrowable().printStackTrace(); } } [...]
The undeploy() method obtains the DeploymentMgr instance for the domain in the same way that deploy() does so. It then calls the DeploymentMgr.undeploy() method for a named module.
The stopServer() method demonstrates how to stop an application server. The stopServer() method simply calls the getJ2EEServer() method on a given server instance, and then calls J2EEServer.stop().