I was just stood in my kitchen washing the dishes and reflecting on the past four years coding Scala and being heavily involved with the community; seeing it grow and enjoying the relationships that have been forged through that time. I have learnt more during my time in this community than probably any other I have ever been involved with.

To date, I am yet to encounter someone in the Scala and Lift communities who isn’t above average intellectually and super friendly. Pretty much everyone, without exception, is very clever and this generates amazingly stimulating discussions, no matter what the topic. I have been exceedingly fortunate to work with the likes of David, Marius, Jonas and Viktor and have them provoke new ideas and create shared experiences with as we challenge our own thinking and continue to improve both Lift and Akka.

Finally, I have been lucky enough to forge some great friendships that have ultimately been very rewarding. Moreover, it makes me wonder what my life might be like had I never gotten involved with Lift? The likelihood of making those same friendships would be slim, and I doubt I would be a published author either!

All this makes me conclude that Scala has had a very, very positive impact on my life as a whole. So, if you are feeling under the weather? Perhaps you should take some Scala ;-)

I was recently asked how to stop Lift’s Mapper from flattening the naming of columns during its “schemification” process. Well, there is a little known configuration object in the net.liftweb.mapper package called MapperRules.

MapperRules contains a whole bunch of stuff that you can use to control the way that Mapper names stuff that it creates and how it will try and inspect your database. If you prefer (like me) to have columns and tables like first_name rather than firstname, then add the following to Boot.scala:



class Boot {
  def boot {
    ...
    MapperRules.tableName =  (_,name) => StringHelpers.snakify(name)
    MapperRules.columnName = (_,name) => StringHelpers.snakify(name)
    ...  
  } 
}

Thats it!

So I have been pretty lax of late with keeping this blog up to date. There is a very good reason for that, and that is I am currently working on a book about Lift – If you haven’t heard, Lift In Action will be available on Manning Publications in Q1 of 2011 and is currently available as an eBook via the Manning website. Its generally eating a lot of my time right now so I haven’t had a chance to post about all the cool new stuff that is making its way into Lift every week – hopefully I will soon get time to write about the awesome new Record persistence system that we are all very excited about as we are currently integrating the extremely awesome Squeryl as a backend for dealing with RDBMS.

By all means, go and checkout the book and let me know what you think as it develops in the author online forums and I will get back to you ASAP. Enjoy!

Continuing with my series of articles about Lift, here’s another hidden gem that not many people know about. Lift can automatically validate your markup so that any validation errors or warnings are high lighted to you as part of the development process. Pretty neat. Here’s what you need to do to enable it:

Configure Boot


  class Boot {
    def boot {
    ......   
      LiftRules.xhtmlValidator = Full(StrictXHTML1_0Validator)
    }
  }

Where of course you can replace StrictXHTML1_0Validator with any one of:


  TransitionalXHTML1_0Validator
  StrictXHTML1_0Validator

  // or subclass:
  GenericValidtor
  // to provide your own custom implementation 

Find this and more great tips in my forthcoming book, Lift in Action

Enjoy!

So im at Scala Days 2010 right now, and during dinner last night their seemed to be some misconceptions about what Lift’s Box[T] monad actually does and how it differs from Option[T]. Now, im not computer scientist, so im not going to be discussing the algebraic validity of Box[T], not shall I be calling it a “tri state option”...

Why bother boxing values?

Have you ever thrown a NullPointerException? Frankly, I don’t know any developers that haven’t had this happen to them at some point because of something they hadn’t considered during development… in short, a NPE is something that was caused by an unexpected series of events causing your application to explode in a variety of ways. This is not good.

Consider a scenario where I want to do something with a value returned from a database; its not uncommon to see programs where one assumes the database query got the correct result, then do some operation on it. Well, news flash, its highly plausible that the database query might not go as you had expected and return some other result….

...Boxes to the rescue! As the name might suggest, a Box is something that you can put stuff in, take stuff out of, and also find empty. Much as you would do with a real life box. Lets illustrate with a simple example:


import net.liftweb.common.{Box,Full,Empty,Failure,ParamFailure}

scala> val x: Box[String] = Empty
x: net.liftweb.common.Box[String] = Empty

scala> val y = Full("Thing")
y: net.liftweb.common.Full[java.lang.String] = Full(Thing)

We have two simple examples here that assign new boxes to vals, and as you can see, x is assigned as a Box[String], yet its actual value is Empty which is a sub type of Box. The second assignment to y has the same type signature, but this time it is “Full” with a value; in this instance “Thing”.

What about exceptions?

Lift has a helper method in net.liftweb.util.Helpers called “tryo” that is a specilized control structure so that if you can execute code in a block that returns a Box’ed value irrespective of what you did in the block and how its execution went. If your using Lift webkit then you already have access to these utility methods, however if you just want to stay light and are not using webkit then the definition of tryo looks like:


  def tryo[T](
      ignore: List[Class[_]], 
      onError: Box[Throwable => Unit])
      (f: => T): Box[T] = {
    try {
      Full(f)
    } catch {
      case c if ignore.exists(_.isAssignableFrom(c.getClass)) => 
        onError.foreach(_(c)); Empty
      case c if (ignore == null || ignore.isEmpty) => 
        onError.foreach(_(c)); Failure(c.getMessage, Full(c), Empty)
    }
  }

There are some other overloads for syntax sugar, but essentially it lets you do:


  tryo {
    // your code here
  }

So lets assume we had some remote API to invoke, and it could not connect, or blow up in some way you hadn’t planned, what would happy given a tryo block / wrap? Consider:


scala> tryo("www".toInt) 
res4: net.liftweb.common.Box[Int] = Failure(
  For input string: "www",
  Full(java.lang.NumberFormatException: For input string: "www"),
  Empty)

As “www” isnt an Int, it unsurprisingly cannot be converted to one, so it blows up with java.lang.NumberFormatException. However, using tryo (boxed values) we are left with a special Box subtype called Failure. This lets us handle the error in a concise way rather than needing to check all the possible outcomes or worry about some awful try-catch block.


scala> tryo("www".toInt) openOr 1234                       
res7: Int = 1234

scala> tryo("www".toInt).map(_.toString).openOr("Invalid Strings")
res8: java.lang.String = Invalid Strings

scala> for(x <- tryo("www".toInt)) yield x
res11: net.liftweb.common.Box[Int] = Failure(
  For input string: "www",
  Full(java.lang.NumberFormatException: For input string: "www"),
  Empty)

So you can see there several ways to interact with Box, Full and Failure subtypes, providing defaults inline and mapping the results etc.

Handling empty values?

But what if we need more information or the value we are looking for isnt a failure, its just the value is Empty (or None for scala Option)? For example, lets assume we were looking for a request parameter to a REST API or similar… rather than throwing a HTTP 500 error with no reason, it would be nice to give the user a much more granular reason. Consider getting a request paramater using Lift’s S.param method.


scala> S.param("id") ?~ "You must supply an ID parameter" 
res17: net.liftweb.common.Failure = 
  Failure(You must supply an ID parameter,Empty,Empty)

The ?~ method allows you to supply an error message and convert the Empty into a Failure. This is an incredibly helpful paradigm when used with for comprehensions.

Chaining boxes

Lets assume that we have a situation where by we could recive a value from several places, or we need to “fall through” to a specific result based on trying several values in a sequence… Box supports this by way of the “or” operand.



scala> val x = Empty
x: net.liftweb.common.Empty.type = Empty

scala> val y = tryo("qqq".toInt) 
y: net.liftweb.common.Box[Int] = 
  Failure(For input string: "qqq",
  Full(java.lang.NumberFormatException: For input string: "qqq"),
  Empty)

scala> x or y or Full("Default")
res18: net.liftweb.common.Box[Any] = Full(Default)

Box has a bunch of features I haven’t covered here, but I hope this helps you understand the rational of this specialised option-esq type.

Note: REST and many other topics discussed within my upcomming book Lift in Action, more information will shortly be published on manning.com

This one is hot off the press – Lift 2.0-SNAPSHOT now has the ability to do notification style service workflows – essentially comet for REST.

So how does this work? Well, following on from my other post on REST services with Lift we are still using a DispatchPF to setup the service, but we now use the statefull dispatcher LiftRules.dispatch rather than statelessDispatchTable and from inside our resource definition we call S.respondAsync. Here’s a complete example:


  LiftRules.dispatch.append {
    case Req("example" :: rest, _, _) => {
      S.respondAsync {
        Thread.sleep(20000) // some computation here
        Full(XmlResponse(<async>response</async>))
      }
    }
  }

The call to S.respondAsync executes the function you pass to it on another thread and if the container you are using supports suspend / resume idiom Lift will pass control to the container and no threads are blocked during its execution; just return a Box[LiftResponse] like normal and Lift will handle notification to listening clients. Sweet.

Note: This subject is discussed in much greater detail within my upcomming book Lift in Action, more information will shortly be published on manning.com

The Goal

So what are we actually trying to achieve here? We’ll use the twitter.com API as an example as its a good illustration in this instance. Consider the following URLs:

http://api.twitter.com/users/timperrett.xml

and

http://api.twitter.com/users/timperrett.json

Its the exact same content, but just presented in different formats. This is very nice, and also very helpful as often you might be in a situation where you need to syndicate a single API from multiple devices or platforms where toolkits may be limited. For example, working with JSON is a lot easier from Java script than it is XML (the latter is of course possible its just more verbose). In the examples above, Twitter are using the format component of the URL following the ”.” to determine the content type the user wants – this is of course one route, and some services may want to add the additional stipulation of a specified accepts and content-type headers in the requests so the server is sure its serving the right content.

The interesting problem here is that if you have the same content, you really only want one point of access for the logic. You simply dont want to be maintaining two set of logic – only the actual code that handles differences in presentation should alter between calls right?

Implementation Pattern

Typically, when I want to create web services in my Lift application I break out my dispatchers into separate objects related to their concerns. This way it keeps things nice and tidy. So, in our example, i’ll be wiring up the following services:


  LiftRules.statelessDispatchTable.append {
    case Req("apps" :: Nil, "json", GetRequest) => 
      ApplicationServices.json.list
    case Req("apps" :: Nil, "xml", GetRequest) => 
      ApplicationServices.xml.list
  }

For those not familiar with Lift’s dispatching mechanism this will expose the following URLs:

  • /apps.json
  • /apps.xml

All pretty simple so far. As you can see from the code listing above, I have broken my application services out into a singleton object called ApplicationServices which has fields for each content type im going to be presenting. Without further ado lets take a look at the definition of the apps listing service:


object ApplicationServices extends Loggable {
  .....
  protected def _list(mediaAction: List[String] => LiftResponse) =
    () => tryo(mediaAction(Applications.list.map(_.name)))
  .....
}

Ok so this is pretty cool. Im using function passing to let each subsequent definition define how it builds the LiftResponse sub-type; in this instance that’ll be JsonResponse for JSON and XmlResponse for XML.

JSON Listing


def list = _list((apps) => 
  JsonResponse(compact(JsonAST.render(("applications" -> apps)))))

XML Listing


def list = _list((apps) => XmlResponse({
  <applications>
    {apps.map(a => <application name={a} />)}
  </applications>
}))

So you can see that each presentation version is only dealing with how it needs to create the response… its not re-computing the list of applications or such.

Syntax Sugar

Within the overall definition I define the formats as inner-objects and assign them to public fields in order to achieve the nice ApplicationServices.xml.list notation:


object ApplicationServices extends Loggable {
  val json = Json
  val xml = Xml

  protected def _list(mediaAction: List[String] => LiftResponse) =
    () => tryo(mediaAction(Applications.list.map(_.name)))

  object Json {
    // definitions here
  }

  object Xml {
    // definitions here
  }
}

Round Up

Thats pretty much all there is too it. You can leverage Scala’s extremely powerful features to create your web services and keep code LOC to a minimum. Over and out.

In my continuing effort to improve the wider knowledge of Lift, here’s another great nugget that shows you how to provide a 404 handler powered from a Lift template


class Boot {
  def boot {
    // ...other stuff...

    LiftRules.uriNotFound.prepend(NamedPF("404handler"){
      case (req,failure) => 
       NotFoundAsTemplate(ParsePath(List("404"),"html",false,false))
    })

  }
}

And I have a 404.html file in the ./webapp/404.html with the contents:


