<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>The Loop - Blog</title>
  <id>tag:blog.getintheloop.eu,2010:mephisto/</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  <link href="http://blog.getintheloop.eu/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://blog.getintheloop.eu/" rel="alternate" type="text/html"/>
  <updated>2010-07-15T18:37:09Z</updated>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2010-07-15:1670</id>
    <published>2010-07-15T18:36:00Z</published>
    <updated>2010-07-15T18:37:09Z</updated>
    <link href="http://blog.getintheloop.eu/2010/7/15/scala-its-good-for-your-health" rel="alternate" type="text/html"/>
    <title>Scala: It's Good for Your Health</title>
<content type="html">
            &lt;p&gt;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.&lt;/p&gt;


	&lt;p&gt;To date, I am yet to encounter someone in the Scala and Lift communities who isn&#8217;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 &lt;a href=&quot;http://twitter.com/dpp&quot;&gt;David&lt;/a&gt;, &lt;a href=&quot;http://twitter.com/mariusdanciu&quot;&gt;Marius&lt;/a&gt;, &lt;a href=&quot;http://twitter.com/jboner&quot;&gt;Jonas&lt;/a&gt; and &lt;a href=&quot;http://twitter.com/viktorklang&quot;&gt;Viktor&lt;/a&gt; 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.&lt;/p&gt;


	&lt;p&gt;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!&lt;/p&gt;


	&lt;p&gt;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 ;-)&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2010-06-27:1647</id>
    <published>2010-06-27T16:27:00Z</published>
    <updated>2010-06-27T16:28:33Z</updated>
    <link href="http://blog.getintheloop.eu/2010/6/27/controlling-schemifier-naming-conventions-with-mapperrules" rel="alternate" type="text/html"/>
    <title>Controlling Schemifier naming conventions with MapperRules </title>
<content type="html">
            &lt;p&gt;I was recently asked how to stop Lift&#8217;s Mapper from flattening the naming of columns during its &#8220;schemification&#8221; process. Well, there is a little known configuration object in the net.liftweb.mapper package called MapperRules.&lt;/p&gt;


	&lt;p&gt;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:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;

class Boot {
  def boot {
    ...
    MapperRules.tableName =  (_,name) =&amp;gt; StringHelpers.snakify(name)
    MapperRules.columnName = (_,name) =&amp;gt; StringHelpers.snakify(name)
    ...  
  } 
}

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Thats it!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2010-06-23:1638</id>
    <published>2010-06-23T19:41:00Z</published>
    <updated>2010-06-23T19:42:00Z</updated>
    <link href="http://blog.getintheloop.eu/2010/6/23/lift-in-action" rel="alternate" type="text/html"/>
    <title>Lift In Action - The comprehensive guide to Lift</title>
<content type="html">
            &lt;p&gt;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 &lt;a href=&quot;http://liftweb.net/&quot;&gt;Lift&lt;/a&gt; &#8211; If you haven&#8217;t heard, &lt;a href=&quot;http://manning.com/perrett/&quot;&gt;Lift In Action&lt;/a&gt; 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&#8217;t had a chance to post about all the cool new stuff that is making its way into Lift every week &#8211; 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 &lt;a href=&quot;http://squeryl.org/&quot;&gt;Squeryl&lt;/a&gt; as a backend for dealing with &lt;span class=&quot;caps&quot;&gt;RDBMS&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;By all means, go and checkout the book and let me know what you think as it develops in the &lt;a href=&quot;http://www.manning-sandbox.com/forum.jspa?forumID=660&#38;start=0&quot;&gt;author online forums&lt;/a&gt; and I will get back to you &lt;span class=&quot;caps&quot;&gt;ASAP&lt;/span&gt;. Enjoy!&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2010/6/23/perrett_cover150.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2010-05-01:1524</id>
    <published>2010-05-01T15:22:00Z</published>
    <updated>2010-05-01T15:22:41Z</updated>
    <link href="http://blog.getintheloop.eu/2010/5/1/inline-markup-validation-with-lift" rel="alternate" type="text/html"/>
    <title>Inline Markup Validation with Lift</title>
<content type="html">
            &lt;p&gt;Continuing with my series of articles about Lift, here&#8217;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&#8217;s what you need to do to enable it:&lt;/p&gt;


	&lt;h2&gt;Configure Boot&lt;/h2&gt;


&lt;pre&gt;&lt;code&gt;
  class Boot {
    def boot {
    ......   
      LiftRules.xhtmlValidator = Full(StrictXHTML1_0Validator)
    }
  }
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Where of course you can replace &lt;code&gt; StrictXHTML1_0Validator&lt;/code&gt; with any one of:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  TransitionalXHTML1_0Validator
  StrictXHTML1_0Validator

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

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Find this and more great tips in my forthcoming book, &lt;a href=&quot;http://manning.com/perrett/&quot;&gt;Lift in Action&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2010-04-16:1494</id>
    <published>2010-04-16T09:26:00Z</published>
    <updated>2010-04-16T09:28:58Z</updated>
    <link href="http://blog.getintheloop.eu/2010/4/16/understanding-lift-s-box-t-monad" rel="alternate" type="text/html"/>
    <title>Understanding Lift's Box[T] monad</title>
