Create and publish your Rest API using Spring Boot and Heroku (Part 2)

Paul ‘Tofunmi O.
Zero To Production
Published in
7 min readMar 28, 2019

Build and deploy RESTful API to Heroku

In part one of the Rest API using Spring Boot and Heroku, we built an imaginary bucket list of places we wish to travel to or visit in our lifetime. However, the buckets are not stored in a database. This means that whenever we restart our server our buckets information get lost.

Let’s fix that.

In part two of this tutorial, you will learn how to store our bucket lists in MySQL database and deploy it to Heroku.

To get the finished code, scroll down to the bottom of this page. If you are don’t know what Rest is or want a refresher on what we have covered so far, please read part 1 of the tutorial here.

Tools used in the tutorial

  1. IDE: IntelliJ
  2. Framework: Spring Boot
  3. Dependency: Spring boot starter web
  • Web: It provides with tomcat server which handles request and response mapping among other things.
  • Mysql: This provides a connector for connect to mysql database
  • JPA: This is the ORM, Hibernate to be precise. It provides a wrapper for mapping Java classes to tables in the database.

4. Build Tool: Maven

5. Language: Java

6. Hosting platform: Heroku

7. Database: Mysql

8. Database GUI: Sequel Pro. You can use any tool of your choice.

This tutorial will be divided into two sections: section 1 and section 2. In section 1, we will be using the start.spring.io to specify the dependencies we need and generate the boilerplate code. In the latter section, we will write the code.

Section 1 (Pictures has been attached showing my selection)

  1. Head over to start.spring.io and provide the group and artifact name for your app. It is a Maven project written in Java 8.
  2. The dependencies are Mysql, JPA and Web.
  3. The group Id is com.zerotoproduction. Yours can be anything.
  4. The artifact id is bucketlist.
  5. Click on generate project
  6. Extract to your computer and import the downloaded maven project to your favourite Editor
  7. Open extracted folder in your editor.
My selection on start.spring.io

My dependencies

dependencies for this project

Section 2

We need to create two Java classes. One will serve as a controller for receiving request and responding with response. The second will serve as a data model.

Here is what our Data Model(BucketList) looks like:

package com.zerotoproduction.bucketlist;

import javax.persistence.*;

