Descriptive Exceptions

April 27th, 2009

The exceptions lecture of the semester is one of the trickier ones I deal with. Part of the issue is that I try to cram it into a single class, a strategy that has backfired on me twice now. Another difficulty is the fact that while there is quite a bit of technical knowledge as far as throwing and catching exceptions, I could easily spend double that time covering design and best practices.

I took a bug today that covers the error messages shown to a user when they input an invalid channel name. Currently, we simply say “Invalid channel name” without any indication of why… was it too short, did it contain invalid characters, was it already in use, etc. Our name validation is correct, but from a user experience stand point, it could use a little love (this was exacerbated by the multi-org addition where a channel name could be taken without you being able to see that data otherwise).

There are a number of different validations we run against the name. A good sampling of them is found in the following snippet:

1
2
3
4
5
if (cname == null || 
    !Pattern.compile(CHANNEL_NAME_REGEX).matcher(cname).find() ||
    cname.length() < 6) {
        throw new InvalidChannelNameException();
    }

Again, the logic is fine. Any of the circumstances in the if clause represent an invalid name. But now we have the need to carry more information to better indicate why it failed.

I started by editing the exception class itself. The constructor now accepts two parameters. The first is the channel name; if we’re saying the exception represents an invalid channel name then it makes sense it should indicate exactly what was invalid. This also saves the UI some work in remembering what was specified that caused the error.

The second is an enum (defined as an inner class of the exception class itself) that describes the reason for the failure. The enum (currently – I’m kinda writing this as I work on it) looks like the following:

1
2
3
4
5
6
public enum Reason {
    REGEX_FAILS,
    TOO_SHORT,
    IS_MISSING,
    NAME_IN_USE
}

I’m a big fan of the enum for something like this. It’s clunky to make subclasses of InvalidChannelNameException just to indicate the different possible reasons for failure, and frankly a series of instanceof checks to later use that information would just be ugly. A similar if/else structure would be needed if I used a series of String constants stored in the exception’s message attribute.

Some camps would argue against the inner enum (is that the way to say an enum defined as an inner class?). Their reasons would center around the usage syntax. I actually feel the opposite way; the syntax I have to use since it’s defined as an inner enum reads really well in my opinion:

1
2
3
4
if (cname == null) {
    throw new InvalidChannelNameException(cname,
        InvalidChannelNameException.Reason.IS_MISSING);
}

Also realize that using an enum lets IntelliJ only show me the enum values when I get to that parameter. There’s no need to hunt around for the possible constants.

Once the extra information was in there, it was just a matter of getting the UI to display a custom message based on what actually happened, cleanly using a switch statement since I’m using enums.