<content type="html">
            &lt;p&gt;So im at Scala Days 2010 right now, and during dinner last night their seemed to be some misconceptions about what Lift&#8217;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 &#8220;tri state option&#8221;...&lt;/p&gt;


	&lt;h2&gt;Why bother boxing values?&lt;/h2&gt;


	&lt;p&gt;Have you ever thrown a NullPointerException? Frankly, I don&#8217;t know any developers that haven&#8217;t had this happen to them at some point because of something they hadn&#8217;t considered during development&#8230; in short, a &lt;span class=&quot;caps&quot;&gt;NPE&lt;/span&gt; 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.&lt;/p&gt;


	&lt;p&gt;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&#8230;.&lt;/p&gt;


	&lt;p&gt;...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:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
import net.liftweb.common.{Box,Full,Empty,Failure,ParamFailure}

scala&amp;gt; val x: Box[String] = Empty
x: net.liftweb.common.Box[String] = Empty

scala&amp;gt; val y = Full(&quot;Thing&quot;)
y: net.liftweb.common.Full[java.lang.String] = Full(Thing)

&lt;/code&gt;&lt;/pre&gt;

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


	&lt;h2&gt;What about exceptions?&lt;/h2&gt;


	&lt;p&gt;Lift has a helper method in &lt;code&gt;net.liftweb.util.Helpers&lt;/code&gt; called &#8220;tryo&#8221; that is a specilized control structure so that if you can execute code in a block that returns a Box&#8217;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:&lt;/p&gt;


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

	&lt;p&gt;There are some other overloads for syntax sugar, but essentially it lets you do:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  tryo {
    // your code here
  }

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So lets assume we had some remote &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; to invoke, and it could not connect, or blow up in some way you hadn&#8217;t planned, what would happy given a tryo block / wrap? Consider:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
scala&amp;gt; tryo(&quot;www&quot;.toInt) 
res4: net.liftweb.common.Box[Int] = Failure(
  For input string: &quot;www&quot;,
  Full(java.lang.NumberFormatException: For input string: &quot;www&quot;),
  Empty)

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As &#8220;www&#8221; 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.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
scala&amp;gt; tryo(&quot;www&quot;.toInt) openOr 1234                       
res7: Int = 1234

scala&amp;gt; tryo(&quot;www&quot;.toInt).map(_.toString).openOr(&quot;Invalid Strings&quot;)
res8: java.lang.String = Invalid Strings

scala&amp;gt; for(x &amp;lt;- tryo(&quot;www&quot;.toInt)) yield x
res11: net.liftweb.common.Box[Int] = Failure(
  For input string: &quot;www&quot;,
  Full(java.lang.NumberFormatException: For input string: &quot;www&quot;),
  Empty)

&lt;/code&gt;&lt;/pre&gt;

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


	&lt;h2&gt;Handling empty values?&lt;/h2&gt;


	&lt;p&gt;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 &lt;span class=&quot;caps&quot;&gt;REST API&lt;/span&gt; or similar&#8230; rather than throwing a &lt;span class=&quot;caps&quot;&gt;HTTP 500&lt;/span&gt; error with no reason, it would be nice to give the user a much more granular reason. Consider getting a request paramater using Lift&#8217;s S.param method.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
scala&amp;gt; S.param(&quot;id&quot;) ?~ &quot;You must supply an ID parameter&quot; 
res17: net.liftweb.common.Failure = 
  Failure(You must supply an ID parameter,Empty,Empty)

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The &lt;code&gt;?~&lt;/code&gt; 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.&lt;/p&gt;


	&lt;h2&gt;Chaining boxes&lt;/h2&gt;


	&lt;p&gt;Lets assume that we have a situation where by we could recive a value from several places, or we need to &#8220;fall through&#8221; to a specific result based on trying several values in a sequence&#8230; Box supports this by way of the &#8220;or&#8221; operand.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;

scala&amp;gt; val x = Empty
x: net.liftweb.common.Empty.type = Empty

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

scala&amp;gt; x or y or Full(&quot;Default&quot;)
res18: net.liftweb.common.Box[Any] = Full(Default)

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Box has a bunch of features I haven&#8217;t covered here, but I hope this helps you understand the rational of this specialised option-esq type.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2010-04-02:1477</id>
    <published>2010-04-02T09:55:00Z</published>
    <updated>2010-04-02T09:57:22Z</updated>
    <link href="http://blog.getintheloop.eu/2010/4/2/asynchronous-rest-services-with-lift" rel="alternate" type="text/html"/>
    <title>Asynchronous REST Services with Lift</title>