@Entity
public class BucketList {

@Id
@Column(name = "id", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@Column(name = "name", length = 60, nullable = false)
private String name;

@Column
private String description;

BucketList() {

}

BucketList(String name, String description){
this.name = name;
this.description = description;
}

BucketList(long id, String name, String description){
this.id = id;
this.name = name;
this.description = description;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

@Override
public String toString() {
return "BucketList{" +
"id=" + id +
", name='" + name + '\'' +
", description='" + description + '\'' +
'}';
}
}

An explanation for each of the annotation

1. @Entity: with this annotation, we have specified that this class represents an entity in the DB.

2. @Id: this specifies that this attribute is a primary key

3. @Column(name = “id”, unique = true, nullable = false): @Column specifies that this field should be column, its name should be id, the values should be unique and it cannot be null.

4. @GeneratedValue(strategy = GenerationType.IDENTITY). We are specified that the values should be generated by DB using Identity generation type.

We also need Data Access Object (DAO). Luckily for us, Spring comes with lots of options from CrudRepository to JPARepository. These interfaces provide CRUD functionalities out of the box for Objects annotated with @Entity annotation. However, the caveat is that your DAO interface must extend them and specify the entity and data type of the primary key for that entity. In our example, we are extending JPARepository like so: JpaRepository<BucketList, Long>. The entity is BucketList and data type of its primary key is Long. Now we have all we need to persist our buckets in the DB.

Here is what our BucketListRepository looks like

package com.zerotoproduction.bucketlist;

import org.springframework.data.jpa.repository.JpaRepository;

public interface BucketRepository extends JpaRepository<BucketList, Long> {
}

Here is what the controller looks like:

package com.zerotoproduction.bucketlist;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;

@RestController
public class BucketListController {

@Autowired
BucketRepository bucketRepository;

@GetMapping(value = "/")
public ResponseEntity index() {
return ResponseEntity.ok(bucketRepository.findAll());
}

@GetMapping(value = "/bucket")
public ResponseEntity getBucket(@RequestParam(value="id") Long id) {
Optional<BucketList> foundBucketList = bucketRepository.findById(id);

if(foundBucketList.isPresent()){
return ResponseEntity.ok(foundBucketList.get());
}else {
return ResponseEntity.badRequest().body("No bucket with specified id " + id + " found");
}
}

@PostMapping(value = "/")
public ResponseEntity addToBucketList(@RequestParam(value="name") String name, @RequestParam(value="description") String desc) {
return ResponseEntity.ok(bucketRepository.save(new BucketList(name, desc)));
}

@PutMapping(value = "/")
public ResponseEntity updateBucketList(@RequestParam(value="name") String name, @RequestParam(value="id") Long id, @RequestParam(value="description") String desc) {
Optional<BucketList> optionalBucketList = bucketRepository.findById(id);
if(!optionalBucketList.isPresent()){
return ResponseEntity.badRequest().body("No bucket with specified id " + id + " found");
}

BucketList foundBucketList = optionalBucketList.get();
foundBucketList.setName(name);
foundBucketList.setDescription(desc);

return ResponseEntity.ok(bucketRepository.save(foundBucketList));
}

@DeleteMapping(value = "/")
public ResponseEntity removeBucketList(@RequestParam(value="id") Long id) {
bucketRepository.deleteById(id);
return ResponseEntity.noContent().build();
}
}

Here is what my folder structure looks like

Folder structure in IntelliJ

Since we are connecting to a database, we need the address of the database, username and password.

We will test this locally on our pc before deploying it to Heroku. I have specified the properties in application.properties. Let’s go over it

spring.datasource.url=jdbc:mysql://localhost:3306/zero_to_production_bucketlist_jpa?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=Toor1234

# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto=update

#MySQL DIALECT
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

server.port=9009
  1. spring.datasource.url specifies the connection string for connecting to the database
  2. spring.datasource.username specifies the username for connecting to the Db
  3. spring.datatsource.password specifies the password.
  4. spring.jpa.hibernate.ddl-auto specifies how hibernate will handle entities in your database. The create option means that all entities will be dropped and created at every restart while the update option adds changes to the entities without dropping it. In production, you need to use update else your data will be flushed.
  5. server.port specifies the port number our application will run on.

It’s time to test and we will do it this time locally. We will use Postman

Test 1: Add a bucket list

http://localhost:9009?name=Visit Big Ben&description=My first list

Add a bucket list

Test 2: Get all bucket lists

http://localhost:9009

Get all bucket list

Test 3: get single bucket list

http://localhost:9009/bucket?id=1

Test 4: Update Bucket

http://localhost:9009?name=Visit Big Ben Updated&description=My first list&id=1

Test 5: Delete bucket

http://localhost:9009?id=2

Let’s deploy to Heroku

We need to use ClearDB Mysql Addon on Heroku

First, we prepare the Spring Boot for heroku like so:

  • git init to initialise the repository
  • git add . to add all files in folder
  • git commit -m ‘Commit name’: commit changes
  • heroku create: to create heroku app

Next, you need to add mysql DB like so:

heroku addons:create cleardb:ignite

Now that you have add clearDB, you need the connection url. To get this, type like so:

heroku config

It should return your connection string.

You need to replace the spring.datasource.url value with the value return from heroku config.

One last thing though, to make it work, add a database config file like so:

package com.zerotoproduction.bucketlist;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class DatabaseConfig {

@Value("${spring.datasource.url}")
private String dbUrl;

@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dbUrl);
return new HikariDataSource(config);
}
}

It’s time to deploy to heroku

git push heroku master

At the end of this process, you should have your app deployed to Heroku

To test, you remove the localhost and port number. For example to get all bucketlists on a deployed app, the url is like this:

https://tranquil-mountain-81706.herokuapp.com/

Just repeat the same process we followed for testing locally however you should remove localhost and port

That marks the end of this step 2.
In step 3, I plan to introduce authentication and roles using Spring Security. In step 4, we would consume the rest api using a JS library like VueJS or React JS.

Stay tuned

Share, clap and add your comment.

The complete code can be found here:

https://github.com/zero-to-production/bucketlist

--

--

Paul ‘Tofunmi O.
Zero To Production

Passionate about business, technology, abundant living — a life of purpose — and a true follower of Jesus