Archive for March, 2011

6 Mar 2011

by Dave

Javascript compilation for SBT

Over the weekend I knocked up a little SBT plugin to wrap up the Javascript resources in our Lift projects and deploy them as one big minified file. Read on to find out how it works, then grab yourself a copy and take it for a spin.

The plugin scans your webapps directory and looks for files with the extensions .jsm or .jsmanifest. These files, called Javascript Manifests, describe lists of Javascript sources that should be combined into a single file. For example:

# You can specify remote files using URLs...

http://code.jquery.com/jquery-1.5.1.js

# ...and local files using regular paths
#    (relative to the location of the manifest):

lib/foo.js
bar.js

# Blank lines and bash-style comments are also supported

Manifest compilation happens in two phases: first, the plugin downloads and caches any remote scripts specified using URLs. Second, it feeds all of the sources (remote and local) into Google’sClosure Compiler, which concatenates them and minifies everything (and provides excellent services like static type checking to boot). The output from the compiler is a .js file with the same base name and relative path as the original manifest.

There’s not a lot more to it than that. The plugin hooks into SBT’s standard compile and package phases, so your Javascript gets rebuilt automatically alongside your Scala code. If this sounds useful to you, please feel free to grab a copy and take it for a spin. Full details are available in the README on Github.

I should point out that there are other useful SBT plugins that do a similar job. For example, I plagiarised extensively from Jon Hoffman’sYUI Compressor plugin and Luke Amdor’s Coffee Script plugin when writing my code. These two particular examples don’t do file combination, though, and that was an important feature for our specific use case.

Posted in Code, Front page, Javascript, Scala, Web development | Comments Off on Javascript compilation for SBT

2 Mar 2011

by Dave

Setting the run.mode in Lift web apps

Update: You can now set the run mode easy and conveniently using our sbt-runmode plugin for SBT.

Setting the run.mode in Lift applications is the source of a surprising number of questions. The documentation recommends passing it as a parameter when the JVM is invoked. This can be hard to achieve for various reasons. In our case our deployment is automated using Chef, and scripts to start and stop the Jetty web server are installed by the package manager. We don’t really want to monkey around with these scripts, so we had to find another way. Jetty is written in Java, which means it must have a ridiculously complex XML configuration language. The Jetty developers turned it up to 11 by making their configuration language Turing complete, so we can actually set the system properties in a configuration file. The file we want to create isWEB-INF/jetty-web.xml and we want it to contain this:

 

<?xml version=”1.0″?>
<!DOCTYPE Configure PUBLIC “-//Mort Bay Consulting//DTD Configure//EN” “http://jetty.mortbay.org/configure.dtd”>
<Configure class=”org.mortbay.jetty.webapp.WebAppContext”>
<Call class=”java.lang.System” name=”setProperty”>
<Arg>run.mode</Arg>
<Arg>production</Arg>
</Call>
</Configure>

 

If we leave this around then our application will always run in production mode. We don’t want this when we’re developing as we won’t, for instance, get stack traces printed to the browser. Thus we should copy this file in when we package up the project, and remove it when the packaging step completes. Assuming you’re using SBT, store the above text in project/jetty-web.xml and add the following to your SBT project file to get this functionality:

 

val jettyWebPath = “src” / “main” / “webapp” / “WEB-INF” / “jetty-web.xml”
lazy val installProductionRunMode = task {}
FileUtilities.copyFile(“project” / “jetty-web.xml”,
jettyWebPath,
log)
log.info(“Copied jetty-web.xml into place”)
None
describedAs(“Install a jetty-web.xml that sets the run mode to production”)
lazy val superPackage = super.packageAction dependsOn(installProductionRunMode)
lazy val removeProductionRunMode = task {}
FileUtilities.clean(jettyWebPath, log)
None
describedAs(“Remove jetty-web.xml and hence set run mode back to testing”)
override def packageAction = removeProductionRunMode dependsOn(superPackage) describedAs BasicWebScalaProject.PackageWarDescription

 

This is pretty simple code. Basically it redefines the package action to first copy in the jetty-web.xml file, then it runs the original package action, and finally it deletes the jetty-web.xml. Now any WARfiles you run under Jetty will automatically be in production mode, but callingsbt jetty-run will still give you development mode.

Posted in Code, Scala, Web development | Comments Off on Setting the run.mode in Lift web apps