<lift:surround with="default" at="content">
  <h2>Ooops!</h2>
  <p>Wow, we totally couldn't find your page. Sorry about that.</p>
</lift:surround>

Then whenever a user browses to a URL that is not supported by your application, you can give them a friendly (and nicely designed) webpage rather than some technical message about 404s.

Note: The only cavet is not to use the <lift:menu /> snippet within your 404 template because Lift is unable to calculate the SiteMap when its a URL that is not accounted for within that scheme.

UPDATE The above note is now redundant because of commit by Marius on issue 376

Recently, Marius added an abstraction layer within Lift so that we could support different comet implementations over different servlet containers. Out of the box, we provide two both Jetty 6 and Jetty 7 APIs. This API is however not very well documented so I thought I would just write a short post on how to use it. In your Boot.scala file you need to put something like:



import net.liftweb.http._
import provider.servlet.containers.Jetty7AsyncProvider

class Boot {
  def boot {
    // ...other stuff here...

    LiftRules.servletAsyncProvider = (req) => 
        new Jetty7AsyncProvider(req)

  }
}

Thats pretty much all you need to do in order to swap comet implementations! If you want to use something else, like Resin etc, all you need to is write the correct provider and away you go.

Its quite often that I need to pass tokens between Scala (Java also) and .NET – this instantly provides a whole raft of issues because of how the algorithms are built under the hood in the respective platforms. This short post details how you can generate consistent base64 hashes over both platforms (this can be helpful for security purposes etc)

The Scala way:



  val input = "sample" 
  val encoding = "UTF-8" 

  base64Encode(
    hexDigest(
      input.getBytes(encoding)
    ).getBytes(encoding)
  )

The .NET way



  using System.Security.Cryptography;

  string input = "sample";

  SHA1CryptoServiceProvider shaHasher = 
       new SHA1CryptoServiceProvider();
  byte[] data = shaHasher.ComputeHash(
    Encoding.UTF8.GetBytes(input)
  );

  StringBuilder sBuilder = new StringBuilder();
  for (int i = 0; i < data.Length; i++){
    sBuilder.Append(data[i].ToString("x2"));
  }

  string hash = sBuilder.ToString();

  Convert.ToBase64String(
    Encoding.UTF8.GetBytes(hash)
  );

UPDATE After I posted this code origionally, it was pointed out that it would be good / helpful to show encryption as well as hashing; so here goes:

The Scala way:



  val key: Array[Byte] = "qwehfjgtufkgurifghfkdjfg".getBytes("UTF-8")
  tripleDESEncrypt("sample", key)

The .NET way:



  using System.Security.Cryptography;

  string key = "qwehfjgtufkgurifghfkdjfg";
  string toEnc = "sample";

  TripleDESCryptoServiceProvider DES = 
       new TripleDESCryptoServiceProvider();

  byte[] bytKey = Encoding.UTF8.GetBytes(key);

  DES.Mode = CipherMode.ECB;
  DES.Key = bytKey;
  DES.Padding = PaddingMode.PKCS7;

  ICryptoTransform DESEncrypt = DES.CreateEncryptor();

  byte[] buffer = Encoding.UTF8.GetBytes(toEnc);

  string base64string = Convert.ToBase64String(
    DESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length)
  );

  Response.Write(base64string);

Maybe this will help someone avoid the pain I have endured with this! lol.

Picture the scene: Im sat in my chair, working away and then I get a fairly crazed phone call from a co-worker in sales – he apparently has this stunning new idea about how to leverage twitter as a marketing platform…

As most of my readers are technical (yes, thats you there) I wont labour the marketing peice, but if your interested, David wrote a really nice article explaining his concept about what happens when social media meets cross-media; find it over here

A cunning scheme indeed

So, from the off, this was going to be an interesting campaign to put together because there were numerous issues, including:

  • Lots of concurrent (and asynchronous) read / write ops to Twitter API
  • Backend communication to XMPie cluster
  • Push production status back down to the browser
  • Downloading of avatar images automatically from twitter and insert into XMPie asset source
  • Doing any of this in the given time frame!?

This project was going to have a sizeable set of works attached no doubt to manage the interplay between XMPie systems and the Twitter API.