<content type="html">
            &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; REST and many other topics discussed within my upcomming book Lift in Action, more information will shortly be published on &lt;a href=&quot;http://manning.com&quot;&gt;manning.com&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;This one is hot off the press &#8211; Lift 2.0-SNAPSHOT now has the ability to do notification style service  workflows &#8211; essentially comet for &lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;So how does this work? Well, following on from my other post on &lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt; services with Lift we are still using a &lt;code&gt;DispatchPF&lt;/code&gt; to setup the service, but we now use the statefull dispatcher &lt;code&gt;LiftRules.dispatch&lt;/code&gt; rather than &lt;code&gt;statelessDispatchTable&lt;/code&gt; and from inside our resource definition we call &lt;code&gt;S.respondAsync&lt;/code&gt;. Here&#8217;s a complete example:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  LiftRules.dispatch.append {
    case Req(&quot;example&quot; :: rest, _, _) =&amp;gt; {
      S.respondAsync {
        Thread.sleep(20000) // some computation here
        Full(XmlResponse(&amp;lt;async&amp;gt;response&amp;lt;/async&amp;gt;))
      }
    }
  }

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;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.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2010-03-29:1467</id>
    <published>2010-03-29T17:00:00Z</published>
    <updated>2010-03-29T17:00:44Z</updated>
    <link href="http://blog.getintheloop.eu/2010/3/29/multi-format-rest-services-with-lift" rel="alternate" type="text/html"/>
    <title>Multi-format REST services with Lift</title>
<content type="html">
            &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This subject is discussed in much greater detail within my upcomming book Lift in Action, more information will shortly be published on &lt;a href=&quot;http://manning.com&quot;&gt;manning.com&lt;/a&gt;&lt;/p&gt;


	&lt;h2&gt;The Goal&lt;/h2&gt;


	&lt;p&gt;So what are we actually trying to achieve here? We&#8217;ll use the twitter.com &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; as an example as its a good illustration in this instance. Consider the following URLs:&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://api.twitter.com/users/timperrett.xml&quot;&gt;http://api.twitter.com/users/timperrett.xml&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;and&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://api.twitter.com/users/timperrett.json&quot;&gt;http://api.twitter.com/users/timperrett.json&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;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 &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; from multiple devices or platforms where toolkits may be limited. For example, working with &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; is a lot easier from Java script than it is &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; (the latter is of course possible its just more verbose). In the examples above, Twitter are using the format component of the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; following the &#8221;.&#8221; to determine the content type the user wants &#8211; 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.&lt;/p&gt;


	&lt;p&gt;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 &#8211; only the actual code that handles differences in presentation should alter between calls right?&lt;/p&gt;


	&lt;h2&gt;Implementation Pattern&lt;/h2&gt;


	&lt;p&gt;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&#8217;ll be wiring up the following services:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  LiftRules.statelessDispatchTable.append {
    case Req(&quot;apps&quot; :: Nil, &quot;json&quot;, GetRequest) =&amp;gt; 
      ApplicationServices.json.list
    case Req(&quot;apps&quot; :: Nil, &quot;xml&quot;, GetRequest) =&amp;gt; 
      ApplicationServices.xml.list
  }
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;For those not familiar with Lift&#8217;s dispatching mechanism this will expose the following URLs:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;/apps.json&lt;/li&gt;
		&lt;li&gt;/apps.xml&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;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:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
object ApplicationServices extends Loggable {
  .....
  protected def _list(mediaAction: List[String] =&amp;gt; LiftResponse) =
    () =&amp;gt; tryo(mediaAction(Applications.list.map(_.name)))
  .....
}
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;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&#8217;ll be JsonResponse for &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; and XmlResponse for &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt;.&lt;/p&gt;


	&lt;h4&gt;&lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; Listing&lt;/h4&gt;


&lt;pre&gt;&lt;code&gt;
def list = _list((apps) =&amp;gt; 
  JsonResponse(compact(JsonAST.render((&quot;applications&quot; -&amp;gt; apps)))))
&lt;/code&gt;&lt;/pre&gt;

	&lt;h4&gt;&lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; Listing&lt;/h4&gt;


&lt;pre&gt;&lt;code&gt;
def list = _list((apps) =&amp;gt; XmlResponse({
  &amp;lt;applications&amp;gt;
    {apps.map(a =&amp;gt; &amp;lt;application name={a} /&amp;gt;)}
  &amp;lt;/applications&amp;gt;
}))
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So you can see that each presentation version is only dealing with how it needs to create the response&#8230; its not re-computing the list of applications or such.&lt;/p&gt;


	&lt;h2&gt;Syntax Sugar&lt;/h2&gt;


	&lt;p&gt;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:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
object ApplicationServices extends Loggable {
  val json = Json
  val xml = Xml

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

  object Json {
    // definitions here
  }

  object Xml {
    // definitions here
  }
}
&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Round Up&lt;/h2&gt;


	&lt;p&gt;Thats pretty much all there is too it. You can leverage Scala&#8217;s extremely powerful features to create your web services and keep code &lt;span class=&quot;caps&quot;&gt;LOC&lt;/span&gt; to a minimum. Over and out.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2010-02-21:1430</id>
    <published>2010-02-21T14:07:00Z</published>
    <updated>2010-03-05T14:08:12Z</updated>
    <link href="http://blog.getintheloop.eu/2010/2/21/gracefully-handling-404s-with-lift" rel="alternate" type="text/html"/>
    <title>Gracefully handling 404s with Lift</title>
