I’m getting back into the game a little bit, and I decided to take a look at Lift for web development. After an initially promising experience, I became totally unhappy with Eclipse (it began forgetting I had Google App Engine libraries on the classpath after every clean). So I moved back to the command line. The recommendation to use Simple Build Tool or Maven for Lift put me off: SBT is pretty weak for a build tool, and Maven is…well…Maven, off to download the Internet. So I went back to Gradle.
For the record, I’m using Objectify for my Google App Engine development, because JPA gets you into that whole ugly ORM conceptual space without need: there’s no “R” in GAE, so you might as well deal with it in a more natural way.
So, given that situation, I came up with this build.gradle script. (Forgive the ugly organization, but this is actually the relevant points extracted from a multi-project build.)
buildscript { repositories { mavenCentral() add(new org.apache.ivy.plugins.resolver.URLResolver()) { name = 'GitHub' addArtifactPattern 'http://cloud.github.com/downloads/[organisation]/[module]/[module]-[revision].[ext]' } } dependencies { classpath "bmuschko:gradle-gae-plugin:$gaePluginVersion" } } apply plugin:'java' // Buildscript dependencies and repositories repositories { mavenCentral() mavenRepo name:'scala-releases', url:'http://scala-tools.org/repo-releases/' mavenRepo name:'objectify-appengine-releases', url:'http://objectify-appengine.googlecode.com/svn/maven' mavenRepo name:'sonatype-releases', url:'http://oss.sonatype.org/content/repositories/releases/' mavenRepo name:'sonatype-snapshots', url:'http://oss.sonatype.org/content/repositories/snapshots/' add(new org.apache.ivy.plugins.resolver.URLResolver()) { name = 'GitHub' addArtifactPattern 'http://cloud.github.com/downloads/[organisation]/[module]/[module]-[revision].[ext]' } } // Universal dependencies dependencies { compile "org.encog:encog-core:$encogVersion", "com.google.guava:guava:$guavaVersion", "commons-lang:commons-lang:$commonsLangVersion", "org.apache.commons:commons-lang3:$commonsLang3Version", "commons-io:commons-io:$commonsIoVersion", "commons-collections:commons-collections:$commonsCollectionsVersion", "org.slf4j:slf4j-api:$slf4jVersion", "org.slf4j:slf4j-simple:$slf4jVersion" testCompile "junit:junit:4.5" } // Now the Scala stuff apply plugin: 'scala' dependencies { scalaTools "org.scala-lang:scala-compiler:$scalaVersion", "org.scala-lang:scala-library:$scalaVersion" compile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scala-tools.testing:specs:1.6.1", "org.scala-lang:scala-compiler:$scalaVersion" } apply plugin:'war' dependencies { compile "net.liftweb:lift-webkit_$scalaVersion:$liftVersion", "net.liftweb:lift-mapper_$scalaVersion:$liftVersion", "net.liftweb:lift-json_$scalaVersion:$liftVersion", "net.liftweb:lift-util_$scalaVersion:$liftVersion", "net.liftweb:lift-common_$scalaVersion:$liftVersion" testCompile 'org.mortbay.jetty:jetty-util:6.1.22', 'org.mortbay.jetty:jetty-management:6.1.22' providedCompile 'javax.servlet:servlet-api:2.5' } apply plugin: 'gae' dependencies { compile "com.googlecode.objectify:objectify:$objectifyVersion" gaeSdk "com.google.appengine:appengine-java-sdk:$gaeVersion" } gae { downloadSdk = true disableUpdateCheck = true // Error with HTTPS appcfg { email = 'smokejumperit@gmail.com' logs { append = true severity = 1 ouputFile = file('build/logs.txt') } } }
I stash versions in the gradle.properties file, which looks like this (it’s a lot more details than you actually need):
scalaVersion = 2.9.1 liftVersion = 2.4-RC1 gaePluginVersion = 0.5.2 objectifyVersion = 4.0a2 guavaVersion = 11.0.1 commonsLang3Version = 3.1 commonsLangVersion = 2.6 commonsIoVersion = 2.1 commonsCollectionsVersion = 3.2.1 encogVersion = 3.1.0-SNAPSHOT androidPluginVersion = 1.1.0 slf4jVersion = 1.6.4 gaeVersion = 1.6.1
If you start Lift up at this point (using gradle gaeRun), there are errors about Lift not having permission to mess with the thread pool.
Now, here’s the amazing magic trick which I found documented nowhere but discovered while digging through the Lift source code. It’s an astounding and miraculous trick which is necessary in order to get Lift to work on Google App Engine.
In the file ./src/main/resources/props/default.props, make sure to have this set:
inGAE=true
That’s it. You do that, Google App Engine works. You don’t do that, it won’t. Magic!
Related posts: