Subscription System

Introduction

This system consists on three microservices:

  • subscription-service: handles the persistence of subscriptions and exposes an API with the required CRUD operations
  • backend-sercive: exposes an API that allows to manage subscriptions. It uses the api exposed by the previous service
  • email-service: performs an action under certain conditions. In this case, a mock email is sent (it is logged to STDOUT) when a new subscription is created

These services use the following underlying infrastructure:

  • database: a PostgreSQL database containing the subscriptions persistent data
  • rabbitmq: a simple message broker used to avoid direct invokation to the email-service

Language used, framework and dependencies

The language used is Java 11.

The specific distribution used in development was:

java -version
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode)

The main framework used is Spring Boot, built with Apache Maven. These technologies were used because they are suitable for the task, highly popular and I have experience with them.

An overview of the components and dependencies:

  • spring-boot-starter-data-jpa and postgresql related: used for ORM / database usage.
  • spring-boot-starter-web: used for everything web related.
  • spring-boot-starter-validation: used for easy validation of entities.
  • spring-boot-starter-security: used to secure the APIs.
  • jackson related: used to (de)/serialize entities and handle some data types.
  • rabbitmq an amqp related: used to connect and interact with rabbitmq.
  • springdoc-openapi-ui: used to expose swagger for the API docs.
  • commons-codec: used for enconding.

Launching the app

Docker dependencies

As stated above, the app uses both a PostgreSQL database and a RabbitMQ message broker.

  • In the database folder, there is a Dockerfile setup for creating the container with the required schema and some test data. There are also scripts for building and launching the image.

  • For rabbitmq, this command allows to have an ephemeral broker, enough to launch the application: docker run --rm -d --hostname localhost --name rabbitmq -p 5672:5672 -p 5673:5673 -p 15672:15672 -e RABBITMQ_DEFAULT_USER='developer' -e RABBITMQ_DEFAULT_PASS='developer' rabbitmq:3-management

Microservices

The three microservices should be able to run by simply executing: mvn spring-boot:run

The application.properties with the configuration can be found in the resources folder and be changed if needed.

The microservices using spring-security have as requirement an access_tokens.json file. It can also be found in the resources folder.

This file provides a set of valid credentials for the Basic Auth requests. When launching the app locally, the provided file is read from the classpath.

If no file is provided in the classpath (like in the Docker images built), the path for the file is read from the value of the following environment variable: ACCESS_TOKENS_PATH. The docker image injects the variable and places the file automatically.

Every microservice has a Dockerfile that builds an executable image. It is a multistage process, where first the application is tested and built. If succedded, an image with only the jar and configuration is created.

Dev "pipeline"

Simulating a simple CI/CD process, in cicd-for-dev, there are some files to ease up the generation of images and running the linked containers, that were actually used when developing the project.

There are two docker-compose files, one that prepares the requirements and another that prepares the microservices.

A script builds the images for the microservices and the database.

If the tests fail or the image cannot be built, the process is aborted by default.

If everything goes ok, the containers are started. The images are also pushed (if so desired) to Dockerhub if they were built successfully, so they can be tested with minikube without needing to create a private docker repository.

The script is written in Python (v3), which should be installed, as well as docker (the script assumes that the executing user belong to docker group and no sudo is required) and docker-compose.

The system can be built and deployed in the local machine by running:

python3 cicd-for-dev/deploy.py

Usage

The apis are intended to be used with a tool like Postman. The requests used were exported and can be found in the docs folder (named: Subscription System.postman_collection.json), ready to use with that tool.

In that folder, the documentation of the APIs generated by Swagger (exported to these files with a maven plugin) can also be found.

The applications allows requests with the credentials: Postman / PostmanToken, if any other tool like curl is to be used.

If it is enabled in the configuration, a Swagger endoint is exposed too.