Spring Boot + MongoDB + Heroku Demo

The Developer’s Bookshelf with Heroku application utilizes the following database technologies: JPA 2.0, Spring Data JPA, Hibernate, Liquibase, PostgreSQL, H2 embedded, and HikariCP.  The source code is available on GitHub.

The Developer’s Bookshelf with MongoDB migrates that application work to with MongoDB and MongoLab while still remaining fully deployable to Heroku. The source code is available on GitHub.

There is a live demo running on Heroku, but keep in mind that it might take 120 seconds to load on the first request.  Please be patient with the first request. Subsequent requests will be normal.

Here is The Developer’s Bookshelf with MongoDB  running on Heroku.

 

Technology Stack

  • Spring Boot, no-xml Spring MVC 4 web application for Servlet 3.0 environment
  • Spring Data MongoDB
  • Database (MongoDB, MongoLab)
  • Thymeleaf templates with added Joda Time & Spring Security Dialects
  • Heroku fully cloud deployable
  • Testing (JUnit/Mockito/MockMVC/AssertJ/Hamcrest)
  • Java 8, Spring Security 3.2, Maven 3, SLF4J, Logback, Bootstrap 3.3.4, jQuery 1.11.2, i18n, etc

Compatibility

This application functions properly with versions of MongoDB previous to 3.0.  As of October 2015, Spring Data MongoDB does not offer a compatible Java driver that will work properly with MongoDB 3.0.  The current Spring Data MongoDB project is using a Java driver with version 2.12.5 whereas version 2.13 is required.

Migrating from JPA to MongoDB

Maven Dependencies

In order to utilize the Spring Data MongoDB project, the following dependency should be added to the pom.xml.

 

Database Configuration

The com.chrisbaileydeveloper.bookshelf.config  package holds the DatabaseConfiguration class for MongoDB.

As opposed to JPA’s @EnableJpaRepositories , the class is now utilizing the @EnableMongoRepositories  annotation.
@EnableTransactionManagement is no longer necessary as MongoDB doesn’t support transactions in the traditional sense. Instead it is transactional on a per document basis.

The DatabaseConfiguration class extends the AbstractMongoConfiguration class which does most of the heavy lifting behind the scenes.

 

Persistence Layer

The com.chrisbaileydeveloper.bookshelf.domain  package holds the Book domain object.

Here is a snippet from the Book class.

The @Entity  and @Table  annotations have been replaced by the @Document  annotation which links the Book domain object to the T_BOOK collection.

The @Version  is no longer required as MongoDB doesn’t utilize a version field for version control.

The @Column  annotation has been replaced by the @Field  annotation.

Note that the JSR-349 (Java Bean Validation API) annotations retain the same functionality whether your domain object is mapped with JPA or with MongoDB.

 

Repository

The com.chrisbaileydeveloper.bookshelf.repository  package holds the BookRepository interface.

With JPA, the BookRepository extended the JpaRepository interface. With MongoDB, the BookRepository can be set to extend the MongoRepository interface.

Spring Data for JPA and Spring Data for MongoDB are both part of the umbrella Spring Data project. All of the Spring Data projects have the same goal – “to provide a familiar and consistent Spring-based programming model for new datastores while retaining store-specific features and capabilities”.  Therefore it is not surprising that all of the functionality that was being utilized with the JpaRepository can also be utilized with the MongoRepository, and the methods don’t require any manual implementation.

 

Service Layer

The com.chrisbaileydeveloper.bookshelf.service  package holds the BookService class. Here is a snippet from the class.

All of the @Transactional  annotations have been removed since MongoDB does not support traditional transactions as discussed previously.

 

Controller

The com.chrisbaileydeveloper.bookshelf.controller  package contains the BookController class.

The main difference between the JPA and MongoDB implementations of the controller is in the creation of a new Book. With JPA, if you have set the ‘Id’ attribute to be auto-generated, then an ‘Id’ will be assigned to a Book automatically when it is saved.

However, MongoDB doesn’t offer automatic auto-increment functionality. Instead, it uses a 12-byte ObjectId for the _id field as the primary key that is utilized to uniquely identify your documents. With MongoDB, you can utilize the ObjectId class in order to generate a new ObjectId that can be utilized as the ‘Id’ for a new Book.

Here is a code snippet showing the createForm method for JPA and then for MongoDB.

JPA

MongoDB

As shown, the only difference is in the creation of Book objects. With MongoDB we can use the ObjectId class to generate a unique Id.

 

Application Configuration

The src/main/resources/config  folder holds the main application configuration files. Let’s compare the application-dev.yml  configuration files for JPA and MongoDB.

JPA Configuration

 

MongoDB Configuration

As shown, the spring.datasource  and spring.jpa  properties have been replaced by the spring.data.mongodb  property and its relevant settings.

 

Heroku Configuration

The Procfile for The Developer’s Bookshelf with Heroku contains the following code.

On Heroku, the $DATABASE_URL  is a system environment variable that can be accessed by your application. This is quite useful since it means that you will never have to hardcode your database’s username & password into your application.

With MongoDB, we will be utilizing the MongoLab Addon and so the Procfile contains the following code:

The $MONGOLAB_URI  system environment variable on Heroku will allow us to set the spring.data.mongodb.uri  property without hardcoding any sensitive information into the application.

 

Steps for Deployment

The steps required to deploy the migrated Spring Boot + MongoDB project locally as well as to Heroku are detailed in the project’s GitHub readme.

 

Questions or Clarification

If you have any questions or require any clarification on any parts of the Spring Boot + MongoDB + Heroku Demo please feel free to contact me.