Sep 17, 2010

int is not Assignable to Integer!

I've met a strange issue with play-morphia: Model.findById(theId) method failed while Model.filter("_id", theId) method works perfect. Digging into the code stack for while, I found a surprising behavior of java.lang.Class.isAssignableFrom(Class cls) method: If you pass a type of primitive type int/long etc (get from reflection of course) to it's corresponding object type class: Integer.class/Long.class, the method will return false! So while the following line of code compiles and runs perfect (because of autoboxing), the primitive type is NOT assignable to it's peer object type!

Integer i0 = 5; int i1 = i0;


Now the solution:

Object theId = play.data.binding.Binder.directBind(id.toString(), Model.Manager.factoryFor(clazz).keyType());


As you might noticed, the method is fairly poor in terms of performance because of lot of conversion and reflection operations. And here comes my suggestion to play-morphia user who use @Id to annotate user defined ID fields:

always override public static findById(Object id) method, that will do you big favor. The default findById method is provided in case you are too lazy to implement your own, and the result is it could be pretty slow.

For model classes relies on system generated ID, e.g. you have no field annotated with @Id, you don't need to worry about this. The enhancer will provide faster version of findById() method implementation for your model.

No comments: