Deploy a Multi-Module Maven Project to Heroku

Recently I was building a private hobby project where I wanted to use Heroku to deploy some Microservices and get some experience with it. Since I’m a Java enthusiast, I wanted to use a Multi-Module Maven project to also share some classes to the different microservices. So my mission was to deploy each submodule to a different Heroku app (I know this is completely against the nature of Microservices to code them all in the same language and have them in one big project like a Monolith – but I have my reasons). Getting started with Heroku was quite simple, because they have a very nice guide to setup and run your first app in the cloud. Unfortunately Heroku only supports one Procfile per project, therefore it’s not so easy to deploy multiple submodules to it. But there is way: You can use Config Variables. Let’s see step by step how to use this!

1. Create your project

First of all you start by creating a Multi-Module Maven Project with two submodules. You can find an example here in my GitHub-Repository. I used Spring Boot and Jersey to create a simple HelloWorldResource:

import org.springframework.stereotype.Component;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Component
@Path("/hello")
public class HelloWorldResource {


    @GET
    public Response sayHelloWorld() {
        return Response.ok("Hello World One!").build();
    }

}

It just returns a simple “Hello World One” (there is a similar resource for the other submodule returning “Hello World Two”). You also need to add a configuration class for Jersey which makes the HelloWorldResource available:

import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;

/**
 * Jersey configuration class. Uses package to scan for resources.
 */
@Configuration
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        super();
        // you can either call register(HelloWorldResource.class) or
        // you can be lazy and just set the package to 
        // search for the REST resource(s)
        packages("your.package.name");
    }
}

Also create the Application starter class for Sprint Boot:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Starter for child one application.
 */
@SpringBootApplication
public class ChildOneApplication extends SpringApplication {

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

You should repeat that for your second submodule to be able to check later if the modules have been deployed successfully.

The Procfile

Especially relevant for your successful submodule deployment is a custom Procfile for your Heroku app like the following:

web: java -Dserver.port=$PORT -jar $PATH_TO_JAR

This file just contains one line and will be placed in the root directory of your project (compare my GitHub repository). Heroku identifies the kind of your app by the keyword web. Due to the variable $PATH_TO_JAR we are able to set a custom path to our jar file later. The jar file will be generated by Maven/Spring Boot. You should add the Sprint Boot Maven Plugin to your pom.xml:

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

The Sprint Boot Maven Plugin creates an executable jar file of your application which will automatically call your starter application class (here: ChildOneApplication). To see the full setup of each pom.xml file, please take a look at my GitHub repository.

2. Setup your Heroku app

In order to deploy the app, you have to use a Git repository. So either connect your GitHub account to Heroku or create a new Git repository connected to Heroku. I prefer to connect GitHub to my Heroku account, because I manage most of my projects there. In the case you connect your GitHub account, you then need to create a new app in Heroku and select the repository of your Multi-Module Maven Project. If you’ve directly connected your Git repository to Heroku, this step isn’t necessary. After creating the app, you need to go to the settings of your app and add a Config Variable like this:

Add Config Variable in Heroku

The value should match the pattern submodule/target/jar-file-name.jar where you should replace submodule and jar-file-name with the real values. You should repeat the steps for every submodule you want to deploy, i.e.

  1. Create the app in Heroku
  2. Connect your repository (if necessary)
  3. Add the Config Variable for PATH_TO_JAR

3. Deploy and Test

Finally you are now able to deploy your submodule as a HelloWorld Microservice. Just go to ‘Deploy‘ and click ‘Deploy Branch‘ at the bottom of the page and Heroku will automatically checkout the repository, build your project and start the application. Hence you should go to https://your-app-name.herokuapp.com/hello and check if it returns “Hello World One!”, respectively “Hello World Two!”.