The appengine-magic library attempts to abstract away the infrastructural nuts and bolts of writing a Clojure application for the Google App Engine platform.
The development environment of Google App Engine for Java expects pre-compiled classes, and generally does not fit well with Clojure's interactive development model. appengine-magic attempts to make REPL-based development of App Engine applications as natural as any other Clojure program.
- Programs using appengine-magic just need to include appengine-magic as a Leiningen dev-dependency.
- appengine-magic takes a Ring handler and makes it available as a servlet for App Engine deployment.
- appengine-magic is also a Leiningen plugin, and adds several tasks which simplify preparing for App Engine deployment.
- Clojure 1.2.0
- Leiningen 1.3.1
- Google App Engine SDK 1.3.7
- swank-clojure 1.2.1 (optional)
You need a copy of the Google App Engine SDK installed
somewhere. appengine-magic cannot replace its
rm src/<project-name>/core.cljto clean out the default
core.cljfile created by Leiningen.
:namespaces [<project>.app_servlet](or use the equivalent
[appengine-magic "0.1.1]to your
lein appengine-new. This sets up four files for your project:
app_servlet.clj(the entry point for the application),
resources/war/WEB-INF/web.xml(a servlet descriptor), and
resources/war/WEB-INF/appengine-web.xml(an App Engine application descriptor). These files should contain reasonable defaults for your application.
.gitignore file produced by Leiningen works well with the
resulting project, but do take a careful look at it.
lein swank or
lein repl, whichever you normally use. Once you have a
working REPL, compile your application's
The key construct provided by appengine-magic is the
appengine-magic.core/def-appengine-app macro. It takes a Ring handler and
defines a new
<project-name>-app var. (If you want to rename this var,
remember to update
app_servlet.clj.) That's it: you may now write your
application using any framework which produces a Ring-compatible handler. Then,
just pass this handler to
To test your work interactively, you can control a Jetty instance from the REPL
(assuming you are in your application's
core namespace and your application is
(ae/start foo-app) (ae/stop) (ae/start foo-app :port 8095) (ae/stop)
Recompiling the functions which make up your Ring handler should produce instantaneous results.
Testing with dev_appserver.sh
lein appengine-prepare. This AOT-compiles the entry point servlet, then copies the necessary classes and library dependencies to your application's
dev_appserver.shwith a path to your application's
Just put all static files into your application's
resources/war directory. If
you put a file called
index.html there, it will become a default welcome file.
Deployment to App Engine
- First of all, be careful. You must manually maintain the version field in
appengine-web.xmland you should understand its implications.
lein appengine-prepareprepares the
resources/wardirectory with the latest classes and libraries for deployment.
- When you are ready to deploy, just run
appcfg.sh updatewith a path to your application's
App Engine Services
appengine-magic provides convenience wrappers for using App Engine services from Clojure.
appengine-magic.services.user namespace (suggested alias:
provides the following functions for handling users.
current-user: returns the
com.google.appengine.api.users.Userfor the currently logged-in user.
:destination): returns the Google authentication servlet URL, and forwards the user to the optional destination.
:destination): performs logout, and forwards the user to the optional destination.
The following Google services are not yet supported:
- Task queues
- URL fetch
Google App Engine maintains a whitelist of permitted Java classes. Other classes
will cause your application to fail to deploy. Examples include threads and
sockets. If you use those in your application, it will not work. More seriously,
if one of your dependencies uses those, your application will also not
work. For example,
clojure.java.io (and its fore-runner, duck-streams from
clojure-contrib), uses java.net.Socket, a forbidden class.
appengine-magic is distributed under the MIT license.