Skip to content

Continues Delivery with Heroku

Overview

Continuous Delivery (or Continuous Deployment, or CD) is a software engineering approach in which software functionalities are delivered frequently through automated deployments.

We will be using Heroku, a platform as a service (PaaS) based on a managed container system, with integrated data services, for deploying and running software applications. Heroku is primed for continuous delivery.1 It is, in a nutshell, a cloud application platform that lets you deploy your server online. By taking care of most things related to deployment, it makes it easy to get your application up and running.

Deploying Javalin on Heroku

Before we get started, you must:

Build a simple Javalin App

Create a new Gradle Java project herokuDemo in IntelliJ and add the following dependencies to it

1
2
compile 'org.slf4j:slf4j-simple:1.8.0-beta4'
compile 'io.javalin:javalin:3.7.0'

Create the following Java class:

1
2
3
4
5
6
7
public class Application {
  public static void main(String[] args) {
    final int PORT = 7000;
    Javalin app = Javalin.create().start(PORT);
    app.get("/", ctx -> ctx.result("Hello Heroku!"));
  }
}

You can run this application and point your browser to http://localhost:7000/ to see the Hello Heroku! message!

Prepare to deploy

We want to package our Javalin application as a single executable file that can be run on Heroku. We are going to make a fat JAR file2 for this purpose. A fat JAR contains your application and all the dependencies needed to run your application.

Gradle is able to package your Java application into a JAR file but, by default, it does so without including the project dependencies. We can overwrite the default behavior by adding a few lines to the project's build.gradle:

1
2
3
4
5
6
7
8
jar {
    manifest {
        attributes 'Main-Class' : 'Application'
    }
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

Now you can run Gradle's jar task: open the terminal at the root directory of your Java project and type the following command:3

1
$ ./gradlew build jar

Once the process is finished, you can find your newly packaged JAR file in the build/libs directory. Verify that the archive is valid by running the following command:

1
$ java -jar build/libs/herokuDemo-1.0-SNAPSHOT.jar

Heroku Gradle Plugin

To deploy Gradle based JVM applications directly to Heroku, we will use a heroku-gradle plugin. Add the plugin to your build.gradle:

1
2
3
plugins {
    id "com.heroku.sdk.heroku-gradle" version "1.0.4"
}

Moreover, you need to add a configuration for the heroku-gradle plugin; add the following to your build.gradle:

1
2
3
4
5
6
heroku {
    jdkVersion = 1.8
    processTypes(
        web: "java -jar build/libs/herokuDemo-1.0-SNAPSHOT.jar"
    )
}

Making Javalin Listen on the Correct Port

When we deployed Javalin locally, we used the 7000 port on localhost. Heroku assigns your application a new port every time you deploy it, so we have to get this port and tell Javalin to use it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
  public static void main(String[] args) {
    final int PORT = getHerokuAssignedPort();
    Javalin app = Javalin.create().start(PORT);
    app.get("/", ctx -> ctx.result("Hello Heroku!"));
  }

  private static int getHerokuAssignedPort() {
    String herokuPort = System.getenv("PORT");
    if (herokuPort != null) {
      return Integer.parseInt(herokuPort);
    }
    return 7000;
  }

Heroku needs Git

Heroku is deeply integrated with the Git workflow. To create and deploy a heroku app, you must make sure the project is tracked by a Git repository. If that is not the case, make one in terminal (you need initiate git at the root of your Gradle-Java project):

1
$ git init

Deploy

Before deployment, you must create a Heroku app using the Heroku CLI; open the terminal at the root directory of your Java project and type the following command:

1
$ heroku create

Note

You "create" the app once, before deploying for the first time.

Then, run the following command:4

1
$ ./gradlew build deployHeroku

If all goes well, you will get a message that looks like this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
> Task :deployHeroku
-----> Packaging application...
       - app: evening-hollows-96506
       - including: build/
-----> Creating build...
       - file: build/heroku/build.tgz
       - size: 4MB
-----> Uploading build...
       - success
-----> Deploying...
remote: 
remote: -----> heroku-gradle app detected
remote: -----> Installing JDK 1.8... done
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote: 
remote: -----> Compressing...
remote:        Done: 55.1M
remote: -----> Launching...
remote:        Released v3
remote:        https://evening-hollows-96506.herokuapp.com/ deployed to Heroku
remote: 
-----> Done

BUILD SUCCESSFUL in 17s
5 actionable tasks: 2 executed, 3 up-to-date

You can point your browser to the URL of your Heroku application. For example, the example above is deployed at https://evening-hollows-96506.herokuapp.com/.

SparkJava and Heroku

Deploying a SparkJava application to Heroku is almost identical. Here is a repository to demonstrate the process for your reference.


  1. Read more about Continuous Delivery on Heroku at https://www.heroku.com/continuous-delivery

  2. JAR stands for Java ARchive. It is used for aggregating many Java files into one. It is the preferred way to bundle a Java application. Read more on Oracle's website

  3. You can also run this task in IntelliJ from the Gradle Tool Window 

  4. You can configure IntelliJ to run this task by following the instructions here