Basic usages

Heroku is often mentionned as an example of PaaS provider. Although I found a few opinions stating that «Java is a second or third class passenger on Heroku», I wanted to test it myself.

Creating a free account is straightforward. Language specific tutorials are provided. I followed the one dedicated to Java.

Requirements, apart from an heroku account, are just «Java» (no version mentionned, but the example in the tutorial i Java 7) and Maven 3.

CLI tools should be downloaded and are available for Debian, Windows, OS X and «standalone» (?). As a debian user, I followed the instructions :

wget -qO- | sh

This :

  • adds a package repository : deb ./
  • installs two packages : foreman and heroku.

After that, you have to login on heroku using the

heroku login


It checks your account/password then let you choose the SSH public key you want to upload.

The getting started tutorial then let you clone an example project. Its pom.xml is a bit surprising :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=""

The target artefact is not a war but a jar. The only class seems to be some kind of autosufficient servlet. It uses jetty 7.6.0. It uses the dependency-plugin to copy jar dependencies in the target/dependency subdir.

The recommended way to proceed if to use a beta feature : creating a git repo where the project will be pushed.

$ heroku create --http-git
Creating glacial-sands-3101... done, stack is cedar-14 |
Git remote heroku added

Then push the code to remote master branch :

$ git push heroku master
Décompte des objets: 33, fait.
Delta compression using up to 2 threads.
Compression des objets: 100% (27/27), fait.
Écriture des objets: 100% (33/33), 4.89 KiB | 0 bytes/s, fait.
Total 33 (delta 12), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: -----> Java app detected
remote: -----> Installing OpenJDK 1.7... done
remote: -----> Installing Maven 3.2.3... done
remote: -----> executing /app/tmp/cache/.maven/bin/mvn -B -Duser.home=/tmp/build_5d419e548f5f5358e7f369fc9f0f73e0 -Dmaven.repo.local=/app/tmp/cache/.m2/repository  -DskipTests=true clean install
remote:        [INFO] Scanning for projects...
remote:        [INFO]                                                                         
remote:        [INFO] ------------------------------------------------------------------------
remote:        [INFO] Building helloworld 1.0-SNAPSHOT
remote:        [INFO] ------------------------------------------------------------------------
remote:        [INFO] Downloading:
remote:        [INFO] Downloaded: (226 KB at 6619.0 KB/sec)
remote:        [INFO] Installing /tmp/build_5d419e548f5f5358e7f369fc9f0f73e0/target/helloworld-1.0-SNAPSHOT.jar to /app/tmp/cache/.m2/repository/com/example/helloworld/1.0-SNAPSHOT/helloworld-1.0-SNAPSHOT.jar
remote:        [INFO] Installing /tmp/build_5d419e548f5f5358e7f369fc9f0f73e0/pom.xml to /app/tmp/cache/.m2/repository/com/example/helloworld/1.0-SNAPSHOT/helloworld-1.0-SNAPSHOT.pom
remote:        [INFO] ------------------------------------------------------------------------
remote:        [INFO] BUILD SUCCESS
remote:        [INFO] ------------------------------------------------------------------------
remote:        [INFO] Total time: 9.911 s
remote:        [INFO] Finished at: 2014-12-03T09:56:38+00:00
remote:        [INFO] Final Memory: 19M/644M
remote:        [INFO] ------------------------------------------------------------------------
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote: -----> Compressing... done, 62.8MB
remote: -----> Launching... done, v6
remote: deployed to Heroku
remote: Verifying deploy... done.
 * [new branch]      master -> master

this automatically builds the artefact, then launch it using the Procfile :

