Tuesday 4 September 2012

Deverbosing ScalaQuery session handling

Just started on a small project employing ScalaQuery and Unfiltered. They are great toolkits, but one thing have been bothering me about ScalaQuery. The typesafe handling of the sessions can make the code a little verbose.

Here's an example of the code before I started my refactorings:



The code receive a json-message through a http put operation on the path http://host/rest/products. It is read to the case class Product and we insert into into the database and returns a json-representation of the save Product.

My problem today starts at the ProductDb.database withSession in line 9. We bind the session implicitly in order to use it in the insertValue and the Query(...).where(...).list statements. The session parameter and implicit declaration in itself is two lines. Of course I could have explicitly specified the session at the insertValue and list method calls, but I kind of like the way it's hidden. When I've got lots of these cases the lack of DRY-ness really creeps out. I just want to hide the session handling completely.

Here is the code I want:



Now this looks a tad better. There are still issues, but the noise of the ScalaQuery session is completely gone. Since I have more of these match cases my code has been reduced substantially. Of course it doesn't work yet. The insertValue and the list methods both demands their implicit session.

Originally I tried to find a way to make it available by extending PartialFunction, but I found no way to make that work; maybe it's not possible. Instead I chose to extend the StorageService with a new trait ScalaQuerySession:



The trait make the session implicitly available for the ScalaQuery methods. Of course we need to  acquire the session before the StorageService-implementation is called and return it on the end.

We do this by implementing the intent method in a new trait ThreadMountedScalaQuerySession and make it call the StorageService intent method on the super object:
 

By binding the session variable to a DynamicVariable I guarantee that it will be separate for each thread in the pool that passes through the intent method.

Now we need only create the object StorageService like this to make it play:

new StorageService with ThreadMountedScalaQuerySession