Spring Boot On Heroku

Introduction

The starting point for this guide can be found on the home page for Spring Boot. It is just a simple service that returns Hello World! as JSON.

At this point I must be said that the Spring folks have really hit a sweet spot with this product offering. It is now trivial to run a JEE container with a few lines of code (or even a Tweet). I can honestly just see this being the core product in the future, particularly with the rise of the micro-service.

As someone who has used Spring since it was considered death by XML it is great to see how far it has come.

Part 1: Booting Up

Prerequisites:

Java 1.7
Maven 3+
Favorite IDE

Instructions

So create a new maven project in your IDE and insert the following to you pom:

…
<parent>  
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.1.8.RELEASE</version>
</parent>  
<dependencies>  
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>  
…

This will pull in all the dependencies we need for a fully working web application that can handle HttpRequests.

Then create a controller class with a desirable name and package. I’m going to call it WelcomeController, as you will see it just returns the obligatory “Hello World!”

package com.nps;

import org.springframework.boot.*;  
import org.springframework.boot.autoconfigure.*;  
import org.springframework.stereotype.*;  
import org.springframework.web.bind.annotation.*;

@Controller
@EnableAutoConfiguration
public class WelcomeController {

    @RequestMapping("/")
    @ResponseBody
    String home() {
        return "Hello World!";
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(WelcomeController.class, args);
    }
}

So there shouldn’t be anything to out of the ordinary here. Perhaps the most unusual occurrence is that we have a main method in a Controller class. This is just included here for brevity and can be refactored later.

Otherwise, of note there are several annotations, that depending on your familiarity with Spring may or may not be known to you.

@Controller is a specific stereotype for Spring managed beans that handle HttpRequests.

@EnableAutoConfiguration is where the magic of Spring Boot attempts to configure your Spring Application context with minimum fuss. Later we will define beans programmatically for it to use – without so much of a whiff of XML.

@RequestMapping("/"), indicates that when accessing the base url of our application i.e. “/” this method will be invoked for a response.

@ResponseBody The final annotation indicates that the return type should be converted to the HttpResponse body; by default this will be JSON using the Jackson processor.

Lastly we have SpringApplication.run which is interesting as it is a significant change to the typical paradigm of deploying a Java web application. Traditionally you start a server in a different process then deploy your application to it. In this case however, it sees us “bringing our own” container, sometimes referred to as “Bootstrapping”. By default Spring Boot uses and embedded version of Tomcat although this can be swapped out easily enough for Jetty.

Check Point:

So providing your code compiles you should be able to run the class with main in, most IDE’s will allow you to simply Right Click > Run Main(). You should see the server starting in the console finishing with something like “Started WelcomeController in X seconds”

Got to your browser and head to localhost:8080 and you should be greeted by “Hello World!”

Part 2: The Fat Jar

Instructions

Ok, we have what resembles a working application, if executed through main; however as we will be putting this application on Heroku. We would therefore like an executable jar file that can be invoked from a command line.

Head to the command line and build your project; mvn clean install or equivelant. Once built you should see a jar file in the target directory. If you were to try and run this using the command java –jar myjarname.jar you will get and error. Also note the size of the file is very small, opening it up will show we actually have little inside other than what we have so far created.

Time to make a “fat jar” of our application; add the following to your pom:

<build>  
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>  

If you now rebuild your project the resultant jar file will be a lot bigger, circa 10MB. The plugin has added all the dependencies into the jar, hence the colloquialism “fat jar”.

Checkpoint:

So now executing java –jar myjarname.jar from the command line will result in a running application server.

Remember to stop the existing process if you still have it running in the IDE.

This is pretty cool in itself we can now easily run an application server anywhere we have Java (7) installed.

Part 3: Heroku

Heroku is probably one of the best examples of a Platform as a Service (PaaS). Most importantly for us it offers a free tier that is sufficient for our needs.

The free tier will stop all running processes after a period of an hour inactivity. This means that the first time you return to the application you can experience a significant delay while the server restarts.

Prerequisites:

Git (and on path)
Heroku Toolbelt (and on path)
SSH Keys

