AMX Internal Developer's Guide

Last updated: 20 July 2005 18:01 PST
Author(s): lloyd.chambers@sun.com

0.  Checkin requirements

Checking in or changing the AMX APIs is an activity that must be approved prior to checkin by amx-dev@sun.com.

This means almost everything in com.sun.appserv.management and all its subpackages.   The AMX APIs are the publicly supported APIs for managing the appserver and require much more stringent review than interfaces used elsewhere. They should see very infrequent change, and must be consistent in multiple ways with the other interfaces already in AMX.

An AMX interface should generally not be checked in until it is fully-javadoc'd and in its final form.  Any AMX interface which is subject to change must be clearly javadoc'd  as such as follows. The following javadoc entry in the source code should be used:

<b>This interface has not been finalized and is subject to change.  Except by special arrangement, it is informational only and should not be used.</b>

It is possible to introduce new interfaces without providing any implementation.  In this case, the amx-dev code review and approval is the critical step that must be followed.  The unit tests must still be run as a sanity check prior to checkin.

Pre checkin checklist:

___ 1. Added new unit test(s) to amxtest.classes or modified existing ones appropriately.  Please note that unit tests apply to not only AMX MBeans, but code in com.sun.appserv.management.util.* (although many are not currently tested).

___ 2. Ran the unit tests with amxtest.classes.

___ 3. Verified that all tests pass excepting known issues.

___ 4. Code reviewed and approved by amx-dev@sun.com It is especially important that AMX interfaces (APIs) be reviewed prior to checkin. Please follow this rule strictly.



1.  Adding AMX MBeans

This is a brief summary of how to add an MBean to the AMX MBean API.


1.1.  Add a type for your new MBean in XTypes.java (or J2EETypes.java if it's a JSR 77 extension).   Be sure to follow the javadoc and naming conventions.  Example:

    /**
        ID for {@link com.sun.appserv.management.base.LogRecordEmitter}
     */
    public final static String    LOG_RECORD_EMITTER        =  P + "LogRecordEmitter";


1.2.  Define the interface for your MBean.  Your interface should extend com.sun.appserv.management.base.AMX, or one of its sub-interfaces.   The static variable J2EE_TYPE should be defines as the type you added in step (1).  All interface additions and/or changes to AMX must be approved prior to checkin by the AMX team.  Be sure to read the AMX Conventions.

public interface LogRecordEmitter
    extends AMX
{
    /** The j2eeType as returned by {@link com.sun.appserv.management.base.AMX#getJ2EEType}. */
    public static final String J2EE_TYPE    = XTypes.LOG_RECORD_EMITTER;

}

Notes:

1.3.  Add an entry for your interface in the MBEANINTERFACES Class[] in XTypesMapper (or J2EETypesMapper if it's a JSR 77 extension).  Example:

private static final Class[] MBEANINTERFACES    =
{
    ...
    LogRecordEmitter.class
    ...
};

1.4.  Define containment within the AMX hierarchy by adding an appropriate entry in the com.sun.enterprise.management.support.TypeInfos.TypeData array.  Examples:

new DomainRootChild( XTypes.MONITORING_ROOT ),
new MiscChild( XTypes.NOTIFICATION_SERVICE, XTypes.NOTIFICATION_SERVICE_MGR),


1.5.  Decide what ObjectName your MBean will have.

For config or monitoring MBeans, this is generally taken care of by the AMX infrastructure code. 

1.5.1 Config mbeans

If it's a new config type, you'll need to add something to com.sun.enterprise.management.support.OldConfigTypes.

1.5.2 Monitoring mbeans

If it's a new monitoring type, you'll probably need to add something to com.sun.enterprise.management.support.OldMonitorTypes.

1.5.3 Other mbeans

You will probably need to define the ObjectName yourself.  The minimum ObjectName should look like:
amx:j2eeType=type,name=name

By default only the above form is used.  This is sufficient if the MBean is a Singleton or Utility .

If the MBean is contained within another MBean, additional properties may be needed for the containment hierarchy.  However, in most cases, this is handled as part of the ObjectName implied by the containment hierarchy.

1.6.  Implementing your MBean.

The MBean should extend com.sun.enterprise.management.support.AMXImplBase or one of its subclasses.  Possible subclasses include:
In the course of implementing be particularly aware of methods with the following classes; in general if you think you need to do something with AMX, there's probably already a routine to do it:
If your MBean emits Notifications, there are things to be aware of:
If you issue Notifications of type javax.management.Notification, the following are sufficient for the AMX infrastructure to properly expose the MBeanNotificationInfo[] required by JMX:

private final String[]    NOTIF_TYPES    = new String[]
{
    ... all types emitted, see DeploymentMgrImpl for an example...
};
    protected Set
getNotificationTypes( Set existing )
{
    return SetUtil.newSet( existing, SetUtil.newSet( NOTIF_TYPES ) );
}



Avoid importing internal appserver classes.  This is very important for speeding development and reducing code coupling, compile time, compile-order dependencies, etc. Whenever possible, get the information you need by calling another MBean (preferably AMX).  Any MBean has available to it all the client-side facilities that any client does.   Your MBean inherites the methods getProxy(), getProxyFactory(), getNamedChildProxy().  You can get a proxy to any AMX MBean by calling getProxyFactory().getProxy( objectName ). Be aware, also, of getOldConfigProxies() if you need to access com.sun.appserv MBeans.

Actively fail unimplemented operations.  If you haven't implemented some operations, be sure to code them using  a call to
unimplementedOperation(), which is inherited from AMXImplBase:

public int myUnimplementedOperation() {
    unimplementedOperation( "
myUnimplementedOperation" );
}

Please also be aware of  unimplementedAttribute() and impossible().
rv MBeans.

Use the correct package name. 
MBean implementations should be placed in the appropriate subpackage of com.sun.enterprise.management, in the glassfish/admin/mbeanapi-impl module.  Never place implementation code in com.sun.appserv.management or its subpackages--except for certain client support code and utility code, com.sun.appserv.management is strictly public interfaces.



1.7. Ensuring your MBean gets loaded

There are various ways AMX MBeans get registered or unregistered.

Most AMX MBeans, such as the config or monitoring MBeans are driven entirely by the registration or unregistration of their corresponding com.sun.appserv MBeans.  This process is coordinated by com.sun.enterprise.management.support.Loader.

Only a very few AMX MBeans are loaded explicity--examples of this include DomainRoot and SystemInfo.  The containment hierarchy causes Singleton and Utility MBeans to load implicitly.  For example, the QueryMgr is loaded because it is a Utility MBean; when DomainRoot is loaded this causes the QueryMgr to also be loaded, because it is contained within DomainRoot.  See AMXImplBase.registerSelfMgrChildren() if this is of interest.  Defining containment in step 4 above is sufficient for these cases to cause the appropriate MBean to be loaded.

As AMX evolves, there may be more cases where explicit loading is done.  This appears to be the case, for example, with the WebServiceInfo MBeans.  Ask Lloyd Chambers or Kedar Mhaswade if you're unsure.

1.8 Testing your AMX MBean

Please see these two guides on running and creating unit tests:

admin/mbeanapi-impl/tests/com/sun/enterprise/management/unit-tests-README.html

admin/mbeanapi-impl/tests/com/sun/enterprise/management/AddingAMXUnitTests.html

1.9 Acronyms and special cases for Attribute names

Special handing is required for acronyms.  AMX has the convention that acronyms are always upper-case.  This makes automatic mapping a problem in some cases.  Also, there are a few cases where the AMX name does not match the underlying name in domain.xml.


For creation of any type of Config, the correct way to map the parameters is to add getParamNameOverrides() to the Factory.  See any of the AbcFactory classes in the package com.sun.enterprise.management.config.

        protected Map<String,String>
    getParamNameOverrides()
    {
        return( MapUtil.newMap( REFERENCED_CONFIG_NAME, "config-ref" ) );
    }


For the Attribute itself as fetched by getAttribute() in the registered and already-existing MBean, add the following method to the MBean implementation class (AbcImpl for the interface Abc).  See any of the AbcImpl classes in the package com.sun.enterprise.management.config.

 protected void
addCustomMappings( final AttributeNameMapper mapper ) {
 mapper.addMapping( "autodeploy-jsp-precompilation-enabled", "AutodeployJSPPrecompilationEnabled" );
 mapper.addMapping( "deploy-xml-validation", "DeployXMLValidation" );
}
   
It would be nice to reconcile these two, but that's the way it is for now.



2.  AMX Conventions

The conventions used in the AMX API are very, very important for several reasons:
This table summarizes the conventions used in AMX:
Convention
Discussion
Suffixes Config, Monitor, Mgr
  • Any interface whose name ends with the suffix Config is a configuration MBean
  • Any interface whose name ends with the suffix Monitor is a monitoring MBean
  • Any interface whose name ends with the suffix Mgr is an MBean that has some sort of managerial control over operations or other MBeans

  • Any MBean which is persistent configuration must have a class name that ends in "Config" and an XType (XTypes.java) that ends in "_CONFIG".
  • Any MBean which is monitoring must have a class name that ends in "Monitor" and an XType that ends in "_MONITOR".
  • The XType and class name should match ed "AbcMgr" and "ABC_MGR".
getAbcMap
getAbcObjectNameMap
This is a special idiom.  MBean implementations can only return ObjectName; they cannot return dynamic proxies that will work correctly.  So the client side dynamic proxy code looks for the special suffix "ObjectNameMap".  When found, it assumes that the Map values (not keys) are all ObjectName and instantiates dynamic proxies for each of them.  The actual Map the client receives is a new map keyed by the same keys, but with values that are dynamic proxy implementations of the appropriate AMX interface for the particular ObjectName.
acronyms
All acronyms must be upper-case.  This includes class names and method names.
utility routines
Do not add utility routines to MBeans. In almost all cases they are more suitably implemented in a class within the com.sun.appserv.management.helper package.  If in doubt, ask first.
data types
No proprietary data types are to be used in any AMX interface.

When a complex object is needed, the AMX convention is to use java.util.Map in most cases, or javax.management.openmbeans.CompositeData in certain cases.

The only legal data types that may be used are those found in:
  • com.sun.appserv.management.*
  • java.util.*
  • javax.management.*
No other data types may be used.
method names
Do not use method names that are so obtuse they require javadoc to explain.  Choose them very carefully; they are semi-permanent.
incompatible changes
By default, no incompatible changes are allowed.  Such changes may only occur at a major release, and require approval by the AMX team and notification to customers.
javadoc
All methods and constants must be javadoc'd.
values of constants
Values of constants in AMX are always camel case eg:
public static final String WEIGHTED_ROUND_ROBIN = "WeightedRoundRobin".

This table summarizes data type conventions used in AMX:
Convention
Discussion
method signatures and primitive types Primitive types must always be used eg char, int, long, not Character, Integer, Long.    The only time the Object form is acceptable is to indicate that the parameter is optional and therefore may be null.
return types
Return types should be restricted to java.lang types whenever possible.  When more complex data is to be returned, a strongly-typed java.util.Map may be used eg Map<String,Integer>.  In certain cases the JMX javax.management.openmbeans.CompositeData may be used.
no proprietary types
No proprietary types should be used for method signatures or return types.  A client lacking the AMX client interfaces should be able to fully access all operations and Attributes with no fear of getting ClassNotFoundException, or worrying about serialization versions.