# javax.management.ObjectName changes

## The `getInstance()` methods

JMX 1.2 introduced four overloaded static version of the `getInstance()` method: `public static ObjectName getInstance(String name)` `public static ObjectName getInstance(ObjectName name)` `public static ObjectName getInstance(String name, Hashtable properties)` `public static ObjectName getInstance(String domain, String key, String value)`

The first version is the preferred way to create ObjectNames, and should be used instead of using the new Java keyword. Creating a new ObjectName from a string is expensive because require parsing of the string. JMX implementations may use caching techniques to speed up creation of ObjectNames from strings. MX4J does this optimization both in this method and in the ObjectName's constructor; it is likely that other implementations perform the optimization in getInstance(), but not in the ObjectName's constructor, so choosing to use getInstance() ensure coherent behaviors.

The second version is mostly used to convert ObjectName subclasses to plain ObjectName. This is useful in a secure environment where evil ObjectName subclasses can try to bypass security checks done when `javax.management.MBeanPermission`s are checked to see if access to the MBean with the given ObjectName is allowed or not.

The third and the fourth version are just a replacement for the usage of the new Java keyword, and offer mostly syntactic sugar to your code.

## The `quote()` and `unquote()` methods

JMX 1.2 introduced a way to "quote" the value of ObjectName's properties that is, to allow special characters to be present in the properties values of an ObjectName.

A simple example of this feature is to specify an LDAP name as an ObjectName property value. Since the comma is a reserved character that separates ObjectName properties, it would have been impossible to specify an LDAP name as an ObjectName property.

Let's suppose to have a distinguished name of 'uid=guest,ou=project,o=company', and to build an ObjectName with a property called 'dname' whose value is the distinguished name. Without quoting, the ObjectName is:

:dname=uid=guest,ou=project,o=company

which leads to an invalid ObjectName.

Using quoting, instead, it becomes:

:dname="uid=guest,ou=project,o=company"

which leads to a valid ObjectName.

It is possible also to "unquote" the property value to obtain the original string.

The ObjectName class has no knowledge if a value should be quoted or not, so it is responsibility of the developer to quote and unquote property values. It is a good practice to do so in those cases where the property value is chosen by users, for example by inputting it in a web form or in a swing gui.

Refer to the javadoc of the ObjectName class for further information.

## Support for remote API

## Overview

JMX 1.2 defined all changes to the JMX specification needed to support remote API. Imagine a situation where a client needs to contact a remote MBeanServer, to invoke operations on it and to receive the result of such invocations. In order for this situation to be possible, the JMX specification needed several changes such as specifying the serialVersionUID of serializable classes that can be exchanged between the client and the remote MBeanServer (for example `javax.management.MBeanInfo`), specifying details of MBeanServer's classloading to support classloading from remote locations, and the possibility for the client to invoke operations on an MBeanServer-like interface that supports remote invocation (for example that throws IOException if the connection with the remote MBeanServer is broken).

## The `javax.management.MBeanServer` class inherits from `javax.management.MBeanServerConnection`

The MBeanServer interface cannot be used directly by clients that need to contact a remote MBeanServer. The reason is that this interface does not list, in its method's throws clause, `java.io.IOException` as a possible exception being thrown. Furthermore, the MBeanServer interface has some method (like registerMBean(), deserialize(), getClassLoader(), etc.) that have no meaning in the remote case.

The `javax.management.MBeanServerConnection` interface has been defined as the portion of the MBeanServer interface that can be used by client to contact a remote MBeanServer, and is MBeanServer's parent interface.

## The `javax.management.MBeanServerBuilder` class

## Introduction

JMX 1.2 introduced the possibility to replace, at runtime, the MBeanServer implementation by specifying a full qualified name of a `javax.management.MBeanServerBuilder` subclass with the system property "javax.management.builder.initial". When creating a new `MBeanServer` instance, the `MBeanServerFactory` checks (every time) for the value of that system property; if it is not null, loads (using the context classloader), instantiates, and delegates the `MBeanServerBuilder` subclass to create `MBeanServer` instances.

Since now the creation of `MBeanServer` instances can be delegated to a custom `MBeanServerBuilder`, it is possible to achieve two things:

- Use Sun's JMX reference implementation (JMXRI) but telling it to use MX4J's `MBeanServer` implementation
- "Wrap" the `MBeanServer` implementation and "decorate" it with added functionality.

## How to use MX4J's `MBeanServer` implementation with Sun's JMX Reference Implementation.

This is very simple to achieve:

    java -cp jmxri.jar;mx4j-impl.jar -Djavax.management.builder.initial=mx4j.server.MX4JMBeanServerBuilder <MyClass>

Note how the classpath specifies first the JMXRI jar and then the MX4J implementation jar.

## How to "decorate" `MBeanServer` methods.

A custom `MBeanServerBuilder` allows you to specify how to create an `MBeanServer`. Any JMX implementation has already in place a mechanism that uses a default `MBeanServerBuilder` to create instances of the default `MBeanServer` implementation. In order to be able to "decorate" an `MBeanServer` it is sufficient to specify a custom `MBeanServerBuilder` that "decorates" the default one; then the implementation of the custom `MBeanServerBuilder` will "decorate" the default `MBeanServer`.

However, implementing a "decorating" `MBeanServerBuilder` requires a bit of precision. We will explain how to do this in detail in the following, using as example the MX4J implementation.

Using the `MBeanServerBuilder` to "decorate" an `MBeanServer` requires to write two classes:

- a custom `MBeanServerBuilder`
- a decorating `MBeanServer`

Although it's possible to start from scratch, the MX4J API gives you two base classes to start from:

- `mx4j.server.ChainedMBeanServerBuilder`
- `mx4j.server.ChainedMBeanServer`

Let's suppose we want to decorate the default `MBeanServer` by adding logging statements whenever a `MBeanServer` method is called. First, we write the "decorating" `MBeanServer`:

### A "decorating" `MBeanServer` that logs method calls.

    public class LoggingMBeanServer extends ChainedMBeanServer
    {
       // Overridden just to make it public
       public void setMBeanServer(MBeanServer server)
       {
          super.setMBeanServer(server);
       }

       public Object getAttribute(ObjectName objectName, String attribute)
          throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException
       {
          Object value = super.getAttribute(objectName, attribute);
          System.out.println("[LOGGER] getAttribute() returned: " + value);
          return value;
       }

       // And so on for all other MBeanServer methods.
    }

The class `ChainedMBeanServer` simply forwards the calls to a nested `MBeanServer`. `ChainedMBeanServer` thus allows to create a "chain" of `MBeanServer`s that are called in succession, one after the other, from the outermost to the innermost.

Second, we write the "decorating" `MBeanServerBuilder`:

### A "decorating" `MBeanServerBuilder`

    public class LoggingBuilder extends ChainedMBeanServerBuilder
    {
       public LoggingBuilder()
       {
          super(new mx4j.server.MX4JMBeanServerBuilder());
       }

       public MBeanServer newMBeanServer(String defaultDomain, MBeanServer outer, MBeanServerDelegate delegate)
       {
          LoggingMBeanServer extern = new LoggingMBeanServer();
          MBeanServer nested = getMBeanServerBuilder().newMBeanServer(defaultDomain, outer == null ? extern : outer, delegate);
          extern.setMBeanServer(nested);
          return extern;
       }
    }

As for the `ChainedMBeanServer` class, also `ChainedMBeanServerBuilder` simply forwards the calls to a nested `MBeanServerBuilder`. Also here, `ChainedMBeanServerBuilder` allows to create a "chain" of `MBeanServerBuilder`s that are called in succession, one after the other, from the outermost to the innermost.

The `MBeanServerBuilder` chain works in parallel with the `MBeanServer` chain in this way:

### The `MBeanServerBuilder` and `MBeanServer` chains

    MBeanServerFactory  -- calls -->   LoggingBuilder     -- calls -->  MX4JMBeanServerBuilder
                                             |                                   |
                                          creates                             creates
                                             |                                   |
                                             V                                   V
           Application  -- calls -->  LoggingMBeanServer  -- calls -->     MX4JMBeanServer

Note the `LoggingBuilder` constructor: there is where the `MBeanServerBuilder` chain is created. The `LoggingBuilder` specifies a chain of only two rings, the `LoggingBuilder` itself, and MX4J's default `MBeanServerBuilder`, `MX4JMBeanServerBuilder`. This chain is hardcoded in the builder, meaning that if you want to change it at runtime you cannot: either you change and recompile the custom builder, or you use another custom builder.

