Showing posts with label shapeless. Show all posts
Showing posts with label shapeless. Show all posts

Saturday, June 16, 2012

Type-safed Composable Interceptors in Play2.0

This post is just a quick follow-up of this post, which introduced my latest utility for Play 2.0.
I recommend you to have a quick overview on it.


Type-safe composition of interceptors : Premises


Briefly, we'll just see how the first "future work" as been addressed. That is, avoid boilerplate for interceptors composition.

A quick recall, when we had to compose such Interceptors we had to take care our-selves of the validation results and the combined result (tuple or whatever).
The real problem that is under the sea here, is that tuples are not so easily generalizable (no append method, roughly).

So I decided to use the Shapeless library (thx to @milessabin).

Shapeless has an amazing core structure that enables type-and-value chaining (somehow). The HList type is a kind of list but each element is one value and one type. For instance, it has the head value and the Head type on top of the Stack. Here is the kind of stuffs that we can do with Shapeless:

val | = false
val thisIsNotAPipe = "this" :: 15 :: false :: "a" :: | :: HNil


> thisIsNotAPipe: shapeless.::[java.lang.String,shapeless.::[Int,shapeless.::[Boolean,shapeless.::[java.lang.String,shapeless.::[Boolean,shapeless.HNil]]]]] = this :: 15 :: false :: a :: false :: HNil

>Type-safe list of stuffs<

In Action...


While trying to use HList generically I had problem with the implicits that are needed to prepend two lists, but StackOverflow has brought me the answer here.
I'm not gonna tackle here how I did, by I'll demonstrate what is now possible with the new composition functionalities added to Interceptors.

First of all, I had to declare an Interceptor for HList and the related implicit conversion. After what, I added three methods:


  • hlist this method on Intercept is able to convert a classical one to a HList one
  • ~::~ this one is available to compose any interceptors that is not defined using HList with an HList one. It will create a new Interceptor with the new composed HList as result
  • ~:::~ this one enable to compose two Interceptor defined with HList, the results will be the concatanation of the two HList.
Note: concatanation of HLists preserves the type sequence, actually we can see that as if it concat two lists of values and two list of types.

Let's see how we can deal with them:

Easy no? Combine interceptors and use compile-time type-checking to validate the required kinds of items.

Without boilerplate



Friday, June 15, 2012

An Attempt of Play2.0 Action Interceptor

In this post, I'm gonna introduce a piece of code that I laid with the help of two stuffs.
The Security object provided by Play 2.0 out of the box and somehow the Secured one provided by the TypeSafe's plugin util.

The idea here is to leverage the actual functionality wich only enables to provide one Option[String] as result.
What I wanted at first is to satisfy my use case, which is : a lot of actions are secured and I need a username and its id. Where id is an Int.

Here we are, the actual Security and Secured don't permit me to have several extracted values, or to have an Int.

That's why I created this project : https://github.com/andypetrella/steal-play2.


Steal help



The idea is to enable any actions to be preceded by some interceptors that are stealing values either from the request, the cache, the database (or...) and set them as the parameters of a closure that outputs an Action.

But we must also care of the cases when something went wrong during the stealing.


Interceptor



This trait is the core of the solution, it defines:

  • the stealing operation: a function that takes (currently) the request and outputs a validated output (Validation from ScalaZ)
  • the err callback:  a function that takes the request and the failure (when computing the stolen value) and outputs a valid Result to send back to the client.
  • apply: a closure that takes the result (not a Validation) and output an Action.
At this stage and looking at the code below (I've omitted the apply impl because not important here -- just wrapping and unwrapping), it's fairly simple to know how to define such interceptor.

I provided the simplest implementation of this trait that is a case class extending it by defining the two callbacks as fields. Like so:

So now we're armed to do stuff like that:

Where we defined two interceptors that takes a string from the cache and an Int form the cache also (just an illustration). After what, we combined them in an another Intercept using a for-comprehension.

So far, so good, now how to use such combined interceptor within an Action. Check this out:

Monoid

With the help of Monoid (from ScalaZ) and if the case permits it, I defined an implementation of Interceptor that append the successive results one after the another. Reducing and simplifying the composition. Like so:

Note: we used the classical case class. Thanks to an implicit def that wraps the Intercept into the Monoid implementation, using the TypeClass bound declaration. see

What will come next

The next step I've already started is to try using Shapeless to avoid the composition boilerplate. Things are ongoing. Stay tune for that.

One step further, I'll add another parameter to the steal callback, which will be the optional result of the previous computations of other interceptors. That in order to combine them at the function and result levels.

And probably, add all boileplate my self that creates the tuples out-of-th-box in the compose function.


That's all folks!