July 22, 2011
filed in the early afternoon by dirk husemann in: hacking
technorati tags:
QR code for this entry · average time to read 0:51 minutes

it turns out that the sbt/web-plugin configuration i described in my last post is not quite cutting it. what we observed is that while changes to the contents of the webapp subtree were indeed effective immediately1 sbt commands like prepare-webapp and jetty-reload would sometimes work and sometimes just ignore us.

so, back to digging around in the web-plugin sources and this is what we are now using:

temporaryWarPath <<= (sourceDirectory in Runtime) / "webapp",
// watch temporaryWarPath / WEB-INF / classes
jettyScanDirs <<= (temporaryWarPath) { (target) => Seq(target / "WEB-INF" / "classes") },

this sbt configuration tells jetty to run out of the src/main/webapp directory — any changes you do in there will become effective immediately and prepare-webapp and jetty-reload are working as expected. the drawback is that your generated classes and lib files get copied to src/main/webapp/WEB-INF :-( i know, sucks, but still better than having to restart your webapp everytime you change a {html,css,js} file. if you are using git you might want to add

src/main/webapp/WEB-INF/lib/*
src/main/webapp/WEB-INF/classes/*

to your top-level .gitignore file.


  1. on browser reload, that is. 

all content posted on these pages is an expression of my own mind. my employer is welcome to share these opinions but then again he might not want to.
July 4, 2011
filed in the early afternoon by dirk husemann in: hacking
technorati tags:
QR code for this entry · average time to read 1:10 minutes

the solution described below turns out to have its flaws and is not really recommended — have a look at the recently posted update for a better solution!

simple build tool 0.7.5 comprised the jetty and webapp functionality — version 0.10.0 (sbt10) no longer does so, instead you have to pull in the sbt webplugin. one feature of sbt7.5′s webapp support that we used heavily was the ability to run jetty out of the source tree instead of the exploded temporary WAR file:

Another possibility is to directly run the web application out of the the source web application path:

 override def jettyWebappPath  = webappPath
 override def scanDirectories = mainCompilePath :: testCompilePath :: Nil

— sbt7.5, continuous redeployment

(we actually used to set scanDirectories to Nil)

achieving the same setup with sbt10 is not as simple or even obvious, the solution reported in the simple build tool newgroups does not really provide the same feature, as it still requires to have a ~ prepare-webapp running in sbt. here’s what seems to work:

// run jetty from source tree
jettyConfiguration <<= (sourceDirectory in Runtime, jettyConfiguration) map { 
    (sourceDir, jettyConf) => {
        val conf = jettyConf.asInstanceOf[DefaultJettyConfiguration] 
        new DefaultJettyConfiguration { 
            def classpath = conf.classpath
            def jettyClasspath = conf.jettyClasspath
            def war = sourceDir / "webapp"
            def contextPath = conf.contextPath
            def classpathName = conf.classpathName
            def parentLoader = conf.parentLoader
            def scanDirectories = conf.scanDirectories
            def scanInterval = conf.scanInterval
            def port = conf.port
            def log = conf.log
            def jettyEnv = conf.jettyEnv
            def webDefaultXml = conf.webDefaultXml
        }
    }
}

// set jetty scan dirs to empty list
jettyScanDirs := Nil

changes in src/main/webapp are immediately effective for the running jetty instance. voila!

all content posted on these pages is an expression of my own mind. my employer is welcome to share these opinions but then again he might not want to.