List of changes to JMX specification for version 1.2 eamonn.mcmanus@sun.com This document summarizes the status of the changes to the JMX specification that were considered for the 1.2 Maintenance Review. There are three lists of changes: * "accepted" changes are those that were retained as a result of the review. JMX 1.2 includes all of these changes. * "rejected" changes are those that were not retained as a result of the review. JMX 1.2 does not include these changes, and it is not expected that any future JMX 1.x version will. (Some changes might be considered if ever a major release, JMX 2.x, is undertaken.) * "deferred" changes are those were not retained as a result of the review, whether for time reasons or because it was considered that the changes were too significant. JMX 1.2 does not include these changes, but a future JMX 1.x version may. This document is closely based on the original proposed list of changes. The numbering applied here is based on the numbering of the original list. This explains why the numbers in each section are not contiguous. The detailed description of changes in this document is principally of interest to people implementing the JMX specification. JMX users are referred to the "what has changed" section of the JMX Specification. SUMMARY OF ACCEPTED CHANGES =========================== A.1. New superinterface of MBeanServer. A.2. New four-parameter removeNotificationListener methods. A.3. Support for concurrent queries. A.4. Changes to ObjectName. A.4.1. Quoting mechanism for values associated with keys. A.4.2. Newline character forbidden in ObjectName. A.4.3. Factory methods for creating ObjectNames. A.4.4. Clarify semantics of ObjectName.equals in the presence of patterns. A.4.5. Specify a convention for unique ObjectNames. A.4.6. ObjectName implements QueryExp. A.4.7. New method ObjectName.isDomainPattern(). A.4.9. Clarify what characters may appear where. A.5. Changes and clarifications to class loading and class naming. A.5.1. Clarified meaning of MBeanInfo.getClassName(). A.5.2. Clarified meaning of MBeanServer.isInstanceOf(). A.5.3. MBean class name in RoleInfo tested using MBeanServer.isInstanceOf. A.5.4. Clarify semantics of the Class Loader Repository (CLR). A.5.4.1. MLets only delegate to earlier loaders in the CLR. A.5.4.2. The MBean server's ClassLoader is in the CLR. A.5.4.3. Defined order of ClassLoaders in the CLR. A.5.5. One ClassLoaderRepository per MBean server. A.5.5.1. DefaultLoaderRepository specified using CLR. A.5.6. New MBeanServer method to get the right ClassLoader for parameters. A.6. New permissions. A.6.1. javax.management.MBeanPermission. A.6.2. javax.management.MBeanTrustPermission. A.7. User-supplied factory for MBeanServer instances. A.8. MBeanInfo and related classes. A.8.2. MBean*Info implement equals(Object). A.8.3. MBeanConstructorInfo does not have to be exhaustive. A.8.4. MBean*Info constructors check for valid Java identifiers. A.9. Changes related to javax.management.Notification. A.9.1. Clarifications concerning Notification.source. A.9.2. Control over notification dispatch in NotificationBroadcasterSupport. A.10. Changes to Timer Service. A.10.1. Changed behaviour when scheduled time is already past. A.10.3. Public constructor for TimerNotification. A.10.4. Periodic notification can be fixed-delay or fixed-rate. A.11. Changes to Monitor Service. A.11.2. Monitoring the same attribute in several MBeans. A.12. Changes to Relation Service. A.12.1. Changed semantics of RoleInfo class. A.12.2. Role.roleValueToString separated by newlines. A.13. Changes to Open MBeans. A.13.1. Open MBeans become mandatory. A.13.2. OpenMBeanInfo will never extend MBeanInfo. A.13.3. Constants in SimpleType should be final. A.13.4. Add java.util.Date to SimpleType possibilities. A.14. Changes to MLets. A.14.1. MLet implements Externalizable. A.14.2. MLet.check method should be protected rather than private. A.15. Serial compatibility with JMX 1.0 is not required. A.16. Clarification of ObjectName in MBeanRegister.preRegister. A.17. Implementations must forbid calling getters and setters via invoke. A.18. Retrieving all domains in the MBean server. A.19. Standard MBeans. A.19.1. Specify exact rules for deriving NameMBean from Name. A.19.2. Hybrid of Standard and Dynamic MBeans. A.20. InvocationHandler for MBean proxies. A.21. Wrapped exceptions accessible with getCause(). A.22. Changes to Model MBeans. A.22.2. Descriptor extends Cloneable. A.22.3. RequiredModelMBean implements MBeanRegistration. A.22.4. RequiredModelMBeanInfo.invoke invokes locally or on resource. A.22.5. ModelMBeanInfo.getNotifications() includes standard notifications. A.22.6. Descriptor's persistPolicy includes "always". A.22.7. Remove "iterable" Descriptor field. A.22.8. Descriptor field names are case insensitive. A.22.9. Descriptor "export" field can contain external name. A.22.10. Require XML support in DescriptorSupport. A.22.11. Type of Descriptor's "protocolMap" field is Descriptor. A.22.12. "class" field of constructor Descriptor removed. A.22.14. ModelMBeanOperationInfo Descriptor cannot be "constructor". A.22.15. Default value for attribute specified as "default". A.22.16. Specification should not refer to missing findPersistent method. A.22.17. ModelMBean.load called from preRegister not constructor. ACCEPTED CHANGES ================ A.1. New superinterface of MBeanServer. The MBeanServer interface is not suitable for exposure to remote clients, first because it contains methods only appropriate for the exporter of instrumentation, and second because it does not declare an appropriate exception for communication failures. JMX 1.2 introduces a parent interface javax.management.MBeanServerConnection where all methods declare IOException in their "throws" clause and where the following methods from MBeanServer are not present: * deserialize (all overloaded forms) This method returns an ObjectInputStream, which is not a serializable class. It is in any case only of use for the server end of a connector, and even then it is superseded by the new getClassLoader* methods. * getClassLoader * getClassLoaderFor * getClassLoaderRepository These new methods are useful for the server end of a connector. ClassLoaders and ClassLoaderRepository are not serializable and in any case it is not appropriate for a remote client to be able to access this information. * instantiate (all overloaded forms) This method is useful to create instances of parameters to MBean methods or constructors. These parameters are not in general serializable, and even if they are they are unlikely to be known to a ClassLoader on the client end of a connector. * registerMBean This method registers a local object as an MBean within the MBean server. It does not make sense to register a remote object in this way. A.2. New four-parameter removeNotificationListener methods. In JMX 1.1, the two MBeanServer.addNotificationListener methods have four parameters: the ObjectName of the MBean, the listener (either an Object or an ObjectName), the filter, and the handback. You can add the same listener with more than one filter and/or handback. However, the removeNotificationListener does not have these parameters, so there is no way to remove an individual triple (listener,filter,handback). This was apparently an oversight in JMX 1.0 since the documentation there was inconsistent. JMX 1.2 adds two new methods to the MBeanServer interface: void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException; void removeNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException; Adding new methods to an interface breaks existing code that implements the interface. But the MBeanServer interface is only implemented by the JMX implementation so user code should not be impacted. The NotificationBroadcaster interface also needed to be augmented with the ability to remove a specific (listener,filter,handback) triple. Here, adding a new method would potentially have broken user code. So JMX 1.2 adds a new interface javax.management.NotificationEmitter that extends NotificationBroadcaster to add a new method: void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException; The NotificationBroadcasterSupport class, which represents most NotificationBroadcaster instances in practice, implements the new interface, as does MBeanServerDelegate. The MBean server implements the two new removeNotificationListener methods by checking whether the target MBean is instanceof NotificationEmitter. If so, its three-argument removeNotificationListener is called. Otherwise, java.lang.UnsupportedOperationException is thrown, wrapped (as for existing exceptions) in a javax.management.RuntimeOperationsException. A.3. Support for concurrent queries. The existing technique for running queries, calling setMBeanServer on the query before evaluating it and having a static MBeanServer member in the query classes, is not correct when two queries are evaluated at the same time on different MBean servers in the same JVM. It is proposed to document that QueryEval.setMBeanServer sets a thread-local variable and to add a corresponding public static QueryEval.getMBeanServer method. Since QueryEval is public, this is an interface change, albeit minor. A.4. Changes to ObjectName. JMX 1.2 makes a number of changes to javax.management.ObjectName are proposed. This class is central to JMX so it was important to clarify its semantics and add missing functionality that had been asked for. A.4.1. Quoting mechanism for values associated with keys. This fixes an important problem where it was not possible to use arbitrary strings as values in names. For example, this made it hard to map CIM object names to JMX ObjectNames. The change is as follows. As well as the previous key=value syntax, where the value must not contain any of the characters in the set [,*?=:], a new syntax key="value" is added. This allows values to be arbitrary strings. The characters in the set [\"?*] must be quoted by a preceding backslash (\). The syntax \n is also allowed to represent a newline. No other characters may be quoted with a backslash. The value seen in the ObjectName (e.g. by the getKeyProperty method) includes the quotes and any backslashes. Two new methods are added: public static String quote(String s); public static String unquote(String s) throws IllegalArgumentException; The quote method takes an arbitrary string and converts it into a quoted form suitable for use in the value of an ObjectName. The unquote method takes a quoted string that would be legal as an ObjectName value and converts it into an unquote String. For any String s, unquote(quote(s)).equals(s). A.4.2. Newline character forbidden in ObjectName. JMX 1.2 forbids the character newline ('\n') anywhere in an ObjectName. The Relation Service uses newline to separate the names returned by Role.roleValueToString. The \n syntax is accepted in quoted values (see A.4.1) so it is still possible to represent a newline in an ObjectName. A.4.3. Factory methods for creating ObjectNames. In JMX 1.1 the only way to obtain an ObjectName is by invoking one of the constructors. JMX 1.2 adds factory methods. Since ObjectNames are immutable, this allows an implementation to return the same ObjectName instance for the same arguments. It also allows an implementation to return a private optimized subclass of ObjectName. The new methods are these: public static ObjectName getInstance(String name); public static ObjectName getInstance(String domain, Hashtable table); public static ObjectName getInstance(String domain, String key, String value); public static ObjectName getInstance(ObjectName name); The first three correspond to the previously existing constructors. They have the same parameters, throws clauses, and semantics. The fourth method produces an object that is guaranteed to implement ObjectName semantics correctly, even if its argument is of a subclass that does not. This is used by security checks based on ObjectNames, to prevent a malicious user from supplying an instance of an ObjectName subclass that returns one value for the security check and another value for the checked access. (This was preferred to making ObjectName, or all of its methods, final.) A.4.4. Clarify semantics of ObjectName.equals in the presence of patterns. In JMX 1.1, the documentation did not specify what ObjectName.getCanonicalName and ObjectName.getKeyPropertyListString look like in the presence of a property pattern, and it did not say whether the equals method required that either both or neither of the compared ObjectNames be patterns. JMX 1.2 clarifies the specification as follows: * getKeyPropertyListString does not include any indication of whether the ObjectName is a property pattern. * getCanonicalName includes a trailing ",*" if the ObjectName is a property pattern (just "*" if there are no other properties). * equals compares the getCanonicalName values (at least conceptually). A.4.5. Specify a convention for unique ObjectNames. The idea of this change is to avoid collisions between ObjectNames from different vendors. The new convention is the same for Java package names, i.e. the domain should begin with the lowercase reversed DNS name of the defining organization. A.4.6. ObjectName implements QueryExp. In JMX 1.1, an ObjectName could be a pattern, and this could be used to select a subset of MBeans in an MBean server query. However, there was no method for user code to tell whether a given ObjectName matches a given ObjectName pattern. In JMX 1.2, ObjectName implements the QueryExp interface. Thus, its method: public boolean apply(ObjectName name); returns true if "this" is an ObjectName pattern and "name" is an ObjectName that matches the pattern, or if this.equals(name) and neither "this" nor "name" is a pattern. The advantage of implementing QueryExp rather than just adding a "boolean matches(ObjectName name)" method is that an ObjectName pattern can be included in a complex query, e.g. "(domain is com.xinc.appx and attribute `owner' is fred) or (domain is com.yinc.appy and attribute `user' is fred)". A.4.7. New method ObjectName.isDomainPattern(). In JMX 1.1, you couldn't tell if an ObjectName had a wildcard in its domain without searching for wildcard characters explicitly. Both "*:*" and "domain:*" returned true for the existing methods isPattern() and isPropertyPattern(). JMX 1.2 adds a new method isDomainPattern() that returns true for the first but false for the second. A.4.9. Clarify what characters may appear where. The JMX 1.1 specification was not completely clear on what characters could be used in domains, keys, and values. The following rules are specified in JMX 1.2: * A domain may contain any character except colon. This is a difference from 1.1, where comma and equals were forbidden. The query (?) and star (*) characters imply that the ObjectName is a pattern. * A key may contain any character except colon, star, comma, equals, asterisk, or query. This rule was implemented by the 1.1 RI but not clearly specified. * An unquoted value may contain any character except colon, star, comma, equals, quote, or query. This is the same set as for a key except that the quote is also forbidden. Forbidding the quote is a change from 1.1. * A quoted value may contain any character provided the quoting conventions are followed. In addition to these rules, as mentioned above, the newline character ('\n') is forbidden everywhere. This rule is new with 1.2. A.5. Changes and clarifications to class loading and class naming. A key aim of JMX 1.2 is to clarify the semantics of class loading and class naming. Many important details of these were left unspecified in earlier versions of JMX. The details here are of interest to advanced JMX users. Most users will not need to be familiar with this level of detail. A.5.1. Clarified meaning of MBeanInfo.getClassName(). In JMX 1.1, this was incompletely specified. As of JMX 1.2, the specification is clarified as follows. For a Standard MBean, MBeanInfo.getClassName() returns the Java class (not interface) of the corresponding MBean. For a Dynamic MBean, MBeanInfo.getClassName() returns whatever string the Dynamic MBean supplies. The caller cannot always access a Java class of that name. For a Dynamic MBean, MBeanInfo.getClassName() may return any string that is a syntactically legal Java class name. As for JMX 1.1, a Dynamic MBean may return different MBeanInfos at different times, and in particular the class name may vary. It is not required that the name returned by getClassName() for a Dynamic MBean be the name of an existing Java class. If it is, we recommend but do not require that the class's public methods include those that a Standard MBean implementing the same interface would contain. In an ObjectInstance returned by one of the methods createMBean, registerMBean, or queryMBeans in the MBeanServer interface, the string returned by getClassName() is the same as MBeanInfo.getClassName() for the named MBean. RequiredModelMBean returns, by default, its own class name as MBeanInfo.getClassName(). If the user supplies a ModelMBeanInfo, the getClassName() from that is returned. A.5.2. Clarified meaning of MBeanServer.isInstanceOf(). The semantics of MBeanServer.isInstanceOf(objectName, className) are clarified as follows: If objectName does not name an MBean, the method throws InstanceNotFoundException. This behaviour is unchanged. Otherwise, let X be the MBean named by objectName, L be the ClassLoader of X, N be the class name in X's MBeanInfo. If N equals className, the result is true. Otherwise, if L successfully loads both N and className, and the second class is assignable from the first, the result is true. Otherwise, the result is false. A.5.3. MBean class name in RoleInfo tested using MBeanServer.isInstanceOf. The class RoleInfo in the JMX relation service contains an MBean class name, representing the type of MBean that can take on the role in question. In JMX 1.1, RoleInfo performs a check on this class name. It must be a valid MBean class, and to test this it must be loaded. Since the RoleInfo constructor does not reference an MBean server, the loading is done using a ClassLoaderRepository shared by all MBean servers in a given JVM. JMX 1.2 makes the following changes: - The RoleInfo constructor no longer performs any check on the class name it is given. This makes sense given that a DynamicMBean can return any string as the class name in its MBeanInfo, not necessarily an existent Java class. - On creation of a relation instance, the relation service will check that each MBean linked is an instance of the class name in the corresponding RoleInfo, as determined by MBeanServer.isInstanceOf. A.5.4. Clarify semantics of the Class Loader Repository (CLR). JMX 1.1 mentions a Class Loader Repository (also referred to as a Default Loader Repository) but does not say explicitly how loaders are added to it. JMX 1.2 clarifies the specification as follows: When an MBean is registered that is an instance of ClassLoader, it is added to the CLR, unless it is also an instance of the marker interface javax.management.loading.PrivateClassLoader. This interface is new in JMX 1.2. MLets are ClassLoaders, so this rule applies to them. A new class PrivateMLet extends MLet to implement PrivateClassLoader. A.5.4.1. MLets only delegate to earlier loaders in the CLR. In JMX 1.1, if an MLet is used to load a class, and that class is not found in the MLet's list of URLs, the MLet delegates to all other class loaders in the CLR. To avoid a deadlock situation, JMX 1.2 changes this behaviour so that an MLet will only delegate to class loaders that precede it in the CLR. If the MLet is not in the CLR then all class loaders in the CLR are consulted as before. As a result of this change, a new method is added to the ClassLoaderRepository interface: public Class loadClassBefore(ClassLoader loader); Each constructor for the MLet class acquires an overloaded version with a booleanparameter delegateToCLR, which defaults to true. When false, the MLet does not delegate to the CLR when it fails to find classes but directly throws ClassNotFoundException. A.5.4.2. The MBean server's ClassLoader is in the CLR. An undocumented feature of the JMX 1.1 RI is that the MBean server's own ClassLoader is always in the CLR. This behaviour means that the simplest createMBean method, createMBean(className, objectName), will find classes in the class-path. Many RI users depend on this, so it has been specified explicitly for JMX 1.2. The MBean server's ClassLoader cannot be removed from the CLR. There is no way to load classes from the other ClassLoaders in the CLR without consulting the MBean server's ClassLoader first. A.5.4.3. Defined order of ClassLoaders in the CLR. To reduce indeterminism between implementations, JMX 1.2 specifies exactly the order in which ClassLoaders in the CLR are consulted. When a class is loaded through the CLR, each ClassLoader from the first to the last is consulted until one of them successfully loads the class. If none of them loads the class, the result is a ClassNotFoundException. The first ClassLoader in the CLR is the MBean server's ClassLoader. Any registered MBean that is an instance of ClassLoader but not PrivateClassLoader is in the CLR. If the same object is registered under two different names then it appears twice in the CLR. (Registering the same object twice is not recommended in general.) For any two MBeans X and Y, X must appear before Y in the CLR if the registration of X was completed before the registration of Y started. If X and Y were registered concurrently, their order is indeterminate. The registration of an MBean corresponds to the call to MBeanServer.registerMBean or MBeanServer.createMBean. A.5.5. One ClassLoaderRepository per MBean server. The RI of JMX 1.1 used the same CLR for all MBean servers in a given JVM. As of JMX 1.2, every MBean server must have its own CLR. A.5.5.1. DefaultLoaderRepository specified using CLR. JMX 1.1 defined two classes called DefaultLoaderRepository, one in javax.management and one in javax.management.loading. These classes have only static methods and incorporate the assumption that there is a single shared CLR. JMX 1.2 does not remove these classes. Instead, the loadClass and loadClassWithout methods simulate a shared CLR by attempting to load through the CLR of every MBeanServer returned by MBeanServerFactory.findMBeanServer(null). A.5.6. New MBeanServer method to get the right ClassLoader for parameters. To solve certain problems related to class loading, JMX 1.1 defined three "deserialize" methods in the MBeanServer interface. JMX 1.2 deprecates these methods in favour of three new methods: * ClassLoader getClassLoaderFor(ObjectName name) Return the ClassLoader to be used for passing parameters to an existing MBean. * ClassLoader getClassLoader(ObjectName loaderName) Return the ClassLoader named by the given loaderName. * ClassLoaderRepository getClassLoaderRepository() Return this MBeanServer's ClassLoaderRepository. A.6. New permissions. JMX 1.2 defines two new permissions for fine-grained access control. Like the existing MBeanServerPermission, these permissions are only consulted if there is a security manager. A.6.1. javax.management.MBeanPermission. MBeanPermission is a Permission that controls access to the operations in the MBean server. A typical MBeanPermission looks like this: new MBeanPermission("pack.age.Class#op[d:k=v]", "invoke"); This permission grants (or controls) access to the the operation "op" in the MBean whose ObjectName is "d:k=v" and whose class name (in MBeanInfo) is "pack.age.Class". Chapter 12 of the JMX 1.2 Specification covers this permission in detail. A.6.2. javax.management.MBeanTrustPermission. MBeanTrustPermission is a BasicPermission that defines what code sources can be used to register MBeans. An attempt to register an MBean is only accepted if (1) the caller's permissions include an appropriate MBeanPermission for the registerMBean or createMBean operation, and (2) the protection domain of the MBean class to be registered has permissions that imply MBeanTrustPermission("register"). A.7. User-supplied factory for MBeanServer instances. An important change in JMX 1.2 is the ability to specify what class is instantiated by the methods MBeanServerFactory.createMBeanServer and MBeanServerFactory.newMBeanServer. The system property "javax.management.builder.initial" can be set to the name of a subclass of the new class javax.management.MBeanServerBuilder. This class contains two methods: public MBeanServerDelegate newMBeanServerDelegate(); public MBeanServer newMBeanServer(String defaultDomain, MBeanServer outer, MBeanServerDelegate delegate); A call to MBeanServerFactory.createMBeanServer/newMBeanServer will result in a call to newMBeanServerDelegate followed by a call to newMBeanServer. An MBeanServerBuilder subclass can replace the delegate and/or the MBeanServer implementation. A.8. MBeanInfo and related classes. A.8.2. MBean*Info implement equals(Object). Each of the MBean*Info classes overrides the Object.equals(Object) method to compare for equality rather than identity. This is useful because JMX allows an MBean to change its MBeanInfo at any time. A remote client can test whether this has happened by comparing the result of MBeanServer.getMBeanInfo against a previous value. A.8.3. MBeanConstructorInfo does not have to be exhaustive. If you use createMBean to construct an MBean with a given constructor, it is not an error for that constructor not to be in the new MBean's MBeanConstructorInfo array returned by getMBeanInfo(). The JMX 1.2 specification codifies this existing behaviour. A.8.4. MBean*Info constructors check for valid Java identifiers. The JMX 1.1 spec already stated that (e.g.) attribute names must be valid Java identifiers. JMX 1.2 requires that the constructors for the MBean*Info classes check that the supplied names do in fact meet this constraint. Specifically: * In MBeanAttributeInfo, MBeanOperationInfo, and MBeanParameterInfo "name" must be a syntactically valid Java identifier and "type" must be a syntactically valid Java class name. * In MBeanInfo, "className" must be a syntactically valid Java class name. * In MBeanConstructorInfo and MBeanNotificationInfo, "name" must be a syntactically valid Java class name. If these conditions are not met, the constructors throw IllegalArgumentException. The check for syntactically valid Java identifiers or class names does not include a test for Java reserved words. A.9. Changes related to javax.management.Notification. A.9.1. Clarifications concerning Notification.source. JMX 1.2 now documents the way the MBean server replaces a reference to an MBean in the source of a Notification with the ObjectName of that MBean. It also discourages users from doing this. JMX 1.2 explains why there is a "source" field in javax.management.Notification when there is already one in the parent class java.util.EventObject. The reason is that Notification.source is non-transient and is part of the serialized form. A.9.2. Control over notification dispatch in NotificationBroadcasterSupport. In JMX 1.2, NotificationBroadcasterSupport acquires a new method: protected void handleNotification(NotificationListener listener, Notification notification, Object handback); This method is called during sendNotification for each listener registered with the NotificationBroadcaster. By default, it simply does listener.handleNotification(notification, handback). A subclass can, for instance, dispatch the notification in a separate thread, or catch RuntimeException and remove the listener that generated it. A.10. Changes to Timer Service. A.10.1. Changed behaviour when scheduled time is already past. JMX 1.2 changes the behaviour of Timer.addNotification when the specified time for the notification is already past. Instead of throwing IllegalArgumentException, it behaves as if the time specified were the current time. For once-off notifications, the notification is delivered immediately. For periodic notifications, the first notification is delivered immediately and the subsequent ones are spaced as specified by the period parameter. The reasoning behind this change is that the existing behaviour does not allow you to safely schedule a notification for the very near future. Circumstances beyond the program's control, such as heavy system load, may cause the schedule time to be already past by the time the addNotification method is called. A.10.3. Public constructor for TimerNotification. JMX 1.2 makes the constructor of the class TimerNotification public: public TimerNotification(String type, Object source, long sequenceNumber, long timeStamp, String msg, Integer id); This allows user code to construct such notifications, e.g. in a replacement for the timer service. A.10.4. Periodic notification can be fixed-delay or fixed-rate. The JMX 1.1 specification is not clear on the exact meaning of periodic notification in the timer service. As of JMX 1.2, the default behaviour is "fixed-delay execution", as specified in java.util.Timer. An additional overloaded Timer.addNotification method has been added with a boolean parameter that can specify "fixed-rate execution". A.11. Changes to Monitor Service. A.11.2. Monitoring the same attribute in several MBeans. It is proposed to extend the Monitor class and its subclasses so that the same attribute can be monitored in several MBeans. A notification is sent every time any of the MBeans meets the notification criteria. The Monitor class and MonitorMBean interface acquire these new methods: public ObjectName[] getObservedObjects(); public void addObservedObject(ObjectName name); public void removeObservedObject(ObjectName name); public boolean containsObservedObject(ObjectName name); The existing setObserverObject method removes all ObjectNames from the set and then adds its ObjectName argument. The CounterMonitor class and CounterMonitorMBean interface acquire, in addition, these new methods: public void setInitThreshold(Number value); public Number getInitThreshold(); public Number getThreshold(ObjectName name); public Number getDerivedGauge(ObjectName name); public long getDerivedGaugeTimeStamp(ObjectName name); The get/setInitThreshold methods specify the initial threshold to be used for each new observed object. The remaining methods add an ObjectName parameter to existing methods. The existing methods without an ObjectName parameter only work if there is exactly one observed MBean. (This is therefore compatible with existing code.) A.12. Changes to Relation Service. A.12.1. Changed semantics of RoleInfo class. The clarification of class-loading behaviour implies a change to the semantics of the class javax.management.relation.RoleInfo. See A.5.3. A.12.2. Role.roleValueToString separated by newlines. In JMX 1.1, the Javadoc for this method said the returned values were separated by commas, but the implementation separated them by newlines. Commas make no sense because the values being separated are ObjectNames which can contain commas. If an ObjectName could contain an embedded newline this would still lead to problems, so newline has been added to the list of special characters in ObjectName (see A.4.1). A.13. Changes to Open MBeans. A.13.1. Open MBeans become mandatory. In JMX 1.0, Open MBeans were an optional part of JMX because they were incompletely specified. In JMX 1.1, the specification of Open MBeans was completed and an implementation was included in the RI, but they remained optional. Since optional parts of specifications lead to portability problems, Open MBeans become mandatory in JMX 1.2. A.13.2. OpenMBeanInfo will never extend MBeanInfo. In JMX 1.1, the Javadoc suggested that a future version of JMX might make MBeanInfo an interface, in which case the OpenMBeanInfo interface could inherit from it and OpenMBeanInfoSupport would inherit from a hypothetical MBeanInfoSupport. Such a change would be gratuitously incompatible so it is not going to happen. The Javadoc should be revised. A.13.3. Constants in SimpleType should be final. In JMX 1.1, the constants VOID, BOOLEAN, etc in the class javax.management.openmbean.SimpleType were static but not final because the expressions to construct their initial values threw checked exceptions. There is a straightforward way to code the initialization nevertheless, so these constants become final in JMX 1.2 This change is not strictly upward compatible but is retained becauses it closes a security hole. Previously, malicious code could replace the values of these constants with incorrect values. A.13.4. Add java.util.Date to SimpleType possibilities. This allows a simple, type-safe way to have timestamp attributes. It does not solve the problem of attributes whose type is an interval, since Java doesn't have a class specifically for that. A.14. Changes to MLets. The proposed clarification to class loading affects the specification of MLets. See the separate document that explains those changes. Below are additional proposed changes. A.14.1. MLet implements Externalizable. In JMX 1.1, the MLet class has methods readExternal and writeExternal with the correct signatures to implement the java.io.Externalizable interface, but it does not in fact implement that interface. As of JMX 1.2, it does. Because it is not extremely useful to read or write an MLet, and because the implementation in the Reference Implementation of JMX 1.0 and 1.1 did not work, JMX 1.2 allows implementations not to support these methods, throwing UnsupportedOperationException, and in fact the Reference Implementation does this. [A previous version of this document proposed removing the methods readExternal and writeExternal instead. That proposal has been withdrawn because it does not respect strict upward compatibility.] A.14.2. MLet.check method should be protected rather than private. This method was explicitly designed to allow subclasses of MLet to implement caching and versioning. But for some reason it was left private. As of JMX 1.2 it is protected instead. For this to be useful, the MLetContent class, which had package access in the RI of JMX 1.1, has been made public. A.15. Serial compatibility with JMX 1.0 is not required. JMX 1.1 changed the (incompletely specified) serial form of several classes in JMX 1.0. It introduced a property jmx.serial.form to allow code to continue to use the old form. The JMX 1.2 specification says explicitly that independent implementations are not required to support this feature. A.16. Clarification of ObjectName in MBeanRegister.preRegister. This method is called when an MBean that implements the MBeanRegistration interface is registered in the MBean server. The exact meaning of the ObjectName parameter and the ObjectName return value was unclear from the specification of JMX 1.1. JMX 1.2 adds this text to the Javadoc: * @param name The object name of the MBean. This name is null if * the name parameter to one of the createMBean or * registerMBean methods in the {@link MBeanServer} * interface is null. In that case, this method must return a * non-null ObjectName for the new MBean. * * @return The name under which the MBean is to be registered. * This value must not be null. If the name * parameter is not null, it will usually but not necessarily be * the returned value. A.17. Implementations must forbid calling getters and setters via invoke. In JMX 1.1, the specification says that an implementation may or may not allow a getX or setX method in a Standard MBean to be accessed as an operation via MBeanServer.invoke. This was left in place for time reasons. Unspecified behaviour like this is not desirable, so as of JMX 1.2 implementations must forbid calling getters and setters via invoke. A.18. Retrieving all domains in the MBean server. JMX 1.2 adds the following method to the MBeanServer and MBeanServerConnection interfaces: String[] getDomains(); The returned array contains the domains of all currently-registered MBeans. More exactly, a String s appears in the returned array iff there is at least one MBean registered with an ObjectName whose getDomain() returns a String equal to s. A.19. Standard MBeans. A.19.1. Specify exact rules for deriving NameMBean from Name. The JMX 1.1 specification is unclear exactly what is meant when it says that the management interface of a Standard MBean whose implementation class is Name must be called NameMBean. It does not say whether package names are taken into consideration. Different implementations of JMX 1.1 have different behaviour so this had to be clarified. JMX 1.2 states explicitly that if the implementation class is some.package.Name then the management interface must be some.package.NameMBean. A.19.2. Hybrid of Standard and Dynamic MBeans. This change rectifies an important shortcoming in the use of Standard MBeans, namely that there is a fixed relationship between the implementation class of the MBean and its management interface (i.e., if the implementation class is Thing, the management interface must be ThingMBean). Additionally, the change helps with another shortcoming of Standard MBeans, which is that it is not possible to add to the metadata derived from the MBean interface, for instance the string descriptions of attributes and operations. JMX 1.2 adds a new class javax.management.StandardMBean: public class StandardMBean implements DynamicMBean { public StandardMBean(Object impl, Class intf) throws NotCompliantMBeanException { // ... } protected StandardMBean(Class intf) throws NotCompliantMBeanException { this(this, intf); // not actually legal Java but you get the idea } // ...methods from DynamicMBean... protected String getDescription(MBeanOperationInfo op); protected String getDescription(MBeanOperationInfo op, MBeanParameterInfo param, int paramNumber); // ...other getDescription methods... protected int getImpact(MBeanOperationInfo op); protected String getParameterName(MBeanOperationInfo op, MBeanParameterInfo param, int paramNumber); // ...likewise for MBeanConstructorInfo... public Class getMBeanInterface(); public Object getImplementation(); public Class getImplementationClass(); public void setImplementation(Object implementation); protected void cacheMBeanInfo(MBeanInfo); protected MBeanInfo getCachedMBeanInfo(); } An MBean can be created with any implementation class name Impl and with a management interface defined (as for current Standard MBeans) by any interface Intf, in one of two general ways: MBeanServer mbs; // EITHER... Impl impl = new Impl(...); StandardMBean mbean = new StandardMBean(impl, Intf.class); mbs.registerMBean(mbean, objectName); // OR... public class Impl extends StandardMBean implements Intf { public Impl() { super(Intf.class); } // implement methods of Intf } Impl impl = new Impl(); mbs.registerMBean(impl, objectName); In either case, the class Impl must implement the interface Intf. The existing Standard MBeans, where the management interface is discovered based on the name of the implementation class, are retained unchanged. A.20. InvocationHandler for MBean proxies. Since MBeanServer methods such as invoke, getAttribute, and setAttribute have no type checking, JMX 1.2 adds an implementation of the java.lang.reflect.InvocationHandler interface that can be used to construct a proxy for an MBean given its management interface. In addition to type checking, this greatly simplifies client code. The new class, javax.management.MBeanServerInvocationHandler, looks like this: import java.lang.reflect.*; public class MBeanServerInvocationHandler implements InvocationHandler { public MBeanServerInvocationHandler(MBeanServerConnection mbsc, ObjectName objectName); public static Object newProxyInstance(MBeanServerConnection mbsc, ObjectName objectName, Class interfaceClass, boolean notificationBroadcaster); public Object invoke(Object proxy, Method method, Object[] args); // specified by InvocationHandler } To make a proxy for an MBean named objectName in the MBeanServer mbs, whose management interface is Intf, do this: Class intfClass = Intf.class; InvocationHandler h = new MBeanServerInvocationHandler(mbs, objectName); Intf proxy = (Intf) Proxy.newProxyInstance(intfClass.getClassLoader(), new Class[] {intfClass}, h); This is exactly the behaviour of the call: MBeanServerInvocationHandler.newProxyInstance(mbs, objectName, intfClass, false) A call to a getter or setter in Intf will produce a call to mbsc.get/setAttribute. A call to another method in Intf will produce a call to mbsc.invoke. If the proxied MBean is an instance of NotificationBroadcaster or NotificationEmitter, the notificationBroadcaster parameter to newProxyInstance can be true, in which case the NotificationEmitter interface is added to the list of interfaces for the proxy. A call to addNotificationListener or removeNotificationListener on the proxy will produce a call to mbsc.add/removeNotificationListener. The methods toString(), hashCode(), and equals(Object) inherited from java.lang.Object are forwarded to the MBean server in the same way as other methods. This will only work if the MBean declares those methods in its management interface. Because of the way proxies work, it is not possible for an MBeanServerInvocationHandler constructed in the first way illustrated above to know whether or not the management interface does or does not contain these methods. A.21. Wrapped exceptions accessible with getCause(). Certain JMX exceptions wrap other exceptions. In JMX 1.1, they define a getTargetException() method to retrieve the wrapped exception. In JMX 1.2, they also override the getCause() method introduced in J2SE 1.4. A.22. Changes to Model MBeans. A.22.2. Descriptor extends Cloneable. The Descriptor interface includes a public clone() method so it makes sense for it to extend java.lang.Cloneable. A consequence is that DescriptorSupport is also Cloneable. A.22.3. RequiredModelMBean implements MBeanRegistration. The documentation says that it is illegal to call setModelMBeanInfo on a ModelMBean once it has been registered in the MBean server. But in JMX 1.1, RequiredModelMBean does not implement MBeanRegistration, making it difficult to enforce this constraint. In JMX 1.2, RequiredModelMBean does implement MBeanRegistration. Existing code that subclasses RequiredModelMBeanInfo to implement MBeanRegistration will not benefit from the check unless the subclass's preRegister method is changed to call super.preRegister. Making RequiredModelMBean.preRegister final to ensure that the check is made would have risked breaking existing code so it was not proposed. A.22.4. RequiredModelMBeanInfo.invoke invokes locally or on resource. In JMX 1.1, the specification for RequiredModelMBean implies very indirectly that the invoke method (from the DynamicMBean interface) can invoke both (a) methods from the ModelMBeanInfo and (b) methods from the RequiredModelMBean class itself. Though this is not very clean, there is no other way for clients to invoke useful methods such as addAttributeChangeNotificationListener and getNotifications. JMX 1.2 therefore states more explicitly that the invoke method will invoke a method of RequiredModelMBean if one matches the given signature, and otherwise a method from the ModelMBeanInfo on the Managed Resource. A.22.5. ModelMBeanInfo.getNotifications() includes standard notifications. A RequiredModelMBean may emit the notification with name "Generic" and type "jmx.modelmbean.generic" and it may send an AttributeChangeNotification. In JMX 1.1, these notifications are not declared in the value returned by RequiredModelMBeanInfo.getMBeanInfo().getNotifications() unless they are explicitly added there by the programmer. In JMX 1.2, these notifications are automatically added to the list defined by the user if they are not already present. A.22.6. Descriptor's persistPolicy includes "always". In JMX 1.1, there is an inconsistency between the Javadoc of DescriptorSupport, which mentions a possible value "always" for persistPolicy, and the PDF specification, which does not. In JMX 1.2, this value appears in the PDF as a synonym for "OnUpdate", with a note discouraging its use. A.22.7. Remove "iterable" Descriptor field. In JMX 1.1, the semantics of this field are not specified so nobody can use it. JMX 1.2 removes any mention of it from the specification. A.22.8. Descriptor field names are case insensitive. In JMX 1.1, the Javadoc says this but the PDF specification does not. JMX 1.2 adds this to the PDF specification. A.22.9. Descriptor "export" field can contain external name. In JMX 1.1, the Javadoc for DescriptorSupport.isValid (and the RI implementation) only allows the values "t", "true", "f", "false". The PDF says the value "should be the external name or object required to export the MBean appropriately". In JMX 1.2, the Javadoc and the implementation have been changed to match the PDF. A.22.10. Require XML support in DescriptorSupport. In JMX 1.1, the RI includes a constructor for DescriptorSupport that takes an XML string and describes it as being "part of this implementation and not required by the JMX Specification". This is inconsistent, since the constructor is public and therefore appears in the Javadoc, which is part of the JMX Specification. Furthermore, there is a public method toXMLString which is not described as being "part of this implementation". In JMX 1.2, implementations must include the constructor and the method. No specification of the syntax of the XML string has yet been defined. A.22.11. Type of Descriptor's "protocolMap" field is Descriptor. In JMX 1.1, the Javadoc for ModelMBeanAttributeInfo says that the value of this field must of type ProtocolMap. No such type is defined in JMX, and the PDF specification says that the value must be a Descriptor. In JMX 1.2, the Javadoc has been made consistent with the specification. A.22.12. "class" field of constructor Descriptor removed. In JMX 1.1, this field is mentioned in the Javadoc for ModelMBeanConstructorInfo but not described in the PDF specification. Since its purpose was not clear, it has been removed from the Javadoc in JMX 1.2. A.22.14. ModelMBeanOperationInfo Descriptor cannot be "constructor". In JMX 1.1, the Javadoc for ModelMBeanOperationInfo says that the "role" field of the Descriptor can have the value "constructor". This does not make sense, since a constructor should be specified with ModelMBeanConstructorInfo. So this has been removed from JMX 1.2. A.22.15. Default value for attribute specified as "default". In JMX 1.1, the PDF specification says in some places that a default value for an attribute can be specified using the "defaultValue" field in its Descriptor and in others using "default". The Javadoc and the RI use a "default" field. In JMX 1.2, this has been corrected to say "default" everywhere. A.22.16. Specification should not refer to missing findPersistent method. In JMX 1.1, the PDF specification for persistence in Model MBeans says, of ModelMBean.load: "This method must determine if this model MBean has a persistent representation by invoking the findPersistent method." No such method is defined in any JMX interface. In JMX 1.2, this text is removed. A.22.17. ModelMBean.load called from preRegister not constructor. In JMX 1.1, the PDF specification for persistence in Model MBeans says that the load method is called from the ModelMBean constructor. It makes more sense to call it from the preRegister method (now that this method is defined, see A.22.3), so this is what JMX 1.2 specifies. Persistence is not implemented in the JMX 1.1 RI. Existing code based on other implementations is unlikely to be affected by this change. DEFERRED CHANGES ================ D.4.8. Support key=* wildcard in ObjectName. In JMX 1.1, you can have a pattern "domain:key1=value1,*" to match any ObjectName that has exactly that (key,value) pair amongst its keys and values, but you cannot have a pattern "domain:key1=*,*" to match any ObjectName that has a key called key1. The proposal was to add this syntax and allow it in MBean server queries and in the new apply methods (see section 4.6). DEFERRED: This proposal has been deferred to a future revision. D.14.3. MLet file should have explicit syntax for comments. Today the RI allows you to include any garbage outside of <...>. Should instead support comment syntax. This will break existing code that depended on this undocumented behaviour of the RI. DEFERRED: This proposal has been deferred to a future revision. REJECTED CHANGES ================ R.3. Support for concurrent queries via new subinterface of QueryExp. The existing technique for running queries, calling setMBeanServer on the query before evaluating it and having a static MBeanServer member in the query classes, is not correct when two queries are evaluated at the same time on different MBean servers in the same JVM. While it is possible to work around this problem by using ThreadLocal variables, it is cleaner to change the interface as follows: A new interface QueryExpression extends QueryExp to add a new method boolean apply(ObjectName name, MBeanServer mbs) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException; This is the same as the apply method in QueryExp except for the addition MBeanServer parameter. All of the existing javax.management classes that implement QueryExp are changed to implement QueryExpression instead. The appropriate instanceof logic is added to the MBean server query code so that invokes the two-argument apply if possible. Although the JMX specification discourages users from implementing their own QueryExp classes, such classes will continue to work, but if they do setMBeanServer they are still vulnerable to the problem with concurrent queries. REJECTED: This is a big change to solve a small problem. The approach described in A.3 is sufficient. R.8.1. MBean*Info classes become explicitly immutable. The proposal is that the description of the following classes will specify that they are immutable: MBeanAttributeInfo MBeanConstructorInfo MBeanFeatureInfo MBeanInfo MBeanNotificationInfo MBeanOperationInfo MBeanParameterInfo The getters of these classes become final to ensure immutability. Subclasses may add additional attributes but the values supplied to the constructors of these classes cannot subsequently change. Notably, the ModelMBean*Info classes are mutable because they each have a setDescriptor method, but the attributes they inherit from MBean*Info cannot change. The protected fields "description" and "name" in MBeanFeatureInfo become private to avoid compromising immutability. They remain in the serialized form. REJECTED: This change would not respect strict upward compatibility. R.10.2. Internal class TimerAlarmClockNotification should not be public. It is proposed to remove the public class TimerAlarmClockNotification. This class has a public constructor that takes a parameter of a type (TimerAlarmClock) that is not public. It is only used internally by the timer implementation and cannot be used by user code. REJECTED: This change would not respect strict upward compatibility. R.11.1. Internal fields in Monitor class should not be protected. The Monitor class contains a number of fields that are used by the Reference Implementation but are not of use to subclasses. Independent implementations should not be required to have these. The following fields in the Monitor class are protected in JMX 1.1 and should be removed from the public API in JMX 1.2: alreadyNotified RESET_FLAGS_ALREADY_NOTIFIED OBSERVER_OBJECT_ERROR_NOTIFIED OBSERVED_ATTRIBUTE_ERROR_NOTIFIED OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED RUNTIME_ERROR_NOTIFIED dbgTag The following field remains: protected MBeanServer server; REJECTED: This change would not respect strict upward compatibility. R.22.1. Remove ModelMBeanInfoSupport.getDescriptor(String). In JMX 1.1, the meaning of this method was unclear from the Javadoc. It is not clear what the method could reasonably mean. Furthermore, in the JMX 1.1 RI the implementation was broken (always threw an exception). So removing this method should affect nobody. REJECTED: In fact the meaning of this method is clear from the description of getDescriptor(String,String) where the second parameter is null. The RI has been fixed so it does not throw an exception. R.22.13. Remove "getter" and "setter" fields from operation Descriptor. The Javadoc for ModelMBeanOperationInfo refers to "getter" and "setter" fields in the Descriptor for an operation, but the semantics of these fields are not defined and nothing is implemented for them. Getters and setters are specified using ModelMBeanAttributeInfo so it is proposed to remove the references to them from ModelMBeanOperationInfo. REJECTED: This change is not correctly described. In fact what was proposed was that the "role" field for an operation should no longer have "getter" or "setter" as possible values. But in fact these values are useful when the operation is specified as the getMethod or setMethod for an attribute.