<content type="html">
            &lt;p&gt;In my continuing effort to improve the wider knowledge of Lift, here&#8217;s another great nugget that shows you how to provide a 404 handler powered from a Lift template&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
class Boot {
  def boot {
    // ...other stuff...

    LiftRules.uriNotFound.prepend(NamedPF(&quot;404handler&quot;){
      case (req,failure) =&amp;gt; 
       NotFoundAsTemplate(ParsePath(List(&quot;404&quot;),&quot;html&quot;,false,false))
    })

  }
}

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And I have a 404.html file in the ./webapp/404.html with the contents:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&amp;lt;lift:surround with=&quot;default&quot; at=&quot;content&quot;&amp;gt;
  &amp;lt;h2&amp;gt;Ooops!&amp;lt;/h2&amp;gt;
  &amp;lt;p&amp;gt;Wow, we totally couldn't find your page. Sorry about that.&amp;lt;/p&amp;gt;
&amp;lt;/lift:surround&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Then whenever a user browses to a &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; that is not supported by your application, you can give them a friendly (and nicely designed) webpage rather than some technical message about 404s.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The only cavet is not to use the &lt;code&gt;&amp;lt;lift:menu /&amp;gt;&lt;/code&gt; snippet within your 404 template because Lift is unable to calculate the SiteMap when its a &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; that is not accounted for within that scheme.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;&lt;/strong&gt; The above note is now redundant because of commit by Marius on issue 376&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2010-02-18:1429</id>
    <published>2010-02-18T17:07:00Z</published>
    <updated>2010-02-18T17:08:04Z</updated>
    <link href="http://blog.getintheloop.eu/2010/2/18/using-jetty-7-continuations-to-power-lift-comet-support" rel="alternate" type="text/html"/>
    <title>Using Jetty 7 continuations to power Lift comet support</title>
<content type="html">
            &lt;p&gt;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 &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; 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:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;

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

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

    LiftRules.servletAsyncProvider = (req) =&amp;gt; 
        new Jetty7AsyncProvider(req)

  }
}

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;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.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2009-11-11:1135</id>
    <published>2009-11-11T14:50:00Z</published>
    <updated>2009-11-11T16:33:06Z</updated>
    <link href="http://blog.getintheloop.eu/2009/11/11/consistent-hashing-between-lift-and-net" rel="alternate" type="text/html"/>
    <title>Consistent hashing and encryption between Lift and .NET</title>
<content type="html">
            &lt;p&gt;Its quite often that I need to pass tokens between Scala (Java also) and .NET &#8211; 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)&lt;/p&gt;


	&lt;h2&gt;The Scala way:&lt;/h2&gt;


&lt;pre&gt;&lt;code&gt;

  val input = &quot;sample&quot; 
  val encoding = &quot;UTF-8&quot; 

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

&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;The .NET way&lt;/h2&gt;


&lt;pre&gt;&lt;code&gt;

  using System.Security.Cryptography;

  string input = &quot;sample&quot;;

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

  StringBuilder sBuilder = new StringBuilder();
  for (int i = 0; i &amp;lt; data.Length; i++){
    sBuilder.Append(data[i].ToString(&quot;x2&quot;));
  }

  string hash = sBuilder.ToString();

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

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;&lt;/strong&gt; 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:&lt;/p&gt;


	&lt;h2&gt;The Scala way:&lt;/h2&gt;


&lt;pre&gt;&lt;code&gt;

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

&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;The .NET way:&lt;/h2&gt;


&lt;pre&gt;&lt;code&gt;

  using System.Security.Cryptography;

  string key = &quot;qwehfjgtufkgurifghfkdjfg&quot;;
  string toEnc = &quot;sample&quot;;

  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);

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Maybe this will help someone avoid the pain I have endured with this! lol.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2009-10-16:812</id>
    <published>2009-10-16T17:10:00Z</published>
    <updated>2009-10-16T17:11:48Z</updated>
    <link href="http://blog.getintheloop.eu/2009/10/16/conversational-marketing-with-scala-and-lift" rel="alternate" type="text/html"/>
    <title>Conversational Marketing with Scala and Lift</title>
