You can't construct a JMX ObjectName without handling MalformedObjectNameException, which is a checked exception. Here's why that is a pain, how to relieve that pain, and what we're doing to make it less painful in the next version.

If you've done any programming at all with the JMX API, you'll have noticed that all of the ObjectName constructors, and all of the getInstance methods, are declared as throwing MalformedObjectNameException.

MalformedObjectNameException is a checked exception, which means that you have to either declare it in the throwsclause of your method, or catch it within the method. Having this exception be a checked one was a mistake, in the light of modern practice. For example, Effective Java 2 says: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors. Clearly a malformed ObjectName is a programming error.

When the ancestor of the JMX API was being designed about ten years ago this was all much less clear, and there were plenty of misleading precedents like MalformedURLException. If the API were being designed over again, MalformedObjectNameException would surely be a subclass of IllegalArgumentException, or perhaps the constructors would just throw IllegalArgumentException itself.

As it stands, this is painful, especially when you want to initialize a static final field to be an ObjectName. For example, you might want to write something like this:

    public interface EventClientDelegateMBean {
        public static final ObjectName OBJECT_NAME =
            new ObjectName("javax.management.event:type=EventClientDelegate");
        ...
    }
 

Alas, that doesn't compile, because field initializers can't throw checked exceptions. You might try to write this:

    public interface EventClientDelegateMBean {
        public static final ObjectName OBJECT_NAME;
        static {
            try {
                OBJECT_NAME =
                    new ObjectName("javax.management.event:type=EventClientDelegate");
            } catch (MalformedObjectNameException e) {
                throw new IllegalArgumentException(e);
            }
        }
        ...
    }
 

But that doesn't compile either, because interfaces can't have static initializers. Don't ask me why not.

So the solution today is to write a simple staticnewObjectName method that wraps the MalformedObjectNameException as an IllegalArgumentException, park it in some class, say Util, and call that every time you need to construct an ObjectName:

    public class Util {
        ...
        public static ObjectName newObjectName(String s) {
            try {
                return ObjectName.getInstance(s);
            } catch (MalformedObjectNameException e) {
                throw new IllegalArgumentException(e);
            }
        }
        ...
    }
 

Thus our troublesome interface becomes:

    public interface EventClientDelegateMBean {
        public static final ObjectName OBJECT_NAME =
            Util.newObjectName("javax.management.event:type=EventClientDelegate");
        ...
    }
 

That does compile, and it does work. (Although if the string really is incorrect you will get bashed with an ExceptionInInitializerError when you first reference the interface.)

My favourite tiny change in the JMX 2.0 API is that we do now provide standard methods to do this, so you no longer need to define them. The hardest part was to decide what to call them! As of JDK 7, you can write:

    public interface EventClientDelegateMBean {
        public static final ObjectName OBJECT_NAME =
            ObjectName.valueOf("javax.management.event:type=EventClientDelegate");
        ...
    }
 

[Tags: jmx java.]