Note also the usage of the ternary operator (condition ? this : that) in the nested `newMBeanServer()` call: checking for nullity of the "outer" argument is of fundamental importance for the builder to be "chainable". If this check is not made, then `LoggingBuilder` cannot be reused as a ring of a longer chain if, in future, we modify it to accept as parameter to the constructor other builders (i.e. other "rings").

It is of course possible to use different builders from different vendors, simply by creating a custom builder that "chains" all the other in the desired sequence:

### A "decorating" `MBeanServerBuilder`

    public class ComplexBuilder extends ChainedMBeanServerBuilder
    {
       public LoggingBuilder()
       {
          super(new com.sun.jmx.bar.BarBuilder(new com.ibm.jmx.foo.FooBuilder(new mx4j.server.MX4JMBeanServerBuilder())));
       }
    }

Just remember that `MX4JMBeanServerBuilder` is a "terminal" builder and must always be the last in the chain. Other vendors are expected to provide an API for their custom builders very similar to `ChainedMBeanServerBuilder` (which is mostly being able to take a `javax.management.MBeanServerBuilder` as argument to a constructor).

## More complex `MBeanServer` "decorations".

We saw above that is possible to "decorate" `MBeanServer`s by decorating the default mechanism of the `MBeanServerBuilder` already in place in any JMX implementation. We saw that to a chain of builders corresponded a chain of servers. However, it's possible that a builder specifies more than one ring for the server chain, in the following way:

### A More complex `MBeanServerBuilder` and `MBeanServer` chains

    MBeanServerFactory --calls-->  LoggingBuilder    --calls-->          PerformanceBuilder    --calls-->    MX4JMBeanServerBuilder
                                         |                                        |                                     |
                                      creates                                  creates                               creates
                                         |                                   /         \                                |
                                         V                                  V           V                               V
           Application --calls--> LoggingMBeanServer --calls--> TimingServer --calls--> CountingServer --calls--> MX4JMBeanServer

An example of such chains is present in the MX4J testsuite, in the test class that tests the `MBeanServerBuilder` functionality.

## Possible usages of MBeanServer "decorators"

A (non complete) list of possible "decorators" for `MBeanServer` may include functionality such as:

- Logging the invocation
- Measuring the invocation time
- Counting the number of invocations
- Load-balancing the invocations among server nodes
- Cascading the invocations to child servers
- Notifying a message to someone for a particular invocation
- ...

## The `javax.management.MBeanServerInvocationHandler` class

## Introduction

MX4J version 1.x provided a custom implementation of a JDK 1.3's dynamic proxy to ease invocation of methods on a MBean via the MBeanServer, the `mx4j.util.StandardMBeanProxy` class. MX4J 1.x provided also a class for invocation of methods on remote MBeans, namely `mx4j.connector.RemoteStandardMBeanProxy` based on MX4J's custom remote implementation. In MX4J 1.x these classes were separated since JMX 1.1 did not specify a super-interface for MBeanServer that could be used also remotely.

In JMX 1.2, the `javax.management.MBeanServer` interface inherits from the `javax.management.MBeanServerConnection` interface. The MBeanServerConnection interface has basically the same methods of MBeanServer except those that does not have sense remotely (like deserialize() and registerMBean()), and adds `java.io.IOException` in the throws clause of each method, thus making it the "remote" view of a remote MBeanServer.

As of JMX 1.2, both `mx4j.util.StandardMBeanProxy` and `mx4j.connector.RemoteStandardMBeanProxy` are obsolete since they have been replaced by one single class, the standard `javax.management.MBeanServerInvocationHandler` class, that takes advantage of the improved class hierarchy of the `javax.management.MBeanServer` interface to unify the functionalities that were provided before by the two MX4J classes.

In the following section will be explained how to port old MX4J 1.x code to the new JMX 1.2 code.

## MBeanServerInvocationHandler usage

The JMX API to call an MBean via MBeanServer is very tedious: involves a reflection-like syntax and a complex exception handling. The reflection-like syntax is sometimes an advantage, but it suffers of lack of static type checkings made by the compiler. The exception handling is complex since it involves unwrapping of `javax.management.MBeanException`s and rethrowing of the original exception thrown by the MBean method, very much like `java.lang.reflect.InvocationTargetException` requires.

Fortunately, JDK 1.3 provides dynamic proxies via the `java.lang.reflect.Proxy` class. By means of dynamic proxies, is it possible to write a proxy that hides the complexity of JMX invocations and provides static type checking and trasparent exception handling. Compare the two code examples below and note how the second example is cleaner.

