A RestAPI using Spring Boot, MongoDB running on Docker containers

The objective is build a simple RestAPI using Spring Boot and a MongoDB, running over two containers described by docker-compose file. The aim is start with a simple project and gradually increase complexity and technologies in each Release, the whole project is available here https://git.io/vp9IK, and the specific release for the example described on this post here: https://git.io/vp9BT

The application consists in 2 docker containers, one running our application and other running a MongoDB image from the their official Dockhub repository. The webserver container will have the port :8080 exposed and linked to Mongo container connecting by default port : 27017.

Project Structure

On Spring Initializr you can generate the initial project defining group names, dependencies, etc as you can see below

The project is consists basically in the main application itself, a Model, Controller and Repository layers. Also a Docker file describing our server container and a docker-compose.yml defining the whole solution.

Dependencies

To support the Spring Boot application, MongoDB and tests you will need the following dependencies in your pom.xml file

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.fakemongo</groupId>
<artifactId>fongo</artifactId>
<version>2.2.0-RC2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.lordofthejars</groupId>
<artifactId>nosqlunit-mongodb</artifactId>
<version>0.7.6</version>
<scope>test</scope>
</dependency>
</dependencies>

Build

Using the docker maven plugin we are able to build a new image and publish if it is the case during Maven pipeline, on this example we will build a new image on every mvn package .

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>

After build you should be able to find the new created image as this:

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
volmar/demo-restapi latest ff9345c08df4 30 minutes ago 122 MB

Application

The main class is a simple class using Spring annotations defining a new Bootstrap and Rest Service

@SpringBootApplication
@RestController
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

StudentController

This were we gonna define our api endpoints to handle the HTTP requests

@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
StudentRepository studentRepository;

@RequestMapping(method=RequestMethod.GET)
public Iterable<Student> student() {
return studentRepository.findAll();
}
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public Student create(@RequestBody Student student) {
return studentRepository.save(student);
}
@RequestMapping(method=RequestMethod.GET, value = "/{id}")
public Optional<Student> read(@PathVariable String id) {
return studentRepository.findById(id);
}

The main RequestMapping will handle all /student/ requests and subsequent the path from there e.g. /student/{id} and its request method.

StudentRepository

This extends MongoRepository with all basic methods, for a full documentation about this interface access here.

public interface StudentRepository extends MongoRepository<Student, string>

Dockerfile

This define an image based in a openjdk ready image copying the jar created by Maven.

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

Executing docker images you will get the new image listed as this:

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
volmar/demo-restapi latest a8053a7cce37 55 seconds ago 122 MB

docker-compose.yml

On this file we are describing our containers, links and exposed ports

version: "3"
services:
mongodb:
image: mongo:3.2.4
container_name: "mongodb"
ports:
- 27017:27017
command: --smallfiles
app:
image: volmar/demo-restapi
ports:
- 8080:8080
links:
- mongodb

The image mongo:3.2.4 is an official image from Dockhub, a previous pull is not required as docker-compose will pull all required images to run the application. The ports 27017:27017 is exposing the port 27017, this is just for tests purposes if you want to connect using RoboMongo or similar.

All set, Up and running

With docker-compose up will start the application, this will launch 2 containers and start the webserver.

Using a client you can make a request and check the results as below: