Unexpected JRuby overload resolution


Had an interesting bug using Hibernate from JRuby today. Totally unexpected actually. Interestingly, it actually exposed a problem with dynamic dispatch when going into a static language. To a degree I guess it’s about getting our overload resolution more correct, but it seems like a general rule will be hard.

Basically, my problem was this. I was calling update() on org.hibernate.Session. Now, I used the version that take a String with the entity name, and the actually entity as the other parameter. So the signature update(String, Object) was the one I was aiming for. Sadly, things failed, and kept on failing. And I really couldn’t figure out why. I got this lovely error message: org.hibernate.MappingException: Unknown entity: java.lang.String. This problem can show up from several different reasons, so Google didn’t help.

And then, after tracing the calls for a bit, I finally understood. It just so happens that the default implementation of Session (called org.hibernate.impl.SessionImpl), have a few public update methods that are not part of the Session interface. One of them has the signature update(Object, Serializable). The first parameter is the object to update, and the serializable parameter is the id. JRuby was very helpful in choosing to call that method instead of the update(String, Object) one, since my entity happened to be serializable. Of course, this meant that Hibernate tried to persist a String, instead of my real object, and this fails. The workaround was simple in this case: just use the single argument version of update, since the entity name can be figured out from the object.

But in general these kind of problems will show up sometimes – it’s the price you pay for having an extremely flexible dynamic programming language, interfacing with a statically typed language. But we can improve the overload resolution, and also make it possible to control it more explicitly. I’m currently thinking that it might be a good plan to have some debug flags that will give you some output about overload resolution and things like that too. What do you think? How would you solve this in JRuby?