Skip to content

Spring template for a REST service designed with Hexagonal architecture

Notifications You must be signed in to change notification settings

blueoceandevops/hexagonal_spring

 
 

Repository files navigation

ABOUT

This is a 'best practices' template project. However, it is an opinionated take on that.

DISCLAIMER: I'm by no means an expert on Spring Boot (it's not even my preferred tool), one reason to do this is to learn. Opinions are welcomed (with proper reasoning), personal opinions (like naming, libraries, etc.) should be posted in the discussions section.

To share feedback, you can use the following tools:

  • Issues: to report bugs, or request new features
  • Discussions: to raise questions about the implementation decisions, propose alternatives, etc.
  • Pull Requests: to fix problems (i.e.: implementing TODOs or fixing bugs)

The project is hosted on GitLab and GitHub for CI demonstration purposes.

Have fun!

Appointments

Application to create appointments (REST API). Appointments are stored in a relational DB (Postgres), and their creation/deletion is published to a Kafka broker.

Architecture

  • Hexagonal Architecture
  • OpenAPI generation (server and client)

Stack

  • Java 21
  • Spring 3.3 (configurable server, 'undertow' by default)
    • Actuator (healthcheck, etc.)
  • Flyway (chosen over Liquibase for its simplicity)
  • Postgres
  • Kafka

Runtime

  • Cloud Native Buildpacks
  • Docker Compose (local environment with the infrastructure)

Test

  • ArchUnit (preferred over modules: it allows naming checks, etc.)
  • Testcontainers (used to provide a test instance of Postgres and Kafka)

Development

  • SDKMAN (allows to use simpler runners on CI)
  • Maven Wrapper (could be also provided by SDKMAN, however, Maven Wrapper has better IDE support)
  • Editorconfig (supported by a lot of editors, rules limited though)
  • CI pipelines for GitHub and GitLab

Requirements

  • Docker Compose
  • JDK 21+
  • SDKMAN (optional, recommended)

Design

  • The REST API controller and client are generated from the OpenAPI spec at build time.
  • Information about code structure in packages' Javadoc comments. They are copied below:
    • appointments: holds the Spring configuration (dependency injection) and contains the starting class for the application.
    • appointments.adapters: contains services and repositories' actual implementations. These are implementation details and must not be used directly in any place (except DI and tests).
    • appointments.controllers: contains the REST controllers of the application. Classes on this package cannot use any other application layer apart from services.
    • appointments.domain: contains the business rules. Must not reference implementation details (storage, frameworks, etc.) directly, these features should be accessed abstracted by interchangeable interfaces. It's not a problem to reference this package from Controllers or Repositories.
    • appointments.domain.model: holds the business entities. These are the data structures used by the business logic. Follows the same access rules as its parent package.

Design Decisions

  • Minimal: don't use libraries for easy stuff (even if that's boring)
  • Prefer service independence over code reuse, less coupling foster evolution among services and favor scalability when more teams/services are added
  • Less coupling with Spring (easier to migrate if needed)
  • Not use Spring integrations if a library can be used directly
  • No Spring profiles (all loaded from environment)
  • Split API spec in different files for future modularity
  • Take out the common (general) part of the pom.xml to parent.xml, however, it should not be taking aside (because of avoid coupling rule above)
  • Docker Compose profiles are used to separate infrastructure from a complete environment including a container for this application

Set up

  • sdk env install

Commands

All commands assume a Unix like OS.

The most important commands to operate the project are:

  • Build: ./mvnw package
  • Documentation: ./mvnw site
  • Run: ./mvnw spring-boot:run
  • Build image: ./mvnw spring-boot:build-image

To run or deploy the application:

  • Run JAR locally: java -jar target/appointments-0.1.0.jar
  • Run container: docker-compose --profile local up

Service Management

Docker

At the docker-compose.yml you can find the information on how to run the application as a container, adjusting the configuration for running it on different environments.

Two Docker compose profiles are used:

  • Default profile (no profile parameter): to allow starting only the infrastructure, this is useful to start the application from the IDE
  • Local profile (--profile local): which also starts a container using the image of this application

Testing

The verification requests can be executed with: src/test/resources/requests.sh, or PORT=9090 src/test/resources/requests.sh if you want to run them to a different port.

The health check endpoint is: http://localhost:18080/actuator/health

About

Spring template for a REST service designed with Hexagonal architecture

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 99.4%
  • Shell 0.6%