Skip to content

Harmelodic/init-microservice

Repository files navigation

init-microservice

A repo that contains bootstrapping code and reference implementations for developing a microservice.

Built in Java.

Showcases

Project configuration:

  • README
  • .gitignore
  • Docs + ADRs (MkDocs + Markdown)
  • Automated Dependency Updates (Renovate)
  • Automated Code Refactoring (OpenRewrite)
  • HTTP API Specification (OpenAPI)
  • Async API Specification (AsyncAPI)
  • Dependency Management (Maven + BOMs)

Application configuration:

  • Dependency Injection and Application Mgmt (Spring Boot & Starters)
  • Unit Testing (JUnit)
  • Logging Config (Slf4j & Logback)
  • Tracing configuration (OpenTelemetry Java Agent for zero-code instrumentation, OpenTelemetry annotations for custom instrumentation)
  • Metrics configuration (Micrometer + Prometheus Registry/Endpoint)

Build / CI:

  • Test & Build automation (Maven, GitHub Actions)
  • Uses reusable workflows for ease of CI maintenance.
  • Java Project + Container image specific build process:
    • Lint/Scan Java code (PMD, Modernizer, SpotBugs)
    • Reformat Java code
    • Testing (Maven Surefire plugin)
    • Automated publishing of Contract Testing Contracts and Results (PACT Broker, GitHub Actions)
    • Packaging JAR (Maven Compiler plugin, Spring Boot Maven plugin)
    • Packaging and pushing a container image (Jib Maven plugin)

Deployment / CD:

  • Kubernetes resources (Kustomize)
  • Spread pods (Pod Anti-affinity)
  • Auto-scaling (HPA)
  • Pod security (SecurityContext)
  • Expected that an external CD system would deploy to Kubernetes (e.g. Argo CD)
  • Expected that this configuration would actually be in a deployment repository.

Infrastructure as Code:

  • Databases - Terraform, or Self-hosted Kubernetes-operated:
    • SQL = PostgreSQL / CloudNativePG / MySQL / GCP CloudSQL / AWS RDS / AWS Aurora / Azure Database for PostgreSQL
    • Key-Value Memory Store (Caching) = Redis / Memcache / Valkey / GCP Memorystore / AWS ElasticCache / Azure Cache
    • High-available Key-Value (key-value / document / analytical) = GCP BigTable / AWS DynamoDB / Azure Cosmos DB
    • Document-oriented = DocumentDB / MongoDB / GCP Datastore / GCP Firestore / AWS DocumentDB / Azure DocumentDB
  • Message Bus, Queue, PubSub, Topics & Subscriptions - Terraform, or Self-hosted Kubernetes-operated:
    • RabbitMQ
    • Google Pub/Sub
    • AWS Simple Queue Service (SQS)
    • Azure Service Bus
  • Blob Storage (also for Data Lakes) - Terraform, or Self-hosted Kubernetes-operated:
    • PersistentVolumes / Disks
    • Network Attached Storage (NAS) cluster, accessed via SFTP / Samba
    • GCP Storage (buckets)
    • AWS Simple Storage Service (S3)
    • Azure Storage
  • Search Engines (offloading from microservice) - Terraform, or Self-hosted Kubernetes-operated:
    • ElasticSearch
    • Apache Solr
    • PostgreSQL (Full Text Search)
    • GCP Vertex AI Search
    • AWS CloudSearch
    • Azure Cognitive Search
  • Rudimentary applying of Terraform (GitHub Actions)
  • Expected that an external CD system would apply Terraform (e.g. Atlantis).
  • Expected that an external CD system would apply Kubernetes installations (e.g. ArgoCD + Operators / Helm Charts).
  • Expected that this configuration would actually be in a deployment repository.

Reference implementation examples (production):

  • Application Structure Example (app.structure.account)
    • Reasonably decoupled layers/components
    • Domain-driven
    • Scoped explicit exception handling
    • Simple reusable model, mapping done in layers (if needed)
    • Dependency Injection used
    • No implementation details (as implementations covered in other reference implementations)
  • HTTP Endpoint
    • Front Controller pattern
    • Authorization checks
    • Versioning
    • HTTP POST Idempotency
    • Offset Pagination
    • Cursor Pagination
    • Caching (where appropriate)
    • Server Sent Events
    • Feature flag for toggling / releasing endpoints
  • Business Logic
    • Modelling
    • Service Layer pattern
    • Transactions
    • Concurrency / Parallelisation of doing work / collecting data (Virtual Threads)
  • Repository pattern
    • JDBC
    • Not Jakarta Persistence API (JPA) / ORMs
  • External communication components
    • Event Publisher (simple & with Outbox pattern, with CloudEvents (inc. idempotency))
    • Event Subscriber with resubscribe (simple & with Inbox pattern, with CloudEvents (inc. idempotency & feature flag for pausing / totally blocking / releasing processing functionality))
    • HTTP Client (simple & resilient & streamed-response)
    • TCP Socket Send / Receive
    • Blob Storage Client (Google Storage / SFTP Connection)
  • Resiliency patterns (with Resilience4J and/or alternatives)
    • Bulkhead
    • Cache (Simple)
    • Cache (Offline API)
    • Circuit Breaker
    • Rate Limiter
    • Retry
    • Timeout / Time Limiter
  • Telemetry
    • Tracing instrumentation (OpenTelemetry Annotations)
    • Metrics instrumentation (Micrometer or OpenTelemetry)
    • Logging instrumentation (SLF4J and Logback)
    • Profiling instrumentation (Built-in, accessible via JMX for usage with VisualVM, eventually OpenTelemetry)

Reference implementations (testing):

  • Provider Contract Testing the Controller (PACT)
  • Consumer Contract Testing the HTTP Client (PACT)
  • Integration Testing the Repository (in-memory DB)
  • Integration Testing the Event Publisher (Testcontainers)
  • Integration Testing the Event Subscriber (Testcontainers)

Documentation

Docs are found in /docs.

Uses mkdocs to handle documentation, which requires Python (hence the requirements.txt).

Run docs locally by doing:

# Before running the following, I recommend being in a Python Virtual Environment.
pip install -r requirements.txt
mkdocs serve

Then open at localhost:8000.

Running the app locally

mvn spring-boot:run

Template Usage

When being used for templating, remember to set the following in your new repository:

  • Rename all instances of init-microservice with your application name.
  • Refactor the package structure of init.microservice to be what you need.
  • For GitHub Actions, use the Workflow Permissions: "Read and write permissions".
  • Remove/Refactor the infrastructure to ensure it is scoped to the new project (i.e. backend config bucket with a prefix).
  • Remove/Refactor the PACT tests to ensure they don't interfere with the init-microservice PACT tests results (or any others).

About

How I build microservices (in Java).

Topics

Resources

License

Stars

Watchers

Forks

Contributors