Wicket 6 + CDI on Heroku

herokuwicketAs an Apache Wicket user for more than five years I really enjoy its programming model. I recently played with Play Framework 2.1 and Scala and discovered that deploying to Heroku is as easy as a git push. I wondered how difficult it could be using this mechanism to deploy a Wicket application.

Existing attempts

My initial investigation led me to this blog post from Martijn Dashorst explaining how to deploy a Wicket 1.5 application to Heroku, the service has slightly evolved since and the quickstart no longer deploys (Maven repository is no longer available to the run environment).

Adding JPA in the mix

I adapted it to deploy and use Wicket 6 instead of 1.5. And as I am a CDI fan I completed the quickstart with the CDI Wicket module (inspired from this post from Igor Vaynberg) and made the necessary steps to use the heroku bundled PostgreSQL database as a JPA datasource.

The key to make the database works correctly on Heroku resides in the following code snippet, where we parse the provided environment variable to populate hibernate properties.

try {
     URI dbUri = new URI(System.getenv("DATABASE_URL"));
     String username = dbUri.getUserInfo().split(":")[0];
     String password = dbUri.getUserInfo().split(":")[1];
     String dbUrl = "jdbc:postgresql://" + dbUri.getHost() 
                    + ':' + dbUri.getPort() + dbUri.getPath();
     System.setProperty("hibernate.connection.url", dbUrl);
     System.setProperty("hibernate.connection.user", username);
     System.setProperty("hibernate.connection.password", password);
} catch (Exception e) {
     LOGGER.error("Unable to extract database url");
}

Session replication

On Wicket mailing lists, a user recently asked the steps required to get the data store works correctly on Heroku (as the disk space is ephemeral), the key is using a NoSQL backend like Redis. So I wrote a simple and basic implementation of IDataStore using Redis (I think it can be optimized by someone familiar with Redis, pull requests are welcome).

Hands on

The quickstart can be found at the following address and deploys fine on a stack with Redis Cloud and PostgreSQL add ons enabled.
In the end you got :

  • Wicket 6
  • CDI via Weld
  • JPA with PostgreSQL
  • Redis datastore

You can see it live at the following address : http://wicket-6-sample.herokuapp.com/, the app can take a few seconds to start, as Heroku will stop it if it is idling for too long.

PostgreSQL under OS X Mountain Lion

postgresql

I am actually doing a side project which you will heard of very soon. For this project I am using Play! Framework v2 with the server side being developed in Scala. To efficiently push this new application to production, I am using the Heroku platform

While my initial thoughts were using MySQL as my relational backend, the default stack provided by Heroku made me switch to postgresql that I have barely used in the past. I attempted to set it up on my machine, but with no luck, Mountain Lion is bundling an old version (8.4) whereas I wanted the same as on the Heroku platform. My first attempt with Homebrew was quite a disaster, I never managed to correctly connect my newly created user.

After a few hours mumbling, I looked for an alternative to the Homebrew version. Luckily, the guys at Heroku provide a neat application Postgres.app to drop that allows to quickly start/stop a postgresql server. My problem was I didn’t had enough connections to allow my application to start, I was always getting this message : remaining connection slots are reserved for non-replication superuser connections.

I edited the configuration file

vim "~/Library/Application Support/Postgres/var/postgresql.conf"

to bump the number of connections to a lot more (20 instead of 10) but it prevented my server to start. With a lot of file editing and restarts, I found that the limit for my machine was 11 connections.

The solution to this problem resides in a special setup of the mac os kernel which defines the amount of shared memory a process can allocate. To get rid of this, you can edit your /etc/sysctl.conf file (root required) and put the following lines (it will persist across reboots)

kern.sysv.shmall=65536
kern.sysv.shmmax=16777216

Credits for this tip comes from http://ruby.zigzo.com/2012/07/07/postgresql-postgres-app-and-a-gotcha-on-mac-osx-lion/