Thursday, October 11, 2012

Performance Optimization in Lift framework when using Surround and Embed Tags

I worked on a Lift 2.4 web application that used lot of Surround and Embed tags in HTML files. Looking in the LiftSession we can see that lift repeats the merging process again for every request received. This is not required and significant performance can be gained when we cache a merged HTML template and process that instead of evaluating "surround" and "embed" tag on every request. If you enable TemplateCache, then this new cache below will act like a cache one level up in the hierarchy. Note that its a good idea to enable/use this cache only in production mode to not to hinder development activities.

There are multiple ways to implement this. The one I will explain here is by extending the LiftSession class and overriding the processTemplate method. But, if you have a custom content handler DispatchPF appended to lift dispatch, and you do some more stuff before calling the processTemplate yourself then you can add this caching in this class too. The code is very different when compared to the first approach and will try to provide at the end.

First thing to do is to define a synchronized cache that is used to cache the processed templates. The code below is self explanatory. Note that most of the code to follow is copied from Lift and modified to serve the desired purpose.

* A synchronized cache that handles the caching of Processed Templates in production mode only. The strategy used
* is Least Recently Used caching.
object ProcessedTemplateCache{
private val cache : LRU[String, NodeSeq] = new LRU(50)

def get(key: String): Box[NodeSeq] =
cache.synchronized {
else Empty

def set(key: String, node: NodeSeq): NodeSeq =
cache.synchronized {
cache(key) = node
else node

def has(key:String):Boolean =
cache.synchronized {
else false

def delete(key: String) {

We need to split a NodeSeq to its components to use it in the CustomLiftSession to be defined later. This is done using pattern matching in scala.

* A decompressor that expands a Node to its characteristics.
* Ther order being - element, kids, isLazy, attrs, snippetName
private object CachedSnippetNode {
def unapply(baseNode: Node): Option[(Elem, NodeSeq, Boolean, MetaData, String)] =
baseNode match {
case elm: Elem if elm.prefix == "lift" || elm.prefix == "l" => {
Some((elm, elm.child,
elm.attributes.find {
case p: PrefixedAttribute => p.pre == "lift" && (p.key == "parallel")
case _ => false
elm.attributes, elm.label))
case _ => {

Now, lets extend the LiftSession class. Note that, many methods in LiftSession is private and hence not accessible. The only way around the problem is by pulling them in the new CustomLiftSession implementation. So, here the version is very important. The code below uses the LiftSession from 2.4 codebase. Lift 2.5 has modification/extensions to this. I understand this as a bad idea as the methods pulled in from the LiftSession class may be modified in future and HAS to be synched up manually when required, but there is not much we can do using this approach due to private modifiers in the LiftSession class. Note that all the code is written in package net.liftweb.http.

class CustomLiftSession(_contextPath: String, uniqueId: String,
httpSession: Box[HTTPSession]) extends LiftSession(_contextPath, uniqueId, httpSession){
//This val is copied as is from the super class, as it is private and not accessible from here.
private object overrideResponseCode extends TransientRequestVar[Box[Int]](Empty)

//This val is copied as is from the super class, as it is private and not accessible from here.
private val fullPageLoad = new ThreadGlobal[Boolean] {
def ? = openOr false

* This method is copied as is from the super class, as method is private and not accessible from here.
* @param path The path to parse
* @param session The session in which this is invoked
* @return
private[http] def findVisibleTemplate(path: ParsePath, session: Req): Box[NodeSeq] = {
val tpath = path.partPath
val splits = tpath.toList.filter {
a => !a.startsWith("_") && !a.startsWith(".") && a.toLowerCase.indexOf("-hidden") == -1
} match {
case s@_ if (!s.isEmpty) => s
case _ => List("index")
Templates(splits, S.locale)

* This method is responsible to do preProcessing cachedSurround and embed tags. Only these tags and any
* of the same tags in its child nodes are processed. No other snippets are evaluated. The reason to do this
* is to cache the merged pages one level up so that the merging "surround" and "merge" does not
* occur every time.
* @param page The page name if any.
* @param xhtml The page as an XML
* @return
def preProcess(page:String, xhtml:NodeSeq): NodeSeq = {
def processSurroundAndInclude1(page: String, in: NodeSeq): NodeSeq = {
in.flatMap {
case Group(nodes) =>
Group(processSurroundAndInclude1(page, nodes))
//Only process cachedSurround and embed snippets
case CachedSnippetNode(element, kids, isLazy, attrs, snippetName)if(snippetName == "cachedSurround" || snippetName == "embed") =>
S.doSnippet(snippetName) {
S.withAttrs(attrs) {
element, attrs,

case v: Elem =>
Elem(v.prefix, v.label, v.attributes,
v.scope, processSurroundAndInclude1(page, v.child): _*)

case pcd: scala.xml.PCData => pcd
case text: Text => text
case unparsed: Unparsed => unparsed

case a: Atom[Any] if (a.getClass == classOf[Atom[Any]]) => new Text(

case v => v
processSurroundAndInclude1(page, xhtml)

* The custom process template method that tries to use the cached preprocessed lift template, if not then caching one for the first time.
* Every successive process template will use the merged template from the cache. This decreases one level of processing on
* every request.
* @param template The real unprocessed template
* @param request The request that wants the processed template
* @param path The path to search for the template
* @param code Override response code if any
* @return
override def processTemplate(template: Box[NodeSeq], request: Req, path: ParsePath, code: Int): Box[LiftResponse] = {
overrideResponseCode.doWith(Empty) {
(template or findVisibleTemplate(path, request)).map {
xhtml =>
fullPageLoad.doWith(true) {
val path = S.request.get.path.wholePath.mkString("/")
//Phase 0: Preprocess cachedSurround and embed or get the preprocessed page from the cache
val preXML: NodeSeq = if(ProcessedTemplateCache.has(path))ProcessedTemplateCache.get(path).get
else ProcessedTemplateCache.set(path, preProcess(PageName get, xhtml) )
//---- Everything below here is as in the real Lift 2.4 codebase.
// allow parallel snippets
// Phase 1: snippets & templates processing
val rawXml: NodeSeq = processSurroundAndInclude(PageName get, preXML)
// Make sure that functions have the right owner. It is important for this to
// happen before the merge phase so that in merge to have a correct view of
// mapped functions and their owners.
updateFunctionMap(S.functionMap, RenderVersion get, millis)

// Clear the function map after copying it... but it
// might get some nifty new functions during the merge phase

// Phase 2: Head & Tail merge, add additional elements to body & head
val xml = merge(rawXml, request)

// But we need to update the function map because there
// may be addition functions created during the JsToAppend processing
// See issue #983
updateFunctionMap(S.functionMap, RenderVersion get, millis)

notices = Nil
// Phase 3: Response conversion including fixHtml
LiftRules.convertResponse((xml, openOr code),
S.getHeaders(LiftRules.defaultHeaders((xml, request))),

Now, lets define a custom snippet dispatcher for a new tag "cachedSurround" that will be used instead of the "surround" tags in the HTML templates.

* The snippet dispatcher that handles the "cachedSurround" lift tag.
object CachedSurround extends DispatchSnippet {

def dispatch : DispatchIt = {
case _ => render _

def render(kids: NodeSeq) : NodeSeq =
(for {
ctx <- S.session ?~ ("FIX"+"ME: Invalid session")
req <- S.request ?~ ("FIX"+"ME: Invalid request")
} yield {
WithParamVar.doWith(Map()) {
val mainParam = (S.attr("at") openOr "main", ctx.asInstanceOf[CustomLiftSession].preProcess(PageName.get, kids)) //Do preprocess only, do not evaluate snippets right now
val paramsMap = WithParamVar.get + mainParam
ctx.findAndMerge(S.attr("with"), paramsMap)
}) match {
case Full(x) => x
case Empty => Comment("FIX"+ "ME: session or request are invalid")
case Failure(msg, _, _) => Comment(msg)

Next in Boot.scala you will add the following code that will allow lift to use CachedSurround dispatcher when it encounters the "cachedSurround" lift tag(<lift:cachedSurround with="default" at="pageContent">...</lift:cachedSurround>) and use our CustomLiftSession that does the preprocessing and caching of merged templates (with cachedSurround and embed tags only) in production mode.

Map("cachedSurround" -> CachedSurround)

LiftRules.sessionCreator = {
case (httpSession, contextPath) => new CustomLiftSession(contextPath, httpSession.sessionId, Full(httpSession))

Now, many of this code can be avoided if you have a separate content handler dispatcher (this is added again in Boot.scala as LiftRules.dispatch.append(ContentHandler.dispatch)). Note that, this is the way if you want to do more before you process templates or load templates from some other place. I wont go into that detail, but if you do this then you will call the processTemplate on the session manually. So, this is what you can do in that case. Create the below code in net.liftweb.http package. When using below you do not need to extend LiftSession class nor create any new snippet dispatcher (whether you use surround or cachedSurround as in the comments below).

object Expand{
private lazy val logger = Logger(this.getClass)

def apply(template:NodeSeq) : NodeSeq = {
case Group(nodes) => apply(nodes)
case CachedSnippetNode(element, kids, isLazy, attrs, snippetName)if(snippetName == "cachedSurround") => //This part is modified from Surround.scala lift code. Also you can use "surround" directly here if you dont want to create a new lift tag.
(for (ctx <- S.session ?~ ("FIX ME: Invalid session")) yield {
val mainParam = Map(attrs.asAttrMap("at") -> kids)
ctx.findAndMerge(Full(attrs.asAttrMap("with")), mainParam)
}) match {
case Full(x) => apply(x)
case Empty => Comment("FIX ME: session or request are invalid")
case Failure(msg, _, _) => Comment(msg)
case CachedSnippetNode(element, kids, isLazy, attrs, snippetName)if(snippetName == "embed") =>//This part is modified from Embed.scala lift code
(for {
ctx <- S.session ?~ ("FIX ME: session is invalid")
templateOpt <- ctx.findTemplate(attrs.asAttrMap("what")) ?~ ("FIX ME the embed tag has what="+attrs.asAttrMap("what")+" which is not found")
} yield (attrs.get("what"),LiftSession.checkForContentId(templateOpt))) match {
case Full((what,template)) => {
val bindingMap : Map[String,NodeSeq] = Map(kids.flatMap({
case p : scala.xml.PCData => None // Discard whitespace and other non-tag junk
case t : scala.xml.Text => None // Discard whitespace and other non-tag junk
case e : Elem if e.prefix == "lift" && e.label == "bind-at" => {
e.attribute("name") match {
/* DCB: I was getting a type error if I just tried to use e.child
* here. I didn't feel like digging to find out why Seq[Node]
* wouldn't convert to NodeSeq, so I just do it with fromSeq. */
case Some(name) => Some(name.text -> NodeSeq.fromSeq(e.child))
case None => logger.warn("Found <lift:bind-at> tag without name while embedding \"%s\"".format(attrs.asAttrMap("what"))); None
case _ => None
}): _*)

BindHelpers.bind(bindingMap, template)
case Failure(msg, _, _) => throw new SnippetExecutionException(msg)

case _ => throw new SnippetExecutionException("session is invalid")

case v: Elem =>Elem(v.prefix, v.label, v.attributes,
v.scope, apply(v.child): _*)

case pcd: scala.xml.PCData => pcd
case text: Text => text
case unparsed: Unparsed => unparsed

case a: Atom[Any] if (a.getClass == classOf[Atom[Any]]) => new Text(

case v => v

And in your content handler dispatcher, you will use it like this.

val pathParams = S.request.get.path.wholePath
Templates(pathParams) match {
case Full(template) => {
val path = S.request.get.path.wholePath.mkString("/")
val preXML: NodeSeq = if(ProcessedTemplateCache.has(path))ProcessedTemplateCache.get(path).get
else ProcessedTemplateCache.set(path, Expand(template))
S.session.get.processTemplate(Full(preXML), S.request.get, S.request.get.path, 200)
case _@Empty => logger.error("Parsing empty content while loading %s template.".format(filePath))
case error: Failure => logger.error(error)

This will improve the performance significantly on long run in production mode as you already have cached templates that are expanded and merged from cachedSurround and embed tags. Note that this improvement is conditional upon the number of templates you use, and the amount of cachedSurround and embed tag in work. Just to make it simple, I am providing the package and the imports below.

package net.liftweb
package http

import xml._

import net.liftweb._
import net.liftweb.common._
import Box._
import util._
import Helpers._
import builtin.snippet._
import provider._
import xml.Group
import scala.Some
import xml.Text

Thursday, June 28, 2012

Secure Remote Password Protocol in Scala

I was very interested in authentication and bumped against SRP. SRP is a protocol that helps in achieving authentication and is defined at Since, I did not see any implementation of this in my current fav programming language- Scala, I decided to write a small scala based SRP v6a implementation. The code is hosted on Github at and is MIT licensed opensource. Feel free to contribute. I have provided an example implementation using Play 2.0 web framework. This is hosted at The client is authenticated by server, then client authenticates that its speaking to the right server and finally continues to get the secret page over AES 128bit PBE encrypted channel. Since, just scala server side code is not sufficient- there is also srp.js that tags along for the client side javascript. The code scala and JS is small and can be easily understood. Just implement SRPServer trait and you are good to go. The example play 2.0 app provides a sample implementation- ExampleSRPServer.scala. This uses file for storage, you can use DB or any other destination for storage. The usage of javascript is provided as example in login.scala.html. It shows a very cleanly the data that is exchanged between client and server. This is how the example app works. These are just important code snippets. Look in Github for the complete code.

var aVal = a();
var Aval = A(aVal);
var AvalHex = Aval.toHexString();
var username = $('#txtUsername').val();
var password = $('#txtPassword').val();

Client gets a, Aval, username, password for the current session.
url: '/login',
type: 'POST',
data: {"username" : username, "A" : AvalHex}

Client posts username and A to the server.
val Aval = params.get("A")
val username = params.get("username")

Server gets the A and username from request.
val result = ExampleSRPServer.getSessionWithClientParameters(username(0), Aval(0))
val (sessionId, hSessionId, s, bvalStr) = result.get
ExampleSRPServer.saveSession(username(0), sessionId, hSessionId)
println(">>> session id: " + sessionId)
Ok(s + "," + bvalStr)//Return the salt s and calculated value B
Ok("Error: Authentication Failure")

Server calculates the expected session id. There are some more authentication is real code. If the results are defined then save the current session, return s and bvalStr. Refer to SRP design to understand these parameters.
var exch1 = data.split(",")
var Sval = currentSession(exch1[0], exch1[1], aVal, Aval, password)
setCookie("username", username);

From the data received from server, client gets the current session. At this point, server has authenticated the client. Now, we need to make sure we are speaking to the right server.
function validateServer(){
var username = getCookie("username");
Khex = K(sessionId)
var Mval = M(Khex)
var verifier = serverVerifier(Mval, Khex)

url: '/validateServer',
type: 'GET',
data: {"username" : username, "K" : Mval}

Client set the Khex, and the Mval for the current session. It posts username and Mval to server. The response from server must match the serverVerifier generated.
def validateServer(username:String, M:String) = Action(implicit request =>{
import srp._
val (sessionId, hSessionId) = ExampleSRPServer.getSessionWithHash(username)
if(BigInt(ExampleSRPServer.M(hSessionId), 16).equals(BigInt(M,16))){
Ok("Error: Authentication Failure. M mismatch.")

The server returns the verifier. The server and client have authenticated to each other. K has never been sent over the wire, so we use K as secret key for this session to encrypt data exchange between server and client. This is shown in method- getTheSecretPage() in login.scala.html. On the server side check Auth.scala for AES magic. The enc method on the server side does the job in scala.
def enc(username:String, sessionId:String, page:String) = 
EncryptedAuthenticatedPage(username, sessionId, page){decrypted =>
decrypted._3 match {
case "secret" => Ok(decrypted._5(views.html.secret().body))
case _ => NotFound(<h1>Page not found</h1>)

Saturday, March 31, 2012

Gradle wrapper behind a proxy

I was trying to setup gradle wrapper to work with Teamcity behind a proxy but only to realize that gradle wrapper was not using the java proxy options I was providing in command line. I decided to tweak the and gradlew.bat a little to make it use the proxy so that I can provide proxy options in teamcity console when I configure the build step using gradlew. I don’t have access to build agents to configure gradle with properties file. Insert the below code in batch and shell script at a place between the first line and last line (Just before the invocation of GradleWrapperMain). If you put below pieces of code at wrong place then this will not work.
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Add default JVM options by parsing command line. Anything starting with -D is option to java.
set _OPTION=%1
set prefix1=%_OPTION:~0,2%
if "%prefix1%" == "-D" (
if not "%~1"=="" goto SYSTEM_PROPS_EXTRACT

echo Default JVM Options: %DEFAULT_JVM_OPTS%
@rem Execute Gradle
-classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

Shell Script changes

#Add default JVM options by parsing command line arguments.
#Anything starting with -D is passed to JVM also.
for var in "$@"
if [[ $prefix == "-D" ]] ; then

# Split up the JVM_OPTS And GRADLE_OPTS values into an array,
# following the shell quoting and substitution rules
function splitJvmOpts() {

echo "JVM_OPTS :""${JVM_OPTS[@]}"
exec "$JAVACMD" "${JVM_OPTS[@]}"
-classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

And finally the proxy option to use gradlew build -Dhttp.proxyPort=80 -Dhttp.proxyUser=user1 -Dhttp.proxyPassword=user1 -Dhttp.auth.ntlm.domain=COMMON

Wednesday, January 04, 2012

Run Jetty in eclipse with scalatra

Though this is very simple and straight forward, there is no direct answer to this question on internet. You can run any webapp in eclipse using this approach, not necessarily with scalatra. The code is available for Lift web framework and works well with scalatra too.

import org.eclipse.jetty.server.Server
import org.eclipse.jetty.webapp.WebAppContext

object RunWebApp {
def main(args: Array[String]) {
val server = new Server(9080)
val context: WebAppContext = new WebAppContext();

try {
} catch {
case ex: Exception => {