I recently spent some time trying to abstract away some of the
incidental complexity of using Google App Engine with Clojure. Right
now, setting up interactive development and understanding what to do
requires reading several blog posts, and pasting in a lot of
boilerplate code. I ended up making a small library, called appengine-
magic, which cuts the boilerplate down to (1) a single additional .jar
dependency, (2) a couple of macros, and (3) a couple of files
generated by a Leiningen plugin. It takes a Ring handler, and turns it
into an application suitable for App Engine.
http://github.com/gcv/appengine-magic
It doesn't do everything yet, but I feel that it already makes a much
easier starting point than any alternative. The README file explains
the details.
Unfortunately, I hit a major stumbling block. Live deployment to App
Engine does not work because of a dependency importing a blacklisted
class.
appengine-magic expects to deploy a Ring handler. This makes it
possible to write apps using any Ring-compliant Clojure web framework.
In order to deploy to App Engine, it needs to turn the handler into a
servlet. The ring-servlet library does this with its handy
ring.util.servlet/defservice function. The implementation of
defservice uses duck-streams/copy. duck-streams imports
java.net.Socket, a class blacklisted by App Engine, causing deployment
to fail.
So any innocuous dependency, which transitively depends on anything
which loads a file which imports a blacklisted class, can cause
deployment to fail. Even Clojure itself is not entirely safe: for
example, duck-streams is now
clojure.java.io, which imports
java.net.Socket.
I can reimplement defservice, and so avoid depending on ring-servlet.
Still, the situation seems fragile and precarious. Suggestions and
comments welcome.