codahale/dropwizard — pull request #368 by nicktelford (2013-07-23 17:05:59+00:00)
Title: More human configuration errors

Mistakes in run-time configuration currently produce errors that fail the "grokable by sleepy ops folks at 3am" test, so lets make them more understandable, and more helpful.

Note: This is a tracking issue for collaboration; the initial code is not ready for merging.

My first step is to break up `ConfigurationException` in to two sub-classes:

* `ConfigurationParsingException` - for errors parsing the YAML/JSON or binding it to the Configuration objects.
* `ConfigurationValidationException` - for errors validating the configuration against its constraints (existing `ConfigurationException`)

Next, we have to try to determine exactly which types of errors we can detect and handle them appropriately. Unfortunately, Jackson and SnakeYAML have rather stringly-typed Exceptions, so we can only take this so far. Nonetheless, my initial version detects:

* _Malformed YAML_ - If it can't get parsed in to a JsonToken, it's malformed. Something outstanding here is to (potentially) detect problems caused by using YAML constructs currently unsupported by Jackson (e.g. anchors/aliases).
* _Unrecognized field_ - Naming a field that doesn't exist on the target class. This is a common problem, often caused by typos. We can provide a list of suggestions based on the available target fields that Jackson is expecting, and the initial implementation will order this list by their Levenshtein distance from the field - seems like a good match for typos.
* _Incorrect type_ - If the value is of the wrong type and cannot be transparently marshalled by Jackson (e.g. attempting to assign a String to an Integer field; but not attempting to assign an Integer to a String field, which is marshallable).

In my initial implementation, all of the above errors will attempt to describe the location of the error first by the name of the field (if applicable), and then by the line/column in the file (indexed from 1:1).

Caveats:

* `commons-lang` has been added as a dependency, for the Levenshtein distance implementation. If we decide on a different algorithm to "fuzzy-match" suggestions, or we remove it entirely, we can drop this dependency.
* `JsonMappingException` is used to classify a wide range of problems in Jackson. Thankfully, most of these are more to do with the classes you're mapping to than the input you're mapping from, making it unlikely to bother sleepy ops-folk at 3am. Still, it would be nice to catch more of these problems.

I'd love to hear your thoughts on these, I'm thinking that when the server starts up, it should probably suppress the stack-trace when these `ConfigurationException`s get printed to the console, because it adds little value; the problem is in the input config file, not the code (or at least it should be!).