### Standard JMX invocation

    // The ObjectName of the delegate MBean
    ObjectName delegateName = ObjectName.getInstance("JMImplementation:type=delegate");

    MBeanServer server = ...;

    // The MBeanServer ID
    String id = null;
    try
    {
       id = server.getAttribute(delegateName, "MBeanServerId");
    }
    catch (MBeanException x)
    {
       // The getMBeanServerId() method threw an exception ?!?
    }
    catch(AttributeNotFoundException x)
    {
       // Uh ? Not a compliant JMX implementation ?
    }
    catch (InstanceNotFoundException x)
    {
       // Uh ? Not a compliant JMX implementation ?
    }
    catch (ReflectionException x)
    {
      // Uh ? What happened here ?
    }

### JMX invocation with MBeanServerInvocationHandler

    // The ObjectName of the delegate MBean
    ObjectName delegateName = ObjectName.getInstance("JMImplementation:type=delegate");

    MBeanServer server = ...;

    Object proxy = MBeanServerInvocationHandler.newProxyInstance(server, delegateName, MBeanServerDelegateMBean.class, true);
    MBeanServerDelegateMBean delegateMBean = (MBeanServerDelegateMBean)proxy;

    // The MBeanServer ID
    String id = delegateMBean.getMBeanServerId();

Usage of the `javax.management.MBeanServerInvocationHandler` class is straightforward for standard MBeans, since they already comply a management interface that is also a Java interface. This interface can be used directly as argument for the creation of the proxy (the third parameter of the MBeanServerInvocationHandler.newProxyInstance() call). However, usage of MBeanServerInvocationHandler is not limited to standard MBeans, but also to dynamic MBeans can use it, provided that the management interface they comply to does not change during proxy's life. It is not necessary that the dynamic MBean implements a Java interface: it is enough that the Java interface provided to the MBeanServerInvocationHandler is a (sub)set of the management interface exposed by the dynamic MBean.

The MBeanServerInvocationHandler class can also be used for remote MBeans, in conjuction with the JSR 160 API, like shown in the following code snippet:

### Remote JMX invocation with MBeanServerInvocationHandler

    // The address of the connector server
    JMXServiceURL address = ...;

    // Create the JMXCconnectorServer
    JMXConnector cntor = JMXConnectorFactory.connect(address);

    // Obtain a "stub" for the remote MBeanServer
    MBeanServerConnection mbsc = cntor.getMBeanServerConnection();

    // The ObjectName of a remote delegate MBean
    ObjectName delegateName = ObjectName.getInstance("JMImplementation:type=delegate");

    Object proxy = MBeanServerInvocationHandler.newProxyInstance(mbsc, delegateName, MBeanServerDelegateMBean.class, true);
    MBeanServerDelegateMBean delegateMBean = (MBeanServerDelegateMBean)proxy;

    // The MBeanServer ID
    String id = delegateMBean.getMBeanServerId();

Refer to the javadocs of the `javax.management.MBeanServerInvocationHandler` class for further details.

## Porting examples for `mx4j.util.StandardMBeanProxy`

The MX4J 1.x API of `mx4j.util.StandardMBeanProxy` is very similar to `javax.management.MBeanServerInvocationHandler`'s. Below are shown two code snippets that compare the old MX4J 1.x API with the new standard one. Note how only the line marked with (*) changes from the old version to the new one.

### Old MX4J 1.x proxy API

    // The ObjectName of the delegate MBean
    ObjectName delegateName = ObjectName.getInstance("JMImplementation:type=delegate");

    MBeanServer server = ...;

    Object proxy = StandardMBeanProxy.create(MBeanServerDelegateMBean.class, server, delegateName);  (*)
    MBeanServerDelegateMBean delegateMBean = (MBeanServerDelegateMBean)proxy;

    // The MBeanServer ID
    String id = delegateMBean.getMBeanServerId();

### Standard JMX 1.2 proxy API

    // The ObjectName of the delegate MBean
    ObjectName delegateName = ObjectName.getInstance("JMImplementation:type=delegate");

    MBeanServer server = ...;

    Object proxy = MBeanServerInvocationHandler.newProxyInstance(server, delegateName, MBeanServerDelegateMBean.class, true);
    MBeanServerDelegateMBean delegateMBean = (MBeanServerDelegateMBean)proxy;

    // The MBeanServer ID
    String id = delegateMBean.getMBeanServerId();