<content type="html">
            &lt;p&gt;Picture the scene: Im sat in my chair, working away and then I get a fairly crazed phone call from a &lt;a href=&quot;http://david.baldaro.me.uk/&quot;&gt;co-worker in sales&lt;/a&gt; &#8211; he apparently has this stunning new idea about how to leverage twitter as a marketing platform&#8230;&lt;/p&gt;


	&lt;p&gt;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 &lt;a href=&quot;http://david.baldaro.me.uk/2009/10/social-media-meets-cross-media/&quot;&gt;over here&lt;/a&gt;&lt;/p&gt;


	&lt;h2&gt;A cunning scheme indeed&lt;/h2&gt;


	&lt;p&gt;So, from the off, this was going to be an interesting campaign to put together because there were numerous issues, including:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Lots of concurrent (and asynchronous) read / write ops to Twitter &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;Backend communication to XMPie cluster&lt;/li&gt;
		&lt;li&gt;Push production status back down to the browser&lt;/li&gt;
		&lt;li&gt;Downloading of avatar images automatically from twitter and insert into XMPie asset source&lt;/li&gt;
		&lt;li&gt;Doing any of this in the given time frame!?&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;This project was going to have a sizeable set of works attached no doubt to manage the interplay between XMPie systems and the Twitter &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;.&lt;/p&gt;


	&lt;h2&gt;Technology Sandwich&lt;/h2&gt;


	&lt;p&gt;To implement this campaign, I ended up using a whole bunch of different technologies&#8230; The implementing stack eventually ended up utilising the following:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Lift&lt;/li&gt;
		&lt;li&gt;Dispatch&lt;/li&gt;
		&lt;li&gt;Scala Actors&lt;/li&gt;
		&lt;li&gt;XMPie uProduce&lt;/li&gt;
		&lt;li&gt;XMPie &lt;span class=&quot;caps&quot;&gt;ICP&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;Microsoft &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; Server&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;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!:&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2009/10/16/twitter-app-design_1.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;As you can see &#8211; quite a number of software components here! I&#8217;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.&lt;/p&gt;


	&lt;p&gt;This entire campaign was implemented based on top of &lt;span class=&quot;caps&quot;&gt;ICP&lt;/span&gt;, using my Scala abstraction along with the awesome power of Scala Actors, scheduling and some generally very cool libraries like &lt;a href=&quot;http://databinder.net/dispatch/&quot;&gt;Dispatch&lt;/a&gt;&lt;/p&gt;


	&lt;h2&gt;Questions&lt;/h2&gt;


	&lt;p&gt;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&#8217;ll get back to you&#8230;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2009-08-31:789</id>
    <published>2009-08-31T21:57:00Z</published>
    <updated>2009-08-31T21:57:36Z</updated>
    <link href="http://blog.getintheloop.eu/2009/8/31/replacing-checkpoint-secureclient-with-ipsecuritas-on-snow-leopard" rel="alternate" type="text/html"/>
    <title>Replacing Checkpoint SecureClient with IPSecuritas on Snow Leopard</title>
<content type="html">
            &lt;p&gt;So its that time again &#8211; another awesome Apple update to the best operating system in the world; for most, its a joyous time, one of new beginnings and wonderment&#8230;. for some, alas this is just an ideal as all there proprietary software comes crumbling down under a new kernel.&lt;/p&gt;


	&lt;p&gt;Friday was one of these momentous days, and yes, my world came crumbling down. For those who don&#8217;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 &lt;span class=&quot;caps&quot;&gt;VPN&lt;/span&gt; is critical to actually getting paid and doing some work. After upgrading &lt;span class=&quot;caps&quot;&gt;OSX 10&lt;/span&gt;.5 to Snow Leopard my Checkpoint SecureClient completely stopped working &#8211; 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!).&lt;/p&gt;


	&lt;h2&gt;Why should I care about IPSecuritas?&lt;/h2&gt;


	&lt;p&gt;This is simple &#8211; basically (as above) it rocks and has the following great features:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Its speedy.&lt;/li&gt;
		&lt;li&gt;Automatic connection recovery&lt;/li&gt;
		&lt;li&gt;Password persistance&lt;/li&gt;
		&lt;li&gt;Can talk to a bunch of different Firewall types&#8230; no more vendor tie-ins&lt;/li&gt;
		&lt;li&gt;Great &lt;span class=&quot;caps&quot;&gt;OSX&lt;/span&gt; integration&lt;/li&gt;
		&lt;li&gt;Automatic connection upon login (instantly connected to &lt;span class=&quot;caps&quot;&gt;VPN&lt;/span&gt;!)&lt;/li&gt;
		&lt;li&gt;Oh, did I mention its fast?&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Removing Checkpoint SecureClient&lt;/h2&gt;


	&lt;p&gt;OK, so now we&#8217;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 &amp;gt; Utilities &amp;gt; Terminal) and type the following:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;

