Summary
In a pair of recent blog post, Matt Hellige describes some issues he encountered when trying to use Hibernate in a Scala program. In the post, Hellige also shows how Scala language features helped him avoid global state within a Hibernate application.
Advertisement
One of the big benefits of the Scala language is that it works well with existing Java APIs, including popular enterprise APIs, such as Java EE and Hibernate. At one level, these APIs can simply be invoked from Scala code, and treated as black boxes. At a higher level, Scala can be leveraged to re-organize, and perhaps simplify, an enterprise Java application's codebase.
An area new Scala developers often find intriguing are language facilities that help avoid global application state: Some developers prefer to maintain as little global state as possible, and believe that less state leads to a more scalable and error-free application.
In a recent pair of blog post, Matt Hellige shows how some Scala language features help reduce global application state in a Hibernate application and, more generally, how to access Hibernate from Scala. The first part is available as Hibernate and Scala, while the sequel is at More Scala + Hibernate.
The main point of Hellige's post is that Scala and Hibernate work well together:
Generally, Hibernate and Scala work together very easily. But there are a couple of problems, and a bit of redemption at the end...
I'm trying pretty hard to avoid static references of any kind. To my mind, many of the most exciting advantages of Scala lie in this area. But Hibernate really doesn't like this. As far as I can tell, it's almost impossible to get any sort of non-static context into entities without resorting to ugly thread-local hacks, etc...
Hibernate apparently has no way of passing in an entity factory at query time. Of all the options I can set (UserType, Tuplizer, Instantiator...), every single one of them must be defined by class-name in an annotation. This means that Hibernate queries are required to be basically context-insensitive...
I can stick some context in a thread-local and use one of these options to instantiate my entities, but this seemed awfully ugly to me, and I'm really not sure whether it would be OK with Hibernate to make entities sensitive on context in this way. This assumption seems to be baked pretty deeply into the design...
Hellige then describes a solution to this problem, using Scala's implicit parameters:
[I did not] really need the context reference anyway, although I was afraid this would come back to haunt me. It came back quicker than I expected, in the form of a bunch of LazyInitializationExceptions. And in order to initialize my lazy collections, I need a reference to the Hibernate SessionFactory in the entity, but of course this is exactly what Hibernate didn't let me do in the first place...
Scala to the rescue. I've left my entities as stand-alone POJOs, and to capture the fact that certain methods are sensitive to a context, I've added an implicit parameter to those methods that need to perform lazy initialization:
There are only a few of these. In the client code, I can just declare my context reference implicit. I really only ever have one of them at a time, except in a few very special cases where I wouldn't want any implicit handling anyway. This works like a charm...
In any case, this shows how important it is to really pay attention to global resources, and how much clearer things can be when you make this stuff explicit. It also shows that Scala rules, and can be used with Hibernate very easily ...
To what extent do you think Scala can help simplify the codebase of a complex enterprise application? And what enterprise Java APIs have you tried with your Scala programs?