First Steps with Heroku – The New-Old Boy in the Cloud

Since my previous posts about Java cloud platforms I wanted to expend some time with Heroku and compare with the others.

Heroku is a veteran among the cloud platforms, but it’s not until a few months ago that they launched a Java offering.

In this post I will share my experiences starting with Heroku and making an existing application to work on it.

A Brief History of Heroku

Heroku is a cloud platform as a service (PaaS) offering owned by Salesforce.com. It started as an offering for Ruby applications only but with time it has matured and evolved, and now with their third generation application stack, Cedar, is a polyglot platform supporting Ruby, Java, Python, Node.js, Clojure and Scala.

One of Heroku top strengths is their approach to data persistence with a fully managed relational database service based on PostgreSQL. PostgreSQL databases can be contracted independently from the application, and thus can be leveraged by those that already have an application layer but want to access more powerful, secure, scalable data persistence solutions without a large investment.

Heroku pricing model is based on the number of concurrent processes, called dynos, and the database cache level. Heroku also has available a free ‘development plan’ without associated cost, that uses a shared database instance and no concurrent processes in the web layer.

More information on Heroku pricing model and database options can be found here: http://www.heroku.com/pricing.

One important difference between Heroku and other Java cloud platforms is that the runtime, instead of being part of the platform itself, is something we carry over with our application to the cloud. This, in theory, adds a level of freedom for developers but in the practice very few Java web containers can be deployed as part of the automated build process that leverages Maven and Git). Heroku support for Jetty is well documented. There are also some experiences with Tomcat although the support is far from perfect and may conflict with the orthodox Maven structure for a web artifact, which causes known problems with Maven’s regular lifecycle or with the IDE. In short, not many runtimes can be used in an executable form leveraging only Maven public artifacts and the application source code.

Preparing the Tool Set and Creating a New Application

To start developing applications with Heroku, developers will need to install Heroku command-line tools. One way is to grab the Heroku Toolbelt, an all-in-one tools package, from here: https://toolbelt.herokuapp.com/.

Alternatively, for developers that are already using Ruby, just install these two gems issuing the following commands:

>gem install heroku
>gem install foreman

To create a new application in Heroku, a Heroku account is needed. To obtain one, sign up at https://api.heroku.com/signup using a valid e-mail address. We will refer to this account as the application manager.

Once the account is ready, the application manager will log into the account issuing the following command:

>heroku login

First time, SSH public key will be uploaded if found, or created:

Heroku uses a Git repository to get access to application versions. Thus, we will need to setup a local Git repository if we don’t have one. We can create an empty repository or a new repository from an existing application:

>git init
>git add .
>git commit –m “initial version”

Next step is to actually create the application in Heroku Cedar stack by issuing the following command:

>heroku create –-stack cedar

The application will receive an initial name, composed from two names and a number and the remote Git repository will be added. The command output will look like this:

Creating high-fog-3620... done, stack is cedar
http://high-fog-3620.herokuapp.com/ | git@heroku.com:high-fog-3620.git
Git remote heroku added

The application just created will have immediate access to a ‘free-as-in-free-beer’ shared PostgreSQL database.

Note that, by default, only the application manager is able to push changes to the repository. However, new SSH public keys can be authorized by issuing a command analogous to this:

>heroku keys:add c:\Users\developer.A\.ssh\id_rsa.pub

Making Changes

Now that the environment is ready and we have an application (and its Git repository to interact with), let’s discuss about what changes need to be done on an existing Java with Spring application to be deployed there.

The reference application is a very simple one, and the same used in previous articles: web interface using JSP and JSTL, plus Spring 3 and Hibernate. It is currently configured to use an embedded HSQLDB database for data persistent storage. The application is working locally deployed in a Tomcat 7.0 runtime.

Changes that need to be done are, at high-level:

  • Change configuration to leverage PostgreSQL database provided by Heroku.
  • Add support for PostgreSQL JDBC driver at runtime.
  • Add and configure the Maven artifacts for the web container runtime.
  • Create a simple text file telling Heroku how to actually start the web container runtime.

Configuring Database

For the existing application to make use of the shared PostgreSQL database provided by Heroku, we will need to add the JDBC driver to Maven’s runtime dependencies (and remove current HSQLDB artifact):

    <dependency>
        <groupId>postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>9.1-901.jdbc4</version>
        <scope>runtime</scope>
    </dependency>

Heroku exposes database access URL through an environment variable named DATABASE_URL. The format of this variable is not directly understood by JDBC drivers, and thus we will need to work with tokens. When using Spring, this is not a complex step:

    <bean id="dataConfigPropertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="searchSystemEnvironment" value="true"/>
    </bean>
    <bean class="java.net.URI" id="dbUrl">
        <constructor-arg value="${DATABASE_URL}"/>
    </bean>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="org.postgresql.Driver"/>
        <property name="url" value="#{'jdbc:postgresql://' + @dbUrl.getHost() + @dbUrl.getPath()}"/>
        <property name="username" value="#{@dbUrl.getUserInfo().split(':')[0]}"/>
        <property name="password" value="#{@dbUrl.getUserInfo().split(':')[1]}"/>
        <property name="maxWait" value="5000"/>
        <property name="maxActive" value="15"/>
    </bean>