web:    java -cp target/classes:target/dependency/* Main

The app is then up and running.

The tutorial indicates then how to view logs :

heroku logs --tail

The tutorial then gives a hint on how to scale an app, manually allocating nodes using heroku ps.

Then, like Google App Engine, the tutorial indicates how to run the app locally using foreman :

$ foreman start web
11:09:05 web.1  | started with pid 8160
11:09:05 web.1  | 2014-12-03 11:09:05.695:INFO:oejs.Server:jetty-7.6.0.v20120127
11:09:05 web.1  | 2014-12-03 11:09:05.760:INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
11:09:05 web.1  | 2014-12-03 11:09:05.822:INFO:oejs.AbstractConnector:Started SelectChannelConnector@

This is something that I really appreciate. Local (and thus fast) debugging is mandatory in most complex projects.

I just skipped the part on pushing changes with maven (it is just @@git push heroku master@...).

Next, the tutorial introduces add-ons.

As I guessed, an add-on was already configured : the free "postgresql instance" I provisionned when creating my account.

$ heroku addons
=== glacial-sands-3101 Configured Add-ons
heroku-postgresql:hobby-dev  HEROKU_POSTGRESQL_MAROON

Heroku allows the execution of remote commands, using what it calls a "one-off dyno". Dyno are, in a nutshell, nodes instantiated for your apps. Command execution is performed by nodes instantiated on demand, in opposition to the always running web nodes. That why they are called "off nodes".

Lauching bash is straightforward :

$ heroku run bash
Running `bash` attached to terminal... up, run.4406
~ $ 

The filesystem seems to be the same as the webapp.

The tutorial finally deals with environment variables and database (PostgreSQL).

Running a very simple JSF app

I then wanted to run this very simple test, which uses a PrimeFaces 5.1 / MyFaces 2.2.6 / OpenWebBeans 1.2.6 / DeltaSpike 1.1 stack.

Heroku features detailed information on how to get a Tomcat webapp up and running.

I followed the recommendation and added the maven-dependency-plugin declaration, as a heroku profile :


Then, I build the project using :

$ mvn -Pheroku clean install

and tried to run it using :

$ java -jar target/dependency/webapp-runner.jar target/test-heroku##1.0-SNAPSHOT.war

It did not work at first. I got exactly the same problem I had with OpenShift : it seems that my beans were not instantiated.

Suspecting some file-scanning problem, I tried again with the --expand-war parameter... And it worked !

Following the tutorial, I added the following Procfile :

web:    java $JAVA_OPTS -jar target/dependency/webapp-runner.jar --port $PORT --expand-war target/*.war

Then I created the app, requesting that it runs in the European Union and sepcifying a name (because test is, well, widely used. :-) ).

$ heroku create --region eu testlp-heroku

and uploaded the app

$ git push heroku master

...and it did not work. The reason was simple : the heroku profile was not activated, the webapp-runner was not downloaded and not found, as you can se in the logs :

lpenet@dsi-lpenet-personnel:~/heroku/test-jelastic$ heroku logs --tail
2014-12-03T12:54:14.883097+00:00 heroku[api]: Enable Logplex by
2014-12-03T12:54:14.883131+00:00 heroku[api]: Release v2 created by
2014-12-03T12:55:37+00:00 heroku[slug-compiler]: Slug compilation started
2014-12-03T12:57:11.381707+00:00 heroku[api]: Scale to web=1 by
2014-12-03T12:57:11.913533+00:00 heroku[api]: Set DATABASE_URL config vars by
2014-12-03T12:57:11.913616+00:00 heroku[api]: Release v3 created by
2014-12-03T12:57:11.996784+00:00 heroku[api]: Attach HEROKU_POSTGRESQL_CYAN resource by
2014-12-03T12:57:11.996784+00:00 heroku[api]: Release v4 created by
2014-12-03T12:57:12+00:00 heroku[slug-compiler]: Slug compilation finished
2014-12-03T12:57:12.109260+00:00 heroku[api]: Set PATH, JAVA_OPTS config vars by
2014-12-03T12:57:12.109289+00:00 heroku[api]: Release v5 created by
2014-12-03T12:57:12.178189+00:00 heroku[api]: Deploy 8b59698 by
2014-12-03T12:57:12.178189+00:00 heroku[api]: Release v6 created by
2014-12-03T12:57:21.961334+00:00 app[web.1]: Error: Unable to access jarfile target/dependency/webapp-runner.jar
2014-12-03T12:57:22.898521+00:00 heroku[web.1]: State changed from starting to crashed
2014-12-03T12:57:22.899254+00:00 heroku[web.1]: State changed from crashed to starting
2014-12-03T12:57:21.452363+00:00 heroku[web.1]: Starting process with command `java -Xss512k -XX:+UseCompressedOops -jar target/dependency/webapp-runner.jar --port 35347 --expand-war target/*.war`
2014-12-03T12:57:22.895807+00:00 heroku[web.1]: Process exited with status 1
2014-12-03T12:57:36.194058+00:00 app[web.1]: Error: Unable to access jarfile target/dependency/webapp-runner.jar
2014-12-03T12:57:35.466658+00:00 heroku[web.1]: Starting process with command `java -Xss512k -XX:+UseCompressedOops -jar target/dependency/webapp-runner.jar --port 11978 --expand-war target/*.war`
2014-12-03T12:57:37.051245+00:00 heroku[web.1]: Process exited with status 1
2014-12-03T12:57:39.153329+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" request_id=dd20e9a1-0038-48af-bbea-34998ffacb0a fwd="" dyno= connect= service= status=503 bytes=
2014-12-03T12:57:39.804428+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" request_id=dcd0ea94-4895-46f2-95dd-75f372778ad2 fwd="" dyno= connect= service= status=503 bytes=
2014-12-03T12:57:37.060623+00:00 heroku[web.1]: State changed from starting to crashed

So I added an automatic activation when an heroku specific variable is defined, DYNO :


... and it worked like a charm.

More complex example, with PostgreSQL database

I then decided to run my (a little) more complex test, which features JPA 2 / Hibernate 4.2 / PostgreSQL.

So, I added a Procfile and copied in pom.xml the heroku profile from the simple test.

I wanted to avoid copying the DB parameters in my application context.xml.

So, I first tried to use an observer of the PostConstructApplicationEvent. This bean was in an additional build tree, src/heroku/java, that is added using the build-helper-maven-plugin. However, it failed because the InitialContext was not accessible.

So, I switched back to using environment variables that will then be used as username, password and URL in the resource declared in context.xml. It leverages heroku's environment variable management features.

Despite a lot of efforts, I could not get the JNDI part up and running. It it rather disappointing. Heroku java documentation explains how to instantiate a connection programmatically but, well, we are in 2014 and this should be possible using xml configuration files and annotations.


Heroku is a pleasant alternative for a developper, mostly because of the ability to execute locally the webapp in a controlled environment. However, the lack of netbeans support is disappointing, along with the lack of JNDI support. AFAIK, there is no private PaaS version.