1
2
3
4
5
6
7
8
9
10
11
12
catch (InvalidChannelNameException ferengi) {
    switch (ferengi.getReason()) {
        case IS_MISSING:
            errors.add(ActionMessages.GLOBAL_MESSAGE,
              new ActionMessage("edit.channel.invalidchannelname.missing"));
            break;
 
        case REGEX_FAILS:
            errors.add(ActionMessages.GLOBAL_MESSAGE,
              new ActionMessage("edit.channel.invalidchannelname.regex"));
            break;
[snip]

Again, IntelliJ can auto-complete here, this time only showing the possible values (i.e. the enum values) each time I start a new case clause.

Map Lookups

April 21st, 2009

Throughout the semester I have been enforcing the importance of overriding the equals/hashCode methods where applicable (i.e. domain objects). I just fixed a bug in Spacewalk that was caused by not implementing them, so I figured the real world example might help to illustrate my point.

For the record (not that I imagine people will find this all that interesting), the Bugzilla bug can be found here and the Spacewalk commit here. I’m sure everyone is just racing to read those over now.

I’ll try to keep the setup short. We have a map of capabilities and the key is an architecture type (ArchType). The ArchType class, however, didn’t implement equals/hashCode. So when the map was queried by the architecture type, it used the object reference as the key comparison.

There are some more details I’m not going to fully explain. In short, they are all pulled from the database but the instances themselves are potentially cached. So on the first request to the map, the queried type and the the type inside of the map happened to be the same object, so it pulled the result successfully. On subsequent tries however, the caching ended up causing the two instances to be different (despite containing the same data). In those cases, the results came back as null and we saw a really weird, almost non-deterministic error.

The fix was simple, override equals/hashCode in ArchType to use the data (in this case, the id) rather than allow the default comparison by object reference. So no matter how many times we recreate the ArchType objects from the database, it won’t be a problem since the key lookup will use the data inside of the objects, not their references.

Overriding equals and hashCode. Learn it. Live it. Love it.

Triple-quoted Strings

April 20th, 2009

In Python, if you use three double quotes (I know, that just looks weird when written) you don’t have to escape newlines. For instance, I’m working with a query (it’s much longer, I cut out the middle):

1
2
3
4
5
6
7
8
9
10
11
12
_packageStatement_remove = """
    select distinct
        pn.name name,
        pe.epoch epoch,
        pe.version version,
        pe.release release,
        pa.label  arch
    from rhnActionPackage ap,
        rhnPackage p,
[snip]
        and ap.package_arch_id = pa.id(+)
        and p.id = cp.package_id"""

In Java, that’d be a lot uglier. I have no desire to convert the entire query, but it’d look something like:

1
2
3
4
5
6
7
8
String query = 
"select distinct " + 
"        pn.name name, " +
"        pe.epoch epoch, " +
"        pe.version version, " +
"        pe.release release, " +
"        pa.label  arch " +
[snip]

Also keep in mind that in most cases, you have to be careful to add the space after each line within the quotes. Otherwise, when Java munges this all into a single constant, you’ll get two words merged into one:

1
2
String foo = "golden" +
"monkey";

The contents of foo is simply "goldenmonkey" without any spaces. Needless to say, that can really screw with your query.

Score one for Python. :)

Java Collections

April 13th, 2009

We just finished covering data types in class, including a pretty in depth look at the Java Collections libraries. The book covered the basics, but there are a few concepts I wanted to touch on that may be helpful in the upcoming project.

Java can automatically sort collections for you, provided you tell it how to. There are two ways to do this:

Comparable
Unlike equals and toString, which are provide by the Object superclass, the compareTo method is optional. Classes may choose to provide a description of how to compare instances of that class by implementing the Comparable interface. That interface contains a single method compareTo(T o) that provides a numeric result indicating if the object on which it is called is less than (result is less than zero), greater than (result is greater than zero), or equal to (result is zero) the object passed into the parameter.

For instance, for a rather generic Person class, the following implementation would provide sorting based on the person’s last name:

1
2
3
4
5
6
7
class Person implements Comparable&lt;Person&gt; {
  // Attributes
 
  public int compareTo(Person other) {
    return this.lastName.compareTo(other.lastName);
  }
}

Note the use of generics in the implements clause. This lets us write the compareTo method to explicitly take a Person instance rather than the generic Object, saving us from having to deal with the casting. Also note that in many cases, the compareTo method (like equals and hashCode) will often chain down to a simpler data type’s Comparable implementation, in this case String.

One benefit of this approach is that the class is self-describing. In addition to describing how to compare two instances for equality, the class also describes how to order instances of the class. The drawback to this inclusion is that it’s a single method of sorting. There isn’t a really clean way in this approach to distinguish if the person objects should be sorted by last name or, say, social security number. That’s where the second approach comes in.

Comparator
Similar to Comparable, the Comparator interface contains a single method that returns a numeric result. However, a comparator is meant to be a separate class from the one being compared (whereas the Comparable interface is meant to be used by the class being compared). As such, the compareTo method takes two arguments, meant to be the two objects being compared.

For instance, we could write the same ordering functionality as above in an external Comparator implementation:

1
2
3
4
5
class PersonComparator implements Comparator&lt;Person&gt; {
  public int compareTo(Person p1, Person p2) {
    return p1.getLastName().compareTo(p2.getLastName());
  }
}

Again, the use of generics allows us to write the compareTo signature using specific classes rather than just Object references. Note that this implementation is outside the Person class and thus doesn’t have the same access to private variables that the Comparable implementation uses. This shouldn’t be a problem, but it’s worth noting.

There are a number of conventions in the collections APIs to make life easier. For instance, almost all collection classes contain a constructor that takes a Collection as a parameter. That constructor will populate the new collection with the entities in the parameter. For instance:

1
List newList = new ArrayList(oldList);

Keep in mind this doesn’t do a deep copy of each element in the old list. It simply adds all of the object references in the old list to the new one. In other words, the first item in each of these two lists will refer to the same object. However, they are different lists and one can be manipulated without affecting the order or contents of the other.

This is often a good approach when returning collections from a method call. It can prevent the caller from mangling a collection internal to another class, as well as prevent the caller from holding an open iteration of the collection, preventing the original owner of the collection from making any changes to its contents.

This is also a way to jump between different collection types. For instance, if you have a list that may contain duplicate items that you want removed, you can easily throw the items of the list into a set, which will automatically remove the duplicates in the process:

1
2
List hasDups; // Initialized elsewhere
Set noDups = new HashSet(hasDups);

The same functionality can often be achieved through an addAll(Collection c) method that many collections provide. This method will do exactly that: add all elements from one collection to another:

1
2
3
List oldList; // Initialized elsewhere
List newList = new ArrayList();
newList.addAll(oldList);

There are other handy features, such as the ability to make a collection thread-safe or constants for empty collections, that I won’t go into just yet. This has already been more of a wall of text than I like to make these sorts of entries. :)

Fun With Overloading

February 21st, 2009