When testing locally, developers may have a local PostgreSQL database and simply provide a DATABASE_URL variable which value refers to this local instance. For example, if using Eclipse IDE to launch the local test server, just add the variable to the Environment tab on server launch configuration page:

Configuring Runtime

Next step is to add configuration for the web container runtime. We’ve decided to use Jetty, as it provides a runner artifact that does not require deep changes in Maven structure that could conflict with IDE integration.

One option is to add the Maven Dependency Plug-in and add runtime artifacts there. In our case we also needed to add a couple of standard libraries that are not available in Jetty 8.0.4 runtime:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.3</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>copy</goal> 
                </goals>
                <configuration>
                    <artifactItems>
                        <artifactItem>
                            <groupId>org.mortbay.jetty</groupId>
                            <artifactId>jetty-runner</artifactId>
                            <version>8.0.4.v20111024</version>
                            <destFileName>jetty-runner.jar</destFileName>
                        </artifactItem>
                        <!-- not available in jetty 8.0.4 -->
                        <artifactItem>
                            <groupId>javax.el</groupId>
                            <artifactId>el-api</artifactId>
                            <version>2.2</version>
                            <destFileName>el-api.jar</destFileName>
                        </artifactItem>
                      <!-- not available in jetty 8.0.4 -->
                            <artifactItem>
                            <groupId>org.glassfish.web</groupId>
                            <artifactId>javax.el</artifactId>
                            <version>2.2.3</version>
                            <destFileName>el-impl.jar</destFileName>
                        </artifactItem>
                    </artifactItems>
                </configuration>
            </execution>
        </executions>
    </plugin>

Creating the Process File

The process file is a simple text file that Heroku platform will look at to actually launch the web container process. It should contain any command-line switch and options, as well as the deployment action. Taking into consideration that underlying OS is Ubuntu 10.04 will help to create the file with the correct syntax.

The file should be named Procfile and stored in project’s root folder, beside pom.xml file. In our case, it is as simple as:

web: java $JAVA_OPTS -Djava.endorsed.dirs=target/dependency -jar target/dependency/jetty-runner.jar --port $PORT target/*.war

Deploying Changes

Deploying the Application

Once the changes have been made it is time to commit all the files and push them to Heroku. We can use Git command-line but if using Eclipse IDE deploying the changes is as simple as triggering the commit-and-push inside the IDE:

The push will trigger a Maven build in Heroku: sources will be compiled and packaged and after that the command provided in the Procfile file will be executed.

Renaming the Application

Of course, the initially assigned application name is not cool at all. Fortunately Heroku allows renaming the application name as long as it is not used by any other application.

To rename the application, log into the Heroku control app here: https://api.heroku.com/myapps

The list of applications for the account is listed in there and accessing the General Info page will allow, among other things, to rename the application name:

Note that, after renaming the application, the Git repository URL will change, and the remote should be updated accordingly. To do that, just issue these two commands (using the appropriate remote URL, of course):

>git remote rm heroku
>git remote add heroku git@heroku.com:herokufirst.git

The application will be available through the new URL almost instantly (DNS will need to propagate the update):

Some Useful Commands

These are some useful commands when working with Heroku.

To see the log and ‘tail’ it:

>heroku logs –n 1000 -t

To have access to a very useful SQL console, install this add-on:

>heroku plugins:install git://github.com/ddollar/heroku-sql-console.git

To access the console once installed, just issue this command:

>heroku sql

To get the list of deployment history (each deployed version labeled in “vNN” format, issue the command:

>heroku releases

To go back to a previous version, just issue this:

>heroku rollback vNN

To view the current environment configuration (JAVA_OPTS, MAVEN_OPTS, etc):

>heroku config

To change an environment variable:

>heroku config:add VAR_NAME='new_var_value'

This Is Not a Comparison

Although this article is not a comparison, nor a benchmark, it is unavoidable to compare with the other cloud application platforms that we’ve presented in previous articles: VMware Cloud Foundry and Red Hat OpenShift.

  • First, and above all others: Heroku is a commercial, mature platform for offering cloud application services and supporting customers.

VMware Cloud Foundry and Red Hat OpenShift both share that are a (partially at least) open-sourced platforms that are offered for free (with some limitations) to the public. Commercial offerings are starting now to appear and in some cases not directly offered by the VMware or OpenShift as platform sponsors. However, Heroku primary focus is in the business, in creating a rock solid platform so customers want to make use from it. This means, for example, that while in Cloud Foundry and OpenShift support is driven by a community, in Heroku there is a dedicated support team. Of course platform sponsors are very involved in forums and provide timely answers as well.

  • Approach to development and deployment.

This is another important difference. When working with Cloud Foundry developer tools are totally a choice of the development team. Once changes are done and ready to be deployed, development team uploads application binaries (WAR exploded folder). Open Shift and Heroku, on the other side, partially defines the development architecture: Git repository, Maven builds. Changes are deployed through sources upload and remote build process.

  • Runtime (and frameworks) election.

Runtime and frameworks election is another key difference across platforms. While Cloud Foundry is built on top of a Tomcat runtime, allowing only web servlet-based applications (with or without Spring), Open Shift is built on top of a JBoss runtime, allowing more flexibility to the type of Java applications and frameworks that can be deployed: web servlet-based applications (with or without Spring), Java EE web profile applications, Java EE full profile applications or whatever you may need through the DIY cartridge. Heroku approach is different: instead of enforcing a runtime, it requires development team to choose a runtime. However, this ‘apparent freedom’ comes to a price: it is difficult to actually carry over another runtime but the Jetty servlet container as part of a Maven build process.

Conclusion

Heroku is a mature and robust cloud application platform. Although it is relatively new to Java applications, it has been offering scalable applications and databases for two years.

Heroku shares some characteristics with other platform providers while having their very own and unique features, as the web container election or a powerful and flexible database.

Heroku is also a robust commercial offering with lots of experience (or at least as much as possible when discussing about Cloud) running their business, supporting customers and delivering real value to them.

It is as well a technically very interesting platform and definitely one to seriously consider when making a choice for a cloud application platform.

17 thoughts on “First Steps with Heroku – The New-Old Boy in the Cloud

    1. Thanks James for visiting. Actually I just wanted to share my initial experiences and show how easy was to start working with Heroku with the perspective of someone that is already working in a more ‘traditional’ runtime platform. Now I only wish that I have the time to explore more things in detail and share them.

  1. Thanks. I need a good tutorial on deploying. Since I have never used embedded Jetty or embedded Tomcat, I have been finding it very frustrating to get jsps to render and the documentation out there. Sorry James Ward, is very very lacking in details. It is like poof deployed app. There you go. But when things don’t work then there is no where to go. But your blog entry helps out a lot.

    Thanks again, I will try it out on my project and let you know if I got it to work with your post.

    Mark

    1. OK, first part that I found missing that I can’t continue, is that I have Tomcat 7 as y deploy right now, and moving to embedded Jetty like in your post here, but what does all of the pom file look like to get Jetty dependency. I just see the maven plugin. Don’t you need tags for Jetty?

      1. Hi Mark, unless your app uses Jetty specific stuff, you don’t to need to add Jetty runtime dependencies to the pom. I mean that best practice is to have your project depend on the Java EE and JSTL specs, for example, so your runtime env does not impact. I have used for example Tomcat and Glass fish locally in the IDE while using Jetty once the app is up on Cedar.

      2. Thanks. I removed those dependencies and I have it deploying now. But the app just doesn’t work. This is the same problem I had with James’ tutorial on embedded Jetty. Took a while for both to deploy, but then they never render my jsp pages, missing the jsp includes I have that bring down my css, javascript and all my pages in the first page. My app with no styling. ;(

        http://eventgate.herokuapp.com/

        Also, I tried some of the heroku commands you posted and they don’t seem to work in my terminal. I get stuff like

        new-host-2:EventGate bytor99999$ heroku releases
        /Users/bytor99999/.heroku/client/lib/heroku/cli.rb:30:in `start’: undefined method `styled_error’ for Heroku::CLI:Class (NoMethodError)
        from /usr/bin/heroku:28

        Mark

      3. Are you able to run locally? If you a local Postgre db you can run the app locally. Besides that, anything relevant in the log? If you don’t get your styles loaded, it can be an issue with resource redirection from older Tomcat versions.

  2. HI , thnx for your post.
    I have a question similar to Marat. I m trying to connect to a PostgreSQL provided by Heroku. I d like to do that without using the Spring framework .So I want to configure my Peristence.xml file but I m continiously getting this error:

    javax.servlet.ServletException: java.lang.UnsupportedOperationException: The user must supply a JDBC connection
    Do you have any idea what might be the problem for that ?

    I have posted a question here:
    http://stackoverflow.com/questions/13470188/how-do-i-connect-to-postgresql-in-heroku-without-using-spring

    Thnx agian for your article
    Fotis

    1. My assumption is that JPA is not capable of parsing the URL value as Spring is. Moreover, JPA should be guessing “what the heck is dbUrl?”. As a suggestion, I would try to add new environment variables in the Procfile before running the java process, i.e. using some shell script:

      Content of Procfile:
      web: path-to/some.sh

      Content of path-to/some.sh:
      #funny stuff transforming DATABASE_URL env variables into JPA-friendly variables
      #define DB_CONFIG_STUFF=”-Durl=$URL_VAR -Dusername=$USER_VAR…”
      java $JAVA_OPTS $DB_CONFIG_STUFF -jar target/dependency/jetty-runner.jar –port $PORT target/*.war

      I’ve never tried that but it could work.

Leave a comment