# 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

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Type &#8220;yes&#8221; when prompted &#8211; 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&#8230; so you might as well clean up and keep tidy.&lt;/p&gt;


	&lt;h2&gt;Setting up IPSecuritas&lt;/h2&gt;


	&lt;p&gt;If you havent already, &lt;a href=&quot;http://www.lobotomo.com/products/IPSecuritas/&quot;&gt;download IPSecuritas from here&lt;/a&gt; &#8211; open the &lt;span class=&quot;caps&quot;&gt;DMG&lt;/span&gt; and drag the application to your Applications directory. Once there, double click the application to load it for the first time &#8211; you&#8217;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 &#8211; upon reboot you should see a new menu item that looks like a broken wire (below, dont worry about &#8220;XMPie&#8221;, thats just what I decided to call my profile)...&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2009/8/31/ipsecuritas-menu.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Choose the &#8220;Open IPSecuritas&#8221; menu item &#8211; and up should spring the main &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt;. You now need to configure a connection &#8211; this is what you will use to connect to your &lt;span class=&quot;caps&quot;&gt;VPN&lt;/span&gt; endpoint (clue&#8217;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 &#8211; it really depends on the setup implemented on the firewall; however, what I detail uses common place defaults).&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2009/8/31/ipsecuritas-tab-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


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


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2009/8/31/ipsecuritas-tab-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;These are standard security options needed to work with the checkpoint vpn &#8211; because I work long hours connected to the &lt;span class=&quot;caps&quot;&gt;VPN&lt;/span&gt;, i&#8217;ve set it to timeout after 10 hours (essentially it never cuts me off and im in charge&#8230; sweet).&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2009/8/31/ipsecuritas-tab-3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Again, this is standard checkpoint stuff so just copy the configurations as is &#8211; you don&#8217;t need to know whats what.&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2009/8/31/ipsecuritas-tab-4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;So this is an interested panel &#8211; the two boxes ive marked in red need to be filled with your username for the &lt;span class=&quot;caps&quot;&gt;VPN&lt;/span&gt; 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 &lt;span class=&quot;caps&quot;&gt;RSA&lt;/span&gt;, but a lot of organisations use XAuth &lt;span class=&quot;caps&quot;&gt;RSA&lt;/span&gt; etc that involve certificates etc&#8230; if you need this, just use the certificate manager and configure accordingly. I&#8217;ve also set it to remember my password so that I dont have to keep entering it &#8211; depending on your outlook, this is a good/bad thing. Personally, I think its a great timesaver!&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2009/8/31/ipsecuritas-tab-5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Depending on your setup, you may want to configure specilized &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; servers &#8211; you might want this if you have servers that you wish you access with a &lt;span class=&quot;caps&quot;&gt;UNC&lt;/span&gt; style such as:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;\\somefileshare&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Without specifying those &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt;, your &lt;span class=&quot;caps&quot;&gt;VPN&lt;/span&gt; will try to use external &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; and you just wont get what you want (or expect). I&#8217;ve removed mine for security reasons, but it should be fairly simple to figure out what you need to enter.&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2009/8/31/ipsecuritas-tab-6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;So this is the killer panel that confuses most people &#8211; you have some fairly finite control over the connection parameters &#8211; if your using Checkpoint &lt;span class=&quot;caps&quot;&gt;VPN&lt;/span&gt;-1, just do as I have (unless your using another authorisation mechanism) and you should succeed!&lt;/p&gt;


	&lt;p&gt;Once you have all that, your good to go &#8211; just close the window, and click &#8220;Start&#8221; on the main IPSeceritas window then provided all went well you should get a green light next to the connection name &#8211; in my instance, i called the connection &#8220;office&#8221;. If you are having issues, seek help from your IT administrator as it might be a configuration issue &#8211; with &lt;span class=&quot;caps&quot;&gt;VPN&lt;/span&gt;&#8217;s your client much &lt;span class=&quot;caps&quot;&gt;EXACTLY&lt;/span&gt; match what the endpoint is configured to&#8230; 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&#8217;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 &lt;span class=&quot;caps&quot;&gt;DEBUG&lt;/span&gt; and then restart/reboot IPSecuritas)&lt;/p&gt;


	&lt;p&gt;Enjoy, and good luck.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2009-07-26:765</id>
    <published>2009-07-26T22:06:00Z</published>
    <updated>2009-07-26T22:06:36Z</updated>
    <link href="http://blog.getintheloop.eu/2009/7/26/how-to-extensive-localization-with-the-liftweb-framework" rel="alternate" type="text/html"/>
    <title>How To: Extensive Localization with the Liftweb Framework</title>
<content type="html">
            &lt;p&gt;One of the best things about &lt;a href=&quot;http://liftweb.net/&quot;&gt;Lift&lt;/a&gt; is its amazingly flexible template and resource localization system. This article discusses the mechanisms that you can use to localize your application.&lt;/p&gt;


	&lt;h2&gt;Overview&lt;/h2&gt;


	&lt;p&gt;Out of the box, Lift gives you the following options &#8211; items 1 and 2 require zero boiler plate, whilst the 3rd option gives you the flexibility to extend the localization however you need.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Text localization from property bundles&lt;/li&gt;
		&lt;li&gt;Full template localization&lt;/li&gt;
		&lt;li&gt;Custom resource bundle provider hook&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;We will now take a look at each localization option in turn, in relative detail stopping to investigate how they work.&lt;/p&gt;


	&lt;h2&gt;Assumed environment&lt;/h2&gt;


	&lt;p&gt;For the length of this article we&#8217;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:&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;th&gt;Language &lt;/th&gt;
			&lt;th&gt;Code &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; English &lt;/td&gt;
			&lt;td&gt; en_GB &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; French &lt;/td&gt;
			&lt;td&gt; fr_FR &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; German &lt;/td&gt;
			&lt;td&gt; de_DE &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Hebrew &lt;/td&gt;
			&lt;td&gt; he_IL &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;These are standard &lt;span class=&quot;caps&quot;&gt;ISO&lt;/span&gt; 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 &#8211; for example, en is English &#8211; 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 &#8211; UK English might have a salutation of &#8220;Good afternoon&#8221; whilst Australian English might have &#8220;Good ay&#8217;&#8221;.&lt;/p&gt;


	&lt;p&gt;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:&lt;/p&gt;


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

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Add this function someplace in your application &#8211; here we&#8217;ll assume its just in the Boot class, then set it in LiftRules like so:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
LiftRules.localeCalculator = localeCalculator _

