Since going live with XP-Dev.com a few months ago, there has been a nasty little bug that I’ve been trying to chase down where a weird exception is thrown in some obscure situations. When I say “weird”, I mean “I look at the code and keep saying to myself: this exception can’t possibly be thrown here”. Now, the exception is very domain specific and its almost pointless for me to attempt describing it here, as that will take a few posts, rather than just the one.
In a nutshell, a user could login to XP-Dev.com using valid username and password credentials, but then found that he/she could not perform any tasks. It turns out that this only happens if a user logs in using a slightly different case for his/her username. For e.g. When user ‘developer‘ logs in using ‘Developer‘, he’ll basically hit this bug.
The problem is two fold:
First, MySQL stores varchar columns as case insensitive. So, when you run a SQL query like:
select * from Users where username='Developer'
MySQL will return the rows with username ‘developer’.
This is not a problem per-se, as I’ve found this design feature pretty useful when attempting to do web oriented work in the past. The web in general is case insensitive, and system facing the web should reflect that. There is no difference between XP-Dev.com and xp-dev.com.
So, from this perspective, its not really a security bug as well, as you can’t really register the user ‘Developer’ anyway and attemp to ’steal’ the other user.
Here comes the annoying second part of this fiasco.
I use Hibernate as a Object Relationship Mapper/Persistence Layer on the current version of XP-Dev.com. Carrying on with the MySQL example above, pulling out a User object from the Users table using Hibernate can be done as follows:
User user = (User) org.hibernate.Session.get(User.class,
"Developer")
The problem is that the User object returned will have the member ‘username’ set to ‘Developer’, rather than ‘developer’ as it is on the database. The object that Hibernate returns to you does not reflect the database state at all.
Coming back to the bug: Whenever a user logs in, I keep his username in memory attached to his session on the server-side, and refetch a fresh new User object on every HTTP request. The problem was that performing any tasks failed because it relied on strong Foreign Keys on the database tables. For e.g. if user ‘developer’ had 3 repositories, and logs in using ‘Developer’, I will refetch ‘Developer’ using Hibernate and get the username ‘Developer’ back, rather than ‘developer’. The user ‘Developer’ does not have any repositories and the permissions layer that I wrote (which is case sensitive) will throw a nasty exception when user ‘Developer’ tries to access repositories for the user ‘developer’. The permissions layer should be case sensitive as it’s a very critical part of the architecture and should be as restrictive as possible.
It’s nasty the way Hibernate does not return the exactly values back on the data object as it is on the database. The work-around is to use something like below:
org.hibernate.Session.createQuery("from User where username = ?")
.setParameter(0, "Developer")
.list()
Magically, Hibernate DOES return a User object with username set to ‘developer’. This approach has an extra overhead of creating a list on every call, but I suppose I’ll have to live with that for now.
On the new version of XP-Dev.com, I got rid of Hibernate and Wicket. I’ve had growing pains with Wicket as well, but that’s a rant for another blog post. Hibernate is just too bloated, and I can’t afford the performance overhead.


Posts RSS Feed
[...] If you’re finding some weirdness around Hibernate, MySQL and case sensitivity, do have a look at by past blog about it. [...]