At JavaZone 2011 I met with James Ward, technology evangelist for Heroku and had a brief discussion on what it would take to run Wicket applications on Heroku. We figured that it wouldn't be too hard to get a Wicket application running on a single instance (a dyno in Heroku lingo).
So I tasked myself yesterday evening to get a Wicket quickstart running on Heroku. Basically the recipe is as follows:
- generate a quickstart
- modify the pom such that the packaging goes from war
to jar
- modify the pom to depend on jetty at compile time, and on the servlet api on compile time (not provided)
- modify the pom to generate a shell script to start the application (using appassembler-maven-plugin)
- add a Procfile to the root of your project
- add the following Start
class to the src/main/java
path
For some reason the Start
class provided by the quickstart archetype doesn't work on Heroku, but the above class is simple enough. It should be included in the src/main/java
folder (and default package) because with Heroku, you bring your own server (in our case the Jetty server). The code will pick up the provided socket port to connect to (Heroku supplies external settings using environment variables) and start up the Jetty server.
The Procfile
is just a descriptor for Heroku to identify the start up script.
When you have everything up and running locally:
When you see this (don't forget to add the REPO
environment variable to your shell and point it to your maven repository), you can push your code to Heroku using
Getting the Wicket examples running on Heroku was easy now that the recipe is clear. It just works™.
You can see the code modifications I made on my github repositories for both the quickstart and the wicket-examples.
You can see the Heroku QuickStart in action, as well as the Heroku Wicket Examples both running on a single dyno.
Things worthy of note
Not everything is rosy in the garden of Heroku and Wicket.
Server side state
Wicket uses the HTTP session to communicate the last accessed page to a cluster. As HTTP session clustering is not supported on Heroku (unless you persist the session in a memcache or redis instance), you will loose running sessions when Heroku reassigns your dyno. Of course you can persist your HTTP session in a memcache or redis database.
Since Wicket stores the component tree in the filesystem (by default, you can store it in a memcache or other cloud storage) and Heroku has a read-only filesystem the page store can be evaporated at any time. This will affect the back button support when Heroku has reclaimed your specific dyno instance.
Update: As James Ward points out in the comments,
the file system is writeable but ephemeral – so it can go away at any time</p>
.
Concurrency support
Heroku doesn't support sticky sessions, and as such concurrent access to the component tree cannot be prevented by synchronizing on the page. I think we might be able to come up with something that will work in such an environment in the future as we migrate towards more granular locks (Wicket 1.4 would lock on a page map, 1.5 on a page instance). So running a Wicket application on multiple dynos is not supported (yet).
One advantage of Heroku is that one dyno can only process one request at a time, so synchronization on the component tree in a single JVM is no longer necessary.
UPDATE: After some discussion with the Heroku guys, it appears I based this assumption on old information on the Heroku website. The new Java supported platform called cedar stack does support multiple requests coming in at the same time. The running Wicket Heroku example applications are deployed to the herokuapp.com platform, and make use of the cedar stack.
Conclusion
It is possible to run Wicket applications on a Heroku instance which is a great testament of Heroku's engineering team. I found it easier to get a Wicket application up and running on Heroku than on Google App Engine. There are several loose ends, and we might not be able to fix those given Wicket's architecture. That said, I find Heroku's architecture quite compelling and am anxious to get Wicket fully supported on this platform.