Deploying Spring Boot Applications to Heroku

Introduction

When developing a web application, the natural progression is to take it online and make it available for end users. To make this task possible, and easier, there are numerous cloud platforms available to choose from to host your application - Heroku is one of them.

Heroku provides a platform as a service for deploying applications of various technology stacks like Node, Java, Python, etc. It takes care of all the complicated aspects for deployment, infrastructure, scaling, upgrading, security, etc. and allows us to focus on the application's logic and delivering more value to our end users, rather than deployment.

In this article, we will build a really simple Spring Boot REST API application that will expose an endpoint, and we'll look into various ways of deploying the application to Heroku.

Creating a Spring Boot Application

Initializing the Spring Boot App

As always, the easiest way to start off with a skeleton Spring Boot project is to use the Spring Initializer:

spring_boot_initializr

Choose your preferred build tool, we'll be using Maven. The only dependency we'll need is the Spring Web dependency.

Alternatively, we can create the application using the Spring Boot CLI:

$ spring init --dependencies=web heroku-demo

Create a REST Endpoint

With our skeleton done, let's add a simple REST endpoint:

@RestController
@RequestMapping("/api/v1.0")
public class TimeController {

    @GetMapping("/time")
    @ResponseStatus(HttpStatus.OK)
    public String getCurrentTime() {

        return Instant.now().toString();
    }
}

In case you're not already familiar with the @RestController annotation, it's a convenience annotation made as a combination of the @Controller and @ResponseBody annotations.

This endpoint will simply return the current server time upon request. Let's run the application on our local machine and test if it's working:

$ mvn spring-boot:run

Or, using your IDE, simply run the application and navigate to your browser's localhost:8080/api/v1.0/time URL address:

spring_boot_app_homepage

Alternatively, you can use a tool such as curl to hit the endpoint:

$ curl -X GET 'http://localhost:8080/api/v1.0/time'
2020-01-04T13:19:30.980Z

Deployment to Heroku

With our application primed and ready, let's explore the different ways we can deploy it to Heroku.

Using the Heroku CLI with Git

Heroku offers its own CLI, which we can use to deploy an application. In order to do this we need to install Heroku CLI and Git.

Before we try to deploy it, Heroku needs the application to be in a Git repository, so let's create a repository in our project directory:

$ git init

Once the repository is created, let's add and commit the files:

$ git add src/ pom.xml
$ git commit -m "first commit with project base"

The next step is to log in to Heroku using the Heroku CLI and create a Heroku app:

$ heroku login

It will prompt for email and password for your Heroku account:

Enter your Heroku credentials:
Email: ***********@gmail.com
Password: ***********
Logged in as **********@gmail.com

Once we are logged in, let's create the app:

$ heroku create

Relatively quickly, we'll be strapped with an application:

Creating app... done, ⬢ arcane-journey-46830
https://arcane-journey-46830.herokuapp.com/ | https://git.heroku.com/arcane-journey-46830.git

The create command will add a Git remote named heroku to our local Git repository and also add a random name to it - in our case it's arcane-journey-46830.

Finally, we can deploy our code:

$ git push heroku master

Heroku will detect that this is a Java/Maven application by the presence of the pom.xml file in the repository. After pushing, if you take a look at the logs, you'll be able to notice:

Enumerating objects: 26, done.
Counting objects: 100% (26/26), done.
Delta compression using up to 4 threads
Compressing objects: 100% (21/21), done.
Writing objects: 100% (26/26), 2.96 KiB | 504.00 KiB/s, done.
Total 26 (delta 5), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Java app detected
remote: -----> Installing JDK 1.8... done
remote: -----> Installing Maven 3.6.2... done
remote: -----> Executing Maven
...

And finally, the deployment is finished and we're prompted with a URL leading to our app:

...
remote: -----> Compressing...
remote:        Done: 65.7M
remote: -----> Launching...
remote:        Released v3
remote:        **https://arcane-journey-46830.herokuapp.com/** deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/arcane-journey-46830.git
 * [new branch]      master -> master

Let's test the application again using curl:

$ curl -X GET 'https://arcane-journey-46830.herokuapp.com/api/v1.0/time'
2020-01-04T13:51:31.559Z

Or by navigating our browser to its URL:

spring_boot_app_deployed_on_heroku

Heroku Deploy Plugin

If we want to deploy our application directly without using a Git repository, we can do it using the heroku-cli-deploy plugin. Let's begin by installing it:

$ heroku plugins:install heroku-cli-deploy

Similar to the previous section, we ask Heroku to create the application, but this time we include a --no-remote argument to avoid being asked for the Git repository:

$ heroku creare heroku-demo-stackabuse --no-remote

Notice, that we have mentioned an application name this time around - heroku-demo-stackabuse. This will create the application with a given name, and not generate a random name like in the earlier section.

We also need to mention the port at which Heroku will bind the application in the application.properties file:

server.port=${PORT:8080}

Note: This is required as Heroku binds the application to a port passed as the PORT environment variable and Spring Boot by default exposes the 8080 port. Here, we ask Spring to use PORT and fallback to 8080 in case the environment variable isn't present, i.e. we're running locally.

Finally, we build our application with Maven to create the jar file and deploy it:

$ mvn clean package
$ heroku deploy:jar target/heroku-demo.0.0.1-SNAPSHOT.jar --app heroku-demo-stackabuse

Maven Plugin

There could be scenarios where we would like to make the deployment as part of our Maven build. This is possible using the Heroku Maven Plugin. Let's put the plugin configuration in our pom.xml:

...
<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.heroku.sdk</groupId>
                <artifactId>heroku-maven-plugin</artifactId>
                <version>{version}</version>
                <configuration>
                    <appName>heroku-demo-stackabuse</appName>
                    <includeTarget>false</includeTarget>
                    <includes>
                        <include>${project.build.directory}/${project.build.finalName}.jar</include>
                    </includes>
                    <jdkVersion>1.8</jdkVersion>
                    <processTypes>
                        <web>java $JAVA_OPTS -jar
                            ${project.build.directory}/${project.build.finalName}.jar</web>
                    </processTypes>
                </configuration>
            </plugin>
        </plugins>
    </build>
...

Always, check for the latest version of the plugin here.

As a final step, we need to set an environment variable - HEROKU_API_KEY. This step required only if you do not have Heroku CLI logged in for authorization. The API key can be found in your Heroku dashboard account:

heroku_api_key

And now we can use the heroku:deploy goal to deploy the application:

$ mvn clean heroku:deploy

Heroku Dashboard with GitHub

With the programmatic/CLI approaches out of the way, there's also a really user-friendly GUI approach too. We can create an application in the Heroku Dashboard, link it up with a GitHub account and deploy from there.

Navigate to the "new app" option:

heroku_dashboard_new_app

Next, connect your GitHub account, and search for your repository to connect:

github_app_connect_to_heroku

Once connected, you can deploy your application choosing a branch to deploy or directly choosing the master branch. Also, you may chose to enable automatic deployments based on commits on a particular branch:

github_app_deploy_to_heroku

Checking Logs of Deployed Applications

Checking the logs of the deployed application can be useful for many purposes. Thankfully, it's really easy to access them.

Using the CLI, it's just a single command:

$ heroku logs --tail

This would allow to see the logs running:

heroku_logs

Alternatively, the Heroku Dashboard allows us to access them via the right-hand side More > View Logs:

heroku_dashboard_logs

Heroku Procfile

The Procfile could be used to configure or override default application settings and commands. For example, while deploying the application using the Heroku deploy plugin, we have added port information in the application.properties.

This could also be added into the Procfile. We would add commands to run the application such as:

web: java $JAVA_OPTS -jar target/heroku-demo-0.0.1-SNAPSHOT.jar -Dserver.port=$PORT

Here, we've added a command to run the application with Java and added a JVM argument to override the Spring Boot default port binding.

Removing the App from Heroku

At some point, you may want to remove your app from Heroku, for whatever reason. This is done via a simple command:

$ heroku apps:destroy --confirm arcane-journey-46830

We may run the command without the --confirm flag, but in that case, it will prompt to enter the app name.

Alternatively, we can remove the application from the Heroku Dashboard settings:

heroku_delete_app_dashboard

Conclusion

With the increased popularity of cloud computing, it is important to know how we could deploy and manage our application in a cloud platform.

Heroku is a platform as a service to deploy, manage and scale applications. It also provides free of cost deployments with free dyno's. This free deployments could be used for any demo or evaluation purposes but definitely not suitable for production live applications.

In this article, we've covered several ways of deploying Spring Boot applications to Heroku - using the Heroku CLI, the Heroku deploy plugin, the Maven Plugin and finally the GUI approach via a GitHub repository.

All deployments done here, are deployed into the free dyno. Please note that these free dynos will stop when we are not using the application for a certain amount of time. They will spin up again when we have hit the application. So we may face some delays when we try to reach our application after a long time.