One of my students ran into an interesting issue with autoboxing and the List APIs. Before I blog on that example, I wanted to start with something more generic to help flush out overloading further than I had time for in class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    public static void main(String[] args) {
        String s = new String();
        Object o = new String();
 
        wombat(s);
        wombat(o);
    }
 
    static void wombat(Object o) {
        System.out.println("Object");
    }
 
    static void wombat(String s) {
        System.out.println("String");
    }

What will print when the above is executed? More importantly, why?

The first call, “wombat(s)”, should be pretty simple. There is a method definition that takes a String, so it’s not a huge surprise that “String” is printed out (one could argue that this call would also fulfil the requirements to call the Object version of wombat, which will be address later in this entry).

But what about the call to “wombat(o)”? There are two options:

  • The object type inside of o will be checked, which in this case is String, and execute the corresponding version and printing “String”
  • The variable type of o will be checked and execute that implementation, printing “Object”

The result is the second option; the chosen method is determined by the type of the variable, not its contents. But what happens when we take the variable out of the picture?

1
2
wombat(new Object());
wombat(new String());

The first example is trivial; there is only one candidate that could accept an Object. The latter, however, could technically qualify for either implementation of wombat. In that case, the most specific implementation of wombat will be run. In this case, String is more specific than Object (in other words, it is a subclass of Object), so the result will print “String”.

Now consider a slightly more complicated example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public static void main(String[] args) {
        wombat(null);
    }
 
    static void wombat(Throwable o) {
        System.out.println("Throwable");
    }
 
    static void wombat(Error e) {
        System.out.println("Error");
    }
    static void wombat(Exception e) {
        System.out.println("Exception");
    }

The change here is that there are two overloaded methods that accept subclasses of the third (remember Exception and Error are both direct subclasses of Throwable).

What prints in this case, where simply “null” is passed to wombat? The “more specific” argument can’t be applied, since both Error and Exception are more specific than Throwable, however they are unrelated to each other.

What actually happens is a compile time error, indicating there is an “Ambiguous method call”. In other words, there is no way to deterministically decide which implementation of wombat to call (the Error version or the Exception version).

One last detail, such a situation doesn’t prevent you entirely of passing null to these methods. You simply need to indicate which implementation you want to run:

1
wombat( (Exception) null);

It may seem weird to cast null to something, but it serves a way to disambiguate the call, indicating a particular overloaded implementation to execute.

Super Method Calls

February 11th, 2009

I really wanted to start this entry off with some sort of superman reference or joke, but everything I came up with was an order of magnitude past lame.

The notation of using super to call a method came up last night in class. Ok, technically it first showed up on a quiz, an unfortunate aspect my students are hopefully still not mad at me for (in my defense, I gave them all credit for that question when I realized my mistake). My explanation largely centered around a code sample in class that I wanted to make sure I cleaned up and made available.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Alpha {
    public void foo() {
        System.out.println("Alpha");
    }
}
class Beta extends Alpha {
    public void foo() {
        System.out.println("Beta");
    }
    public void printFoos() {
        foo();
        this.foo();
        super.foo();
    }
}

Assuming we created a Beta instance and called printFoos(), the following would be output::

1
2
3
Beta
Beta
Alpha

For the first two calls in printFoos(), the overridden foo() method in Beta is executed. Remember that the super keyword says to look to the parent class for the body of the method. In this case, we’re asking that Alpha’s implementation of foo() be called regardless of the fact that Beta overrides it.

Final Variables

February 10th, 2009

A question came up a few days ago regarding a change I made to the MessageQueue class in Spacewalk. I made the ACTIONS variable (of type Map) final. The reasons I did so refer to its use in a synchronized block, but that’s not the purpose of this blog.

Rather, this example brings up a good distinction I wish I had made in class. What exactly does it mean when a variable is defined as final?

A final variable means the variable can not be assigned a new value. When dealing with primitives, this is pretty simple: the variable can’t take on a different value.

1
private final int NUMBER = 5;

The variable NUMBER (the accepted convention for final variables is all caps) will never have a value other than 5. Nice and straightforward.

What about for objects? Is the following legal?

1
2
private final Person PERSON = new Person("Jason");
PERSON.setName("Jay");

Assuming the setName method doesn’t do anything weird, yes, the above is perfectly legal.

A final variable for an object refers to the object reference. In the above, the PERSON variable can never be pointed to a different Person instance (nor can it be set to null). Methods can still be executed on the object, some of which may change the state of the object. But the reference itself cannot be changed to refer to a different object.

In the Spacewalk example, we’re using a Map (more generally, a Collection). We can’t change the object referenced by ACTIONS, but we are free to manipulate the contents of the collection as necessary.

As a small side point, there is a way to lock the contents of a Collection. The Collections class (note the pluralization) contains a number of static methods for wrapping collections with new functionality. In this case, if we wanted to prevent the contents of the map from changing, we could have done something like:

1
2
3
Map alreadyPopulatedMap; // populated previously
Map neverChangeMe =
    <code></code>Collections.unmodifiableMap(alreadyPopulatedMap);