Instructions:

If you have not used Heroku before, it is at this stage I will recommend their getting started tutorial; then taking it as far as pushing your first application i.e. “Deploying the app”

With Heroku it is wonderfully easy to deploy applications using Git; however it does require a fair amount of one time setup. Registering an account with them, installing their own Toolbelt software and generating SSH keys. As the latter two points will differ for Windows/Mac/Linux users I won’t tackle it here.

By this point, you have followed the instructions above and now deployed at least one application on Heroku so we know you have the Toolbelt and your SSH key correctly configured.

There are two things we need to do to get our Spring Boot application running on Heroku, but first we’re going to do neither of them and see what happens. When learning I feel it is important to get off the happy path from time to time and see what happened when something is broken.

Before we start on the command line, lets create a .gitignore file in the project root to identify the files we are not interested in putting under version control or pushing to Heroku. Here is an example you can use.

So from the root of your project i.e. where the pom.xml file lives execute the following:

git init  

Expect a “Initialized empty Git repository in xyz” message.

heroku login  
<enter credentials>  

Expect a “Authentication successful” message.

heroku create  

Expect an output similar to the following:

Creating warm-sands-3469... done, stack is cedar-14 https://warm-sands-3469.herokuapp.com/ | [email protected]:warm-sands-3469.git

Heroku creates applications with randomly generated verb-noun-number combinations. We can change this to our liking later.

By default the app will be created in the US, it is possible to use –region flag for others. As we plan on hosting our database in US leave it to default the region

Cast your Git spell:

git add .

git commit –am “initial commit”

git push heroku master

<enter passphrase>  

Now hopefully you should see a build success log message in your console.

However when we visit the url for our Heroku application we will get an Application Error page. Type heroku open or look at the last line of the console output for the url.

As I already mentioned, we weren’t actually expecting this to work. So lets open the logs and see why. In the console type:

heroku logs  

This is a very useful command when trouble shooting Heroku deployments; along with its numerous options and flags for tailing and variable number of lines (Log Guide).

Cleverly the Toolbelt software has made the remote logs appear in our own console window and we should see an number of messages referencing “no web process running”. Also if you log into you heroku.com and open up that app you should see a “no dynos” indicator.

Let’s fix that, at the root of your application create a file called “Procfile”. It has no file extension and must start with a capital letter. In that file insert the following line:

web: java $JAVA_OPTS -jar target/*.jar  

Here we are asking Heroku to create a “web” process and what command should be run. As you should be able to see it is a similar command to what we ran earlier on our own command line to execute the jar file. We have also included the JAVA_OPTS system variable, Heroku initializes this with own memory defaults.

You can use the following to examine system variables on Heroku with:

heroku config  

or to get a specific variable.

heroku config:get JAVA_OPTS  

Now lets do the git incantation again and push the change to Heroku

git add .  
git commit –am “add Procfile”  
git push heroku master  
<enter passphrase>  

So if we hit our Heroku URL is the application working? No… let’s check the logs again.

We should see that the Heroku has tried to start our application, but buried in the messages is something along the lines of :

Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

If you are not seeing the above message and the output is still complaining about “no web processing running – give Heroku a poke with the command heroku ps:scale web=1

The boot timeout message is because our application is trying to bind to port 8080, however Heroku likes to be in control of which ports applications are running on.

So we’re actually going to add another argument to the Procfile entry to tell our application which port to use.:

web: java $JAVA_OPTS -Dserver.port=$PORT -jar target/*.jar  

Now the embedded Tomcat will use the PORT enviroment property provided by Heroku.

Push the change to Heroku with the now familiar incantation.

Checkpoint:

We should now see our JSON response of “Hello World!” … out in the wild.

Conclusion

I know part three probably seemed like hard work, but actually that was only because I led you around the houses to give you a feel for what could go wrong.

Actually all we needed was a pom file, one small Java class and one line in a Profile. Pretty neat to think we now have a full Spring container to play with.

In the next part of this tutorial we’ll look at hooking up a database to the application

Spring Boot On Heroku