views:

927

answers:

3

Has anybody tried to setup SBT to work with Google App Engine? I dream about using development server auto-reloading after source changes.

+4  A: 

Here is an sbt-appengine-plugin on Github that I'm trying to get to work right now. I will post any progress.

efleming969
+5  A: 

For a quick demo you can clone or download what I have done here.

A minimalistic sbt-appengine-plugin example from scratch

Clone the sbt-appengine-plugin from GitHub

 cd mystuff
 git clone git://github.com/Yasushi/sbt-appengine-plugin.git
 cd sbt-appengine-plugin
 sbt

Publish the plugin locally so that you can use it in your own projects

publish-local
exit

Create a directory for a new project

cd ..
mkdir sbt-appengine-plugin-test
cd sbt-appengine-plugin-test
sbt

Configure the new project

Project does not exist, create new project? (y/N/s) y
Name: sbt-appengine-plugin-test
Organization: com.example
Version [1.0]: 
Scala version [2.7.7]: 2.8.0.Beta1
sbt version [0.7.3]:
exit

Tell sbt about the plugin you want to use

mkdir project/build
mkdir project/plugins
nano project/build/project.scala

project.scala

import sbt._

class AppengineTestProject(info: ProjectInfo) extends AppengineProject(info)

nano project/plugins/plugins.scala

plugins.scala

import sbt._

class Plugins(info: ProjectInfo) extends PluginDefinition(info) {
  val a = "net.stbbs.yasushi" % "sbt-appengine-plugin" % "1.1-SNAPSHOT"
}

Add a very simple servlet

mkdir -p src/main/scala/com/example
nano -w src/main/scala/com/example/HelloWorld.scala

HelloWorld.scala

package com.example;

import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse}

class HelloWorld extends HttpServlet {
  override def doGet(request: HttpServletRequest, response: HttpServletResponse$
    response.setContentType("text/plain")
    response.getWriter.println("Hello, world")
  }
}

Add some more configuration files

mkdir -p src/main/webapp/WEB-INF
nano -w src/main/WEB-INF/web.xml

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 
   xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xm$
   version="2.5">
  <display-name>sbt-appengine-plugin usage example</display-name>
      <servlet>
    <servlet-name>helloworld</servlet-name>
    <servlet-class>com.example.HelloWorld</servlet-class>
  </servlet>
      <servlet-mapping>
    <servlet-name>helloworld</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>


nano -w src/main/WEB-INF/appengine-web.xml

appengine-web.xml

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0"&gt;
<!-- Replace this with your application id from http://appengine.google.com -$
  <application>hello-world</application>
  <version>1</version>
</appengine-web-app>

And finally run sbt and start the project

sbt

update
dev-appserver-start

Point your browser to http://localhost:8080/ and you should see Hello, world

dev-appserver-stop

To watch for changes in source files I have experimented a little with ~prepare-webapp after starting the server, but I haven't gotten it working properly.

Leo Lännenmäki
In the servlet example, did you mean to put the dollar sign on the line that starts "override def doGet"? Surely, that is meant to be a close bracket?
Tom Morris
+2  A: 

You will find an example by the author of the plugin here: http://gist.github.com/377611

Especially in the plugins configuration, the setting of 1.1-SNAPSHOT (mentioned above) or 2.1-SNAPSHOT (mentioned in the sbt-apppengine-plugin README) did not work.

The example shows:

import sbt._

class Plugins(info: ProjectInfo) extends PluginDefinition(info) {
    val appenginePlugin = "net.stbbs.yasushi" % "sbt-appengine-plugin" % "2.0" from "http://github.com/downloads/Yasushi/sbt-appengine-plugin/sbt-appengine-plugin-2.0.jar"
}

And this worked for me.

Det