Open Credo

February 15, 2012 | Cloud

Deploying Lift Applications to Cloud Foundry

As part of a recent project, I have been working on a number of Scala/Lift applications that we are hosting on a private Cloud Foundry instance.

In this blog post I would like to talk about some practical aspects of developing and deploying Lift applications to Cloud Foundry.

Out of the box, Cloud Foundry is able to run simple Lift applications smoothly. Things however become more interesting if your application needs to talk to one of the available services on Cloud Foundry, such as a relational or a NoSql store.

WRITTEN BY

Tareq Abedrabbo

Tareq Abedrabbo

Deploying Lift Applications to Cloud Foundry

Two options are possible in this case: either to use the Cloud Foundry API programmatically, or to take advantage of the so called auto configuration mechanism.

Simply put, auto configuration allows your existing Lift application to connect to one of the hosted services (almost) unaltered. While this might look compelling at first, auto configuration suffers from a number of limitations that you need to be aware of before making your choice.

First, you can only bind to one and only one service using auto configuration. And the only supported service type is MySql, at least currently. In addition to that, the auto configuration mechanism does not cohabit very well with the Lift’s property loading mechanism and run modes but we will be tackling this particular problem shortly.

The main advantage of auto configuration is that it allows you to get started very quickly. It could also be a viable option if you know that your application will be content enough with a single MySql database.

In all the other cases, you should use the Cloud Foundry API, which at the cost of writing some extra code provides a much more flexible alternative.

How Auto Configuration Works

First, a quick reminder of how Lift properties work. Lift can look up property files in certain locations, picking the most specific configuration file depending on any combination of the current run mode, hostname and user.

For example, you can have a local configuration file that points to an in-memory H2 database while in development mode, and a specific production mode configuration file that points to a different production database depending on the host.

On startup, Lift will inspect all the available files and will pick the most specific one.

Your database connection code then does not need to worry about its environment as Lift will make available the appropriate set of properties at start up.

If you go with auto configuration mechanism, Cloud Foundry will dynamically create a props file based on the user and host names and inserts in Lift’s look up path.

When Lift scans for configuration files at start up, and assuming you are running in the default development mode, it will pick the generated props file since it is the most specific one it can find (because of the combination of the user and host names).

The result of that is that your database initialisation code will connect to the desired database instance. Unfortunately, this also means that all your other configuration properties will become hidden to Lift.

We can fix this by modifying how Lift loads properties, which is something Lift allows to do fairly easily by overriding Props.whereToLook.

The idea is load properties in a hierarchal way: every property file that matches the current environment is loaded but properties defined in more specific files mask those defined in less specific ones.

Chaining properties is also a generally useful way of organising and sharing properties across different runtime environment.

Let’s create an object Here’s how the chained property look up can be implemented:

import net.liftweb.util.Props
import java.util.Properties
import java.io.{ByteArrayInputStream, StringWriter}
import net.liftweb.common.{Box, Logger}

object ChainedProps extends Logger {

    private lazy val _modeName = dotLen(Props.modeName)
    private lazy val _userName = dotLen(Props.userName)
    private lazy val _hostName = dotLen(Props.hostName)

    private lazy val toTry: List[String] = {
        val locations = List(
            "/props/" + _modeName + "default.",
            "/props/" + _modeName + _hostName,
            "/props/" + _modeName + _userName,
            "/props/" + _modeName + _userName + _hostName)
        if (_modeName.isEmpty) locations
        else "/props/default." :: locations
    }.map(_ + "props")

    def init {
        val props = new Properties
        toTry.foreach {
            f =>
                try {
                    props.load(getClass.getResourceAsStream(f))
                    debug("[%s] loaded".format(f))
                } catch {
                    case e => debug("file [%s] could not be loaded".format(f))
                }
        }

        Props.whereToLook = () =>
                    List("_generated_combined_properties.props" -> (() => Box(toInputStream(props))))
    }

    private def toInputStream(Properties props): InputStream = {
        val writer = new StringWriter
        props.store(writer, "")
        new ByteArrayInputStream(writer.toString.getBytes)
    }

    private def dotLen(in: String): String = in match {
        case null | "" => in
        case x => x + "."
    }
}

 

You will need to call ChainedProps.init in your Boot class first thing, before properties are first accessed. Now the file inserted by Cloud Foundry will no longer mask the other props files as it will simply become part of the configuration chain.

Setting The Run Mode

Another issue with the auto configuration mechanism is that it fails if you are not running your the application in the default development mode.

However, running your Lift application in that mode in production is not a good idea because Lift will not apply a certain number of optimisation (such as caching snippets ) unless in production mode, and on top of that all your stack traces will be visible to your end users.

To make it work, we will need to slightly modify the ChainedProps object by adding the auto configuration props file location to our properties whatever the run mode is.

This can be done simply by conditionally prepending the following location: “/props/” + Props.userName + “.” + Props.hostName + “.props” to the toTry list if we are running on Cloud Foundry (which can be detected if one of the preset VCAP environment variables is present).

Now we can set the run mode by using Cloud Foundry’s JAVA_TOOL_OPTIONS environment variable.

To set the run mode to production, you need first to push your application without starting it:

vmc push myapp --no-start

 

Then we can set the environment variable:

vmc env-add myapp JAVA_TOOL_OPTIONS=-Drun.mode=production

 

And finally start the application:

vmc start myapp

 

RETURN TO BLOG

SHARE

Twitter LinkedIn Facebook Email

SIMILAR POSTS

Blog