&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Text localization from property bundles&lt;/h2&gt;


	&lt;p&gt;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&#8230; properties files loaded as a ResourceBundle.&lt;/p&gt;


	&lt;p&gt;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:&lt;/p&gt;


&lt;code&gt;${project.basedir}/src/main/resources/mybundlename_*locale*&lt;/code&gt;

	&lt;p&gt;So for us, that looks like:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
mybundlename_en_GB.properties
mybundlename_fr_FR.properties
mybundlename_de_DE.properties
mybundlename_he_IL.properties

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;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 &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; templates.&lt;/p&gt;


	&lt;p&gt;In code:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;S.?(&quot;mykey&quot;)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;In template:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;lt;lift:loc locid=&quot;mykey&quot;&amp;gt;Default Text&amp;lt;/lift:loc&amp;gt;&lt;/code&gt;&lt;/pre&gt;

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


	&lt;ul&gt;
	&lt;li&gt;Hebrew is a language that is written right-to-left (RTL) so generally the content / css / markup will be quite different&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;So, to deal with such cases Lift brings you comprehensive template localization which we&#8217;ll now discuss.&lt;/p&gt;


	&lt;h2&gt;Template file localization&lt;/h2&gt;


	&lt;p&gt;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 &#8211; based on the LiftRules.localeCalculator Locale that is returned, it can choose the right template. With the problems we face here, we might have:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
index_en_GB.html
index_en_AU.html
index_de.html
index_he.html

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;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&#8230; for arguments sake the imagery in the two templates could be different because Australian culture is somewhat more casual than compared to England.&lt;/p&gt;


	&lt;p&gt;This exact same scheme also applies for &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; resources if you do not need the possibly side effect of code duplication in this system.&lt;/p&gt;


	&lt;h2&gt;Custom resource bundle provider hook&lt;/h2&gt;


	&lt;p&gt;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&#8217;s cycle:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
LiftRules.resourceBundleFactories.prepend { 
  case (basename, locale) if localeAvalible_?(locale) =&amp;gt; 
      CacheResourceBundle(locale)
  case _ =&amp;gt; CacheResourceBundle(new Locale(&quot;en&quot;,&quot;GB&quot;))
}

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;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:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
case class CacheResourceBundle(loc: Locale) extends ResourceBundle

&lt;/pre&gt;&lt;/code&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;Thats pretty much it folks &#8211; 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, &lt;span class=&quot;caps&quot;&gt;RTL&lt;/span&gt; languages and given you all the code you need to get going with localization in Lift &#8211; go forth and localize!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2009-07-20:764</id>
    <published>2009-07-20T11:48:00Z</published>
    <updated>2009-07-20T11:48:34Z</updated>
    <link href="http://blog.getintheloop.eu/2009/7/20/lift-snippet-selection-dispatchsnippet-vs-snippet-reflection" rel="alternate" type="text/html"/>
    <title>Lift snippet selection - DispatchSnippet vs snippet reflection</title>
<content type="html">
            &lt;p&gt;One of the confusing things about &lt;a href=&quot;http://liftweb.net/&quot;&gt;Lift&lt;/a&gt; for new comers are snippets &#8211; 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!&lt;/p&gt;


	&lt;h2&gt;Reflection Snippets&lt;/h2&gt;


	&lt;p&gt;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:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
import _root_.scala.xml.{NodeSeq,Text}

class HelloWorld {
  def speak = &amp;lt;span&amp;gt;Hello World&amp;lt;/span&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I could then just call this in any Lift template I wanted by using the following:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&amp;lt;lift:hello_world.speak /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So right there, with no other plumbing we have a working snippet invocation &#8211; 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 &#8211; 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)&lt;/p&gt;


	&lt;h2&gt;DispatchSnippet to the rescue!&lt;/h2&gt;