Technology Sandwich

To implement this campaign, I ended up using a whole bunch of different technologies… The implementing stack eventually ended up utilising the following:

  • Lift
  • Dispatch
  • Scala Actors
  • XMPie uProduce
  • XMPie ICP
  • Microsoft SQL Server

In earlier drafts of this article I tried to explain the interplay between components, but simply could not find a good way to articulate the meaning. To that end, I hope diagram gets the structure across sufficiently!:

As you can see – quite a number of software components here! I’ve been working with Scala and XMPie uProduce for quite a while now and have built up some very nice abstractions that completely hide calling of services under the hood.

This entire campaign was implemented based on top of ICP, using my Scala abstraction along with the awesome power of Scala Actors, scheduling and some generally very cool libraries like Dispatch

Questions

A few people asked me to write this post, but as im not sure what specifically you might have been interested in, if you want to know more about how its put together, what does what etc then I would gladly take questions! Just leave a comment at the bottom and i’ll get back to you…

So its that time again – another awesome Apple update to the best operating system in the world; for most, its a joyous time, one of new beginnings and wonderment…. for some, alas this is just an ideal as all there proprietary software comes crumbling down under a new kernel.

Friday was one of these momentous days, and yes, my world came crumbling down. For those who don’t read my blog often I work remotely 85% of my working weeks as the company I work for are in another country so having a secure and speedy VPN is critical to actually getting paid and doing some work. After upgrading OSX 10.5 to Snow Leopard my Checkpoint SecureClient completely stopped working – this appears to be the plight of many users out in the interweb so I thought id write up this guide how to use IPSecuritas (as it rocks) which is infinitely better than the default checkpoint client (which sucks major ass!).

Why should I care about IPSecuritas?

This is simple – basically (as above) it rocks and has the following great features:

  • Its speedy.
  • Automatic connection recovery
  • Password persistance
  • Can talk to a bunch of different Firewall types… no more vendor tie-ins
  • Great OSX integration
  • Automatic connection upon login (instantly connected to VPN!)
  • Oh, did I mention its fast?

Removing Checkpoint SecureClient

OK, so now we’ve established that SecureClient is evil, lets remove it. Helpfully, checkpoint took the time to provde a shell script in the install directory to do just this. Open a Terminal window (Applications > Utilities > Terminal) and type the following:



# i'm not 100% sure on the names, as im writing this from memory, 
# but just have a poke around and you'll find what I mean.
timperrett$ cd /opt/C (press tab for auto-complete then return key)
timperrett$ open Uninstall.command

Type “yes” when prompted – the script will then go about removing all the various components. If your thinking of skipping this step, your free to, but remember than this installation is completely broken and wont ever run under Snow Leopard as it appears to be tied to the 9.x Kernel present in 10.5… so you might as well clean up and keep tidy.

Setting up IPSecuritas

If you havent already, download IPSecuritas from here – open the DMG and drag the application to your Applications directory. Once there, double click the application to load it for the first time – you’ll need to enter your Administrator password then the application will install a daemon onto your system and configure itself. Once completed, take my advice and reboot your system – upon reboot you should see a new menu item that looks like a broken wire (below, dont worry about “XMPie”, thats just what I decided to call my profile)...

Choose the “Open IPSecuritas” menu item – and up should spring the main GUI. You now need to configure a connection – this is what you will use to connect to your VPN endpoint (clue’s in the name!). Making this connection is however a rather technical process for most users so im going to post screen shots of my configuration at every stage so that you can make something similar (yours may not be identical – it really depends on the setup implemented on the firewall; however, what I detail uses common place defaults).

So the two boxes in red are the important ones. For Remote IPSec Device you need to fill in the domain name or IP address of your firewall / vpn endpoint; this is organisation specific so i’ve removed mine. Secondly, Network address – this is the base IP range to which you want to connect to; again, organisation specific and yours will likely be different – if you don’t know, check with an IT administrator.

These are standard security options needed to work with the checkpoint vpn – because I work long hours connected to the VPN, i’ve set it to timeout after 10 hours (essentially it never cuts me off and im in charge… sweet).

Again, this is standard checkpoint stuff so just copy the configurations as is – you don’t need to know whats what.

