Skip to main content

Getting rid of that pesky MalformedObjectNameException

Posted by emcmanus on November 17, 2008 at 8:21 AM PST

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 throws
clause 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
static newObjectName 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:
.]

Related Topics >>

Comments

Possibly, if we were just looking at the ObjectName(String) constructor. But we also want to provide methods for the other constructors: ObjectName(String,Hashtable) and ObjectName(String,String,String). It was easier to reuse the valueOf pattern already established by many other classes in the Java SE platform, though I admit that ObjectName.valueOf("java.management.event", "type", "EventClientDelegate") is not very obvious.

May be ObjectName.fromString("javax.management.event:type=EventClientDelegate"); is better?

Ashvini: Or javaRanch...or forums.sun.com...

Ashvini: I recommend the site StackOverflow.com for that type of questions, you are much more likely to find someone with the time and inclination to help you there than when you are bothering individual developers.

hi eamonn, ashvini here...........eamonn i want to make a "jar file" as a "window service". inface i don't want to execute jar file by double click on it.......rather i want to make this "jar file" set as a window servive.........is this posible ? please help me eamonn it is urgent for me. i m using window xp. thank u.

Yes; I like your approach.

I was a bit laconic, but in your example I think the failure to validate user input is a programming error. Compare NumberFormatException, which is a runtime exception. If you read a string from the user then either you have to validate it before giving it to (e.g.) Integer.parseInt, or you have to catch NumberFormatException and do the right thing. By way of contrast, ConnectException clearly should be checked (and is), because you can't tell before connecting whether it will succeed. There's certainly a grey area between things that obviously should be runtime exceptions and things that obviously should be checked exceptions. In any case, if only for historical reasons, the JMX API will now give you the option to have incorrect ObjectNames generate either.

Minor nit: "Clearly a malformed ObjectName is a programming error." It's inconvenient, no doubt, but (as with MalformedURLException) what if the incoming String is user-supplied, not programmer-supplied? Then it's not a programming error, but a runtime error--and you probably *could* recover from it (just ask the user again).