The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


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 >> Open JDK      
Comments
Comments are listed in date ascending order (oldest first)

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).

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.

Yes; I like your approach.

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.

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.

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

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

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.