So this is an interested panel – the two boxes ive marked in red need to be filled with your username for the VPN connection; you should have this already with that which you were using with the Checkpoint SecureClient system. In this example (and the checkpoint default) its using Hybrid RSA, but a lot of organisations use XAuth RSA etc that involve certificates etc… if you need this, just use the certificate manager and configure accordingly. I’ve also set it to remember my password so that I dont have to keep entering it – depending on your outlook, this is a good/bad thing. Personally, I think its a great timesaver!

Depending on your setup, you may want to configure specilized DNS servers – you might want this if you have servers that you wish you access with a UNC style such as:

\\somefileshare

Without specifying those DNS, your VPN will try to use external DNS and you just wont get what you want (or expect). I’ve removed mine for security reasons, but it should be fairly simple to figure out what you need to enter.

So this is the killer panel that confuses most people – you have some fairly finite control over the connection parameters – if your using Checkpoint VPN-1, just do as I have (unless your using another authorisation mechanism) and you should succeed!

Once you have all that, your good to go – just close the window, and click “Start” on the main IPSeceritas window then provided all went well you should get a green light next to the connection name – in my instance, i called the connection “office”. If you are having issues, seek help from your IT administrator as it might be a configuration issue – with VPN’s your client much EXACTLY match what the endpoint is configured to… any miss-match at all will result in failure; however if you wish to debug the issue yourself, bring up the connection log from the top bar menu and you’ll be able to see exactly what is going on under the hood (if you need a boat load of wire information, set the logging level in preferences to DEBUG and then restart/reboot IPSecuritas)

Enjoy, and good luck.

One of the best things about Lift is its amazingly flexible template and resource localization system. This article discusses the mechanisms that you can use to localize your application.

Overview

Out of the box, Lift gives you the following options – items 1 and 2 require zero boiler plate, whilst the 3rd option gives you the flexibility to extend the localization however you need.

  • Text localization from property bundles
  • Full template localization
  • Custom resource bundle provider hook

We will now take a look at each localization option in turn, in relative detail stopping to investigate how they work.

Assumed environment

For the length of this article we’ll assume that we have the need to localize into English (our default language), French, German and Hebrew. These languages have the following locale codes:

Language Code
English en_GB
French fr_FR
German de_DE
Hebrew he_IL

These are standard ISO codes used by the Java localization system, irrespective of Lift et al. As a bit of background for those of you not familiar with locale codes and there purpose, you can see that the first part of the locale code denotes the spoken language – for example, en is English – and the second part after the underscore is the country code. This is amazingly helpful for languages like English and Arabic which are spoken in many countries as it gives you a specific language and then culture on which you can account for language nuances etc. Salutations are a classic one – UK English might have a salutation of “Good afternoon” whilst Australian English might have “Good ay’”.

In order to tell Lift that this application will be localized into several languages, we have to set a customized localeCalculator. In our application it will look like this:


def localeCalculator(request : Box[HttpServletRequest]): Locale = 
  request.flatMap(r => {
  def workOutLocale: Box[java.util.Locale] = 
  S.findCookie(localeCookieName) match {
    case Full(cookie) => cookie.getValue()
    case _ => Full(LiftRules.defaultLocaleCalculator(request))
  }
  tryo(r.getParameter("locale")) match {
    case Full(null) => workOutLocale
    case Empty => workOutLocale
    case Failure(_,_,_) => workOutLocale
    case Full(selectedLocale) => {
      setLocale(selectedLocale)
      selectedLocale
    }
  }
}).openOr(java.util.Locale.getDefault())

Add this function someplace in your application – here we’ll assume its just in the Boot class, then set it in LiftRules like so:


LiftRules.localeCalculator = localeCalculator _

Text localization from property bundles

So, given our working languages we have several issues at hand and several strategies we could choose. Lets start with the most basic form of localization that will be familiar with most users of the java platform… properties files loaded as a ResourceBundle.

So lets assume that we have our translations already completed, we just need to put them into key-value pairs in properties files located in:

${project.basedir}/src/main/resources/mybundlename_*locale*

So for us, that looks like:


mybundlename_en_GB.properties
mybundlename_fr_FR.properties
mybundlename_de_DE.properties
mybundlename_he_IL.properties

This is pretty standard stuff that is well documented in the javadocs from sun. So, you need to know how to specify value keys within lift. There are two use cases, one is in your code, and the other is in your HTML templates.

In code:

S.?("mykey")

In template:

<lift:loc locid="mykey">Default Text</lift:loc>

This is all well and good, but there are use cases that simple key/value replacement doesnt take care of – with our use case languages we have a great example here:

  • Hebrew is a language that is written right-to-left (RTL) so generally the content / css / markup will be quite different
  • Within the languages that are left-to-right (LTR), French and English have a comparable number of character tokens, but german is typically more verbose and content takes up more room.

So, to deal with such cases Lift brings you comprehensive template localization which we’ll now discuss.

Template file localization

Given this conundrum about language direction and content length lift can assert different template names. For example, lets assume that in your webapp directory you have a file called index.html – based on the LiftRules.localeCalculator Locale that is returned, it can choose the right template. With the problems we face here, we might have:


index_en_GB.html
index_en_AU.html
index_de.html
index_he.html

This would then yield different content templates for German and Hebrew, and gives us two distinctly different english templates for UK English and Australian English… for arguments sake the imagery in the two templates could be different because Australian culture is somewhat more casual than compared to England.

This exact same scheme also applies for CSS resources if you do not need the possibly side effect of code duplication in this system.

Custom resource bundle provider hook

One of the driving mantras of Lift is that everything, and we mean everything has sensible defaults, but you can hook right into the core lift lifecycle and add your own stuff. Localization is no different and it is of course a common idiom to need to load localization content from a database backed cache. I wont delve into exactly how you handle the caching or similar (that my friends is up to you) but this is how you pass the special resource bundles into Lift’s cycle:


LiftRules.resourceBundleFactories.prepend { 
  case (basename, locale) if localeAvalible_?(locale) => 
      CacheResourceBundle(locale)
  case _ => CacheResourceBundle(new Locale("en","GB"))
}

In the above example, localeAvalible_? checks if this locale is available (from a value in my application) and of course, CacheResourceBundle is a subclass of ResourceBundle and has the following signature:


case class CacheResourceBundle(loc: Locale) extends ResourceBundle

Conclusion

Thats pretty much it folks – by way of a mix of these schemes its possible to build up a very rich localization methodology which works for pretty much all locale needs. In this example we have discussed language lengths, RTL languages and given you all the code you need to get going with localization in Lift – go forth and localize!

One of the confusing things about Lift for new comers are snippets – not only conceptually, but the bewildering array of options they have when choosing snippet implementation style. Users have to choose between snippet reflection, dispatch snippets and even statefull snippets that extend snippet dispatching!

Reflection Snippets

Loading class-based snippets via reflection is the default scheme in Lift as it offers a quick start for development. Given the following code in my snippet package:


import _root_.scala.xml.{NodeSeq,Text}

class HelloWorld {
  def speak = <span>Hello World</span>
}

I could then just call this in any Lift template I wanted by using the following:


<lift:hello_world.speak />

So right there, with no other plumbing we have a working snippet invocation – granted, our example is not feature full but it services our needs for this example. So this is all great, and works perfectly for development / low volume deployment, however when your site starts to scale this method of snippet modeling will become undesirable. Why? Every time you call the reflection snippet in your markup code, a new instance is instantiated and the appropriate method invoked – of course, if you have lots of the same snippet in a single page request cycle this is less than desirable (not to mention if said page is getting thousands of requests)

DispatchSnippet to the rescue!

In Scala we can of course use the object keyword to create a singleton object – this is most helpful in terms of snippets, as comparatively to creating lots of instances, here we will only have a single one which makes for a much more optimal snippet system. Lets take our previous snippet and turn it into a dispatch snippet:


import _root_.scala.xml.{NodeSeq,Text}
import _root_.net.liftweb.http.DispatchSnippet

object HelloWorld extends DispatchSnippet {
  def dispatch = { 
    case "talk" => speak
  }
  def speak = <span>Hello World</span>
}

There is of course a slight downside – the reflection snippets mean no plumbing, but with the DispatchSnippet we will of course just need to let Lift know when we call something in our XHTML what snippet instance we are referring to – we do this with a SnippetDispatchPF call in your Boot.scala file:


  LiftRules.snippetDispatch.append(
    Map("hello_world" -> HelloWorld)
  )

This means in our XHTML we can call:


<lift:hello_world.talk />

This has the exact same output as the reflection style snippet, but only using a single snippet instance for your application.

Admitidally, every time i’ve ever looked at the Lift codebase in TextMate, i’ve always wondered what the hell the “lift-amqp” module was for. Well, curiosity may have killed the cat but it was not enough of deterrent to me finding out and building a sample AMQP / RabbitMQ application!

AMQP you say?

Yup, thats right. AMQP – Advanced Message Queuing Protocol to the lay’ man not familiar with the acronym. Essentially AMQP is an open standard for enterprise messaging. There are several implementations of the standard, namely, Open AMQ and RabbitMQ – the latter is newer and generally considered to be the defacto implementation. Rabbit MQ is written in ERLang and has clients for Java, .NET, Ruby etc etc.

So where does Lift fit in?

Strictly speaking, it doesn’t. It just so happens that Steve J was working on the Lift team some time ago and wrote a nifty Scala wrapper around the standard (and highly mutable) Java client implementation of Rabbit MQ. To all intense purpose, “lift-amqp” can be used in any Scala application and has no other dependencies within the Lift framework.

Hand-wavy overview

Lets get down to business… I spent quite a lot of time just looking at the source code and scala-docs for lift-amqp and for the longest while couldn’t figure out what went where. Being a fairly visual person, I’ve drawn up a diagram that explains the implementation and how you (yes, you reading this) would implement your application:

A working example?

So rather than try to post lots of pictures – I thought just putting up a screen-cast explaining the components would make more sense :-)

The client listener

So from the diagram above that explains the code layout – you can see that one of the first things you need to do is subclass AMQPDispatcher. The below is my example code that connects to the RabbitMQ broker and firstly declares a queue with the appropriate parameters. If you wondering why when the 2nd client connected in my example things didn’t explode and complain about more than one exchange existing with the same name, thats because RabbitMQ is clever enough to know that if the queue / exchange already exists then it just Noop’s the requests. Its a nice feature.


class DemonstrationSerializedAMQPDispatcher[T](
  queueName: String, factory: ConnectionFactory, 
  host: String, port: Int) extends AMQPDispatcher[T](
    factory, host, port) {
  override def configure(channel: Channel) {
    val ticket = channel.accessRequest("/data")
    channel.exchangeDeclare(ticket, "mult", "fanout")
    channel.queueDeclare(ticket, queueName)
    channel.queueBind(ticket, queueName, "mult", "example.*")
    channel.basicConsume(ticket, queueName, false, 
      new SerializedConsumer(channel, this))
  }
}

So, your probably thinking that this was not the class that I created an instance of during the screencast – and you’d be right. Essentially we still need a wrapper class to mask our dispatcher; the listener proper.

The purpose of the listener is to establish a connection to the broker, pass the right credentials etc. Within the listener we create an instance of the dispatcher and start its actor. We also then just have an inner class that we use for example purposes (another actor) that prints out the messages you saw in the terminal window. In reality, this would likely be passing messages to some other, external actor which handled the business process. For a full code listing see the end of this article.

The postman…

So now that you know how the example listens for messages, lets see the posting code…


  val params = new ConnectionParameters
  params.setUsername("guest")
  params.setPassword("guest")
  params.setVirtualHost("/")
  params.setRequestedHeartbeat(0)
  val factory = new ConnectionFactory(params)
  // Create a new instance of the string sender.
  // This sender will send messages to the "mult" exchange with a 
  // routing key of "routeroute" 
  val amqp = new StringAMQPSender(
    factory, "macbookpro", 5672, "mult", "example.demo" 
  )
  amqp.start

  /**
   * Salute the rabbit!
   */
  def salute = amqp ! AMQPMessage("hey there!")
}

Little explanation needed here – essentially the string sender is just an actor that knows how to respond to AMQPMessage…. it couldn’t be simpler! I hope this has proved helpful and a good overview of the lift-amqp module.

If you would like to download the source code, you can get it from here