	&lt;p&gt;In Scala we can of course use the &lt;code&gt;object&lt;/code&gt; keyword to create a singleton object &#8211; 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:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
import _root_.scala.xml.{NodeSeq,Text}
import _root_.net.liftweb.http.DispatchSnippet

object HelloWorld extends DispatchSnippet {
  def dispatch = { 
    case &quot;talk&quot; =&amp;gt; speak
  }
  def speak = &amp;lt;span&amp;gt;Hello World&amp;lt;/span&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;There is of course a slight downside &#8211; 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 &lt;span class=&quot;caps&quot;&gt;XHTML&lt;/span&gt; what snippet instance we are referring to &#8211; we do this with a SnippetDispatchPF call in your Boot.scala file:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  LiftRules.snippetDispatch.append(
    Map(&quot;hello_world&quot; -&amp;gt; HelloWorld)
  )
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This means in our &lt;span class=&quot;caps&quot;&gt;XHTML&lt;/span&gt; we can call:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&amp;lt;lift:hello_world.talk /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This has the exact same output as the reflection style snippet, but only using a single snippet instance for your application.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.getintheloop.eu/">
    <author>
      <name>timperrett</name>
    </author>
    <id>tag:blog.getintheloop.eu,2009-05-22:710</id>
    <published>2009-05-22T11:39:00Z</published>
    <updated>2009-05-22T12:53:30Z</updated>
    <link href="http://blog.getintheloop.eu/2009/5/22/lift-amqp-with-rabbitmq-and-scala-tutorial-and-screencast" rel="alternate" type="text/html"/>
    <title>Lift AMQP with RabbitMQ and Scala - Tutorial and Screencast</title>
<content type="html">
            &lt;p&gt;Admitidally, every time i&#8217;ve ever looked at the &lt;a href=&quot;http://liftweb.net/&quot;&gt;Lift&lt;/a&gt; codebase in TextMate, i&#8217;ve always wondered what the hell the &#8220;lift-amqp&#8221; 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 &lt;span class=&quot;caps&quot;&gt;AMQP&lt;/span&gt; / RabbitMQ application!&lt;/p&gt;


	&lt;h2&gt;&lt;span class=&quot;caps&quot;&gt;AMQP&lt;/span&gt; you say?&lt;/h2&gt;


	&lt;p&gt;Yup, thats right. &lt;span class=&quot;caps&quot;&gt;AMQP&lt;/span&gt; &#8211; Advanced Message Queuing Protocol to the lay&#8217; man not familiar with the acronym. Essentially &lt;span class=&quot;caps&quot;&gt;AMQP&lt;/span&gt; is an open standard for enterprise messaging. There are several implementations of the standard, namely, &lt;a href=&quot;http://www.openamq.org/&quot;&gt;Open &lt;span class=&quot;caps&quot;&gt;AMQ&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;http://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt; &#8211; the latter is newer and generally considered to be the defacto implementation. Rabbit MQ is written in &lt;a href=&quot;http://erlang.org/&quot;&gt;ERLang&lt;/a&gt; and has clients for Java, .NET, Ruby etc etc.&lt;/p&gt;


	&lt;h2&gt;So where does Lift fit in?&lt;/h2&gt;


	&lt;p&gt;Strictly speaking, it doesn&#8217;t. It just so happens that &lt;a href=&quot;http://twitter.com/stevej&quot;&gt;Steve J&lt;/a&gt; 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, &#8220;lift-amqp&#8221; can be used in any Scala application and has no other dependencies within the Lift framework.&lt;/p&gt;


	&lt;h2&gt;Hand-wavy overview&lt;/h2&gt;


	&lt;p&gt;Lets get down to business&#8230; 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&#8217;t figure out what went where. Being a fairly visual person, I&#8217;ve drawn up a diagram that explains the implementation and how you (yes, you reading this) would implement your application:&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.getintheloop.eu/assets/2009/5/18/lift-amqp.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;h2&gt;A working example?&lt;/h2&gt;


	&lt;p&gt;So rather than try to post lots of pictures &#8211; I thought just putting up a screen-cast explaining the components would make more sense :-)&lt;/p&gt;


&amp;lt;embed allowfullscreen=&quot;true&quot; type=&quot;application/x-shockwave-flash&quot; src=&quot;http://blip.tv/play/AYGD0GoA&quot; allowscriptaccess=&quot;always&quot; height=&quot;305&quot; width=&quot;450&quot;&gt;&amp;lt;/embed&gt;

	&lt;h2&gt;The client listener&lt;/h2&gt;


	&lt;p&gt;So from the diagram above that explains the code layout &#8211; 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&#8217;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&#8217;s the requests. Its a nice feature.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
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(&quot;/data&quot;)
    channel.exchangeDeclare(ticket, &quot;mult&quot;, &quot;fanout&quot;)
    channel.queueDeclare(ticket, queueName)
    channel.queueBind(ticket, queueName, &quot;mult&quot;, &quot;example.*&quot;)
    channel.basicConsume(ticket, queueName, false, 
      new SerializedConsumer(channel, this))
  }
}

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So, your probably thinking that this was not the class that I created an instance of during the screencast &#8211; and you&#8217;d be right. Essentially we still need a wrapper class to mask our dispatcher; the listener proper.&lt;/p&gt;


	&lt;p&gt;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.&lt;/p&gt;


	&lt;h2&gt;The postman&#8230;&lt;/h2&gt;


	&lt;p&gt;So now that you know how the example listens for messages, lets see the posting code&#8230;&lt;/p&gt;


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

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

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Little explanation needed here &#8211; essentially the string sender is just an actor that knows how to respond to AMQPMessage&#8230;. it couldn&#8217;t be simpler! I hope this has proved helpful and a good overview of the lift-amqp module.&lt;/p&gt;


	&lt;p&gt;If you would like to download the source code, you can get it from &lt;a href=&quot;http://github.com/timperrett/rabbitmq-scala-tutorial/tree/master&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
</feed>
