Monday, December 14, 2009

Scala Lift, Jetty 6, static content, and Virtual Directories

I have a simple web application written using the Lift framework. I am using Maven to build and test with, in the way recommended by various Lift docs (i.e. I use mvn jetty:run to launch the app). I ran into an issue when it came to serving static image content, however.

  • The app is called webapp
  • The app deploys to /webapp
  • Images are on local disk at /hdd/data/images (i.e. not in the .war)
  • Want to access images from /images (i.e. outside of the context root of the Lift app)
  • Needs to work when developing and running with Maven's jetty:run

The main issue was simply "how do I setup a virtual directory from http://server/images to /hdd/data/images on disk?" This seems trivial, but I had a really difficult time finding any straightforward docs on how to do it. My complicating requirement was that it had to work when developing with jetty:run. For "real" deployment, the images location will be manually configured, so whether this makes sense in production is not a factor here.

Long story short: you can configure the maven-jetty-plugin to load up additional "context handlers" at startup. Some decent info on this here. A context handler of type WebAppContext will do the job as far as acting like a virtual directory. Here's the config from pom.xml for the project:

<plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <configuration>
        <contextPath>/webapp</contextPath>
        <scanIntervalSeconds>0</scanIntervalSeconds>
        <contextHandlers>
            <!-- setup a simple webapp to serve our images -->
            <contextHandler implementation="org.mortbay.jetty.webapp.WebAppContext">
                <contextPath>/images</contextPath>
                <resourceBase>/hdd/data/images</resourceBase>
            </contextHandler>
        </contextHandlers>
    </configuration>
</plugin>

I make no claims about this being secure or the best way to do things, but after a lot of trial and error it does at least work.

1 comment: