ReactiveMongo/ReactiveMongo — pull request #98 by justwrote (2013-07-26 12:06:42+00:00)
Title: fixed `ClassCastException` when trying to cast `BSONNull` to `BSON*`

While profiling my app I saw a lot of exceptions thrown by reactivemongo, namely `DocumentKeyNotFound` and `ClassCastException` - actually I got **27500** `DocumentKeyNotFound`s and **10600** `ClassCastException`s in a very short period of time!

This pull request fixes the `ClassCastException`s. That one is kinda tricky because it is been swallowed by the `Try` and therefore never caused any visible harm. But since this exception is always thrown if a key is `null`, it actually has an impact (see above). For example: `LastError` always produces (at least?) one `ClassCastException`! For this fix I had to change more code than I wanted, but no public facing API has been touched. Well the returned Failure now contains a `DeserializationException` or a `ValueIsNull` exception instead of a `ClassCastException`.

Basically what this patch does is, return a Failure containing a `ValueIsNull` exception instead of throwing a `ClassCastException`. I created an `AllowNullable` trait which, if extended from, indicates that the `BSONReader` allow the value to be `BSONNull` or `BSONUndefined` and therefore does not throw a `DeserializationException`, but return a `None`. Now if a `BSONReader` cannot handle the `BSONValue` a `DeserializationException` will be thrown. All default `BSONReader` extend this trait, except `BSONBooleanLike`, because that one handles the `BSONNull` and `BSONUndefined` slightly different. Of course a few things in this patch could be further improved, but I didn't since that would break the public facing API!

What do you think?