Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Spring Modulith – A Deep Dive

Spring Modulith – A Deep Dive

Slides of the workshop I gave at SpringOne 2023, Las Vegas.

Oliver Drotbohm

August 23, 2023
Tweet

More Decks by Oliver Drotbohm

Other Decks in Programming

Transcript

  1. "A system is a whole that consists of parts, each

    of which can affect its behavior and properties. … Each part of the system is dependent on some other part."
  2. The System Order Product Products Product details Prices Order Line

    items Customer Details Address Account Auth PIM Pricing Invoicing Shipment
  3. Monolith VS. Microservice Module A Module B Module C Module

    B Module C Module A Bounded Context Deployment Unit Internal invocation External invocation
  4. Monolith VS. Microservice Module A Module B Module C Bounded

    Context Deployment Unit Internal invocation External invocation !"
  5. Monolith The application packages the implementation of multiple Bounded Contexts

    as a single deployment unit. Easy to refactor Simple IDE features can be used to move significant parts of the codebase around and update all client code at the same time. Easy to test the overall system An overall test run is a matter of running a Spring (Boot) integration test.
  6. Monolith 21 The application packages the implementation of multiple Bounded

    Contexts as a single deployment unit. Likely to degrade unless explicitly managed Unless explicit means of monitoring the structure are employed, the architecture will degrade over time. Harder to test individual Bounded Contexts Testing individual bounded contexts requires extra effort in setting up Spring configuration to make sure components can be picked up for each module individually.
  7. Microservices A bounded context defines the boundaries of the deployment

    artifact. Often parts of the context are even deployed as separate processes. ◦ Bounded Context interaction is remote The interaction between BCs involved remote interaction, either by sending messages or invoke other systems directly. This accumulates latency, and requires additional measures against the collaborators being unavailable which increases complexity. ◦ Testing individual modules Testing individual modules usually requires collaborating systems to be bootstrapped, stubbed or mocked.
  8. Microservices A bounded context defines the boundaries of the deployment

    artifact. Often parts of the context are even deployed as separate processes. Hard to refactor context boundaries Context boundaries are implemented as published APIs that have to be evolved carefully as clients cannot be updated to server changes immediately. Hard to test the overall system While testing an individual system usually works reasonably well, integration testing multiple systems together is complex and creates additional overhead.
  9. Domain Based Structure Domain Based Boundaries via Dan North –

    CUPID—for joyful coding Video cast episode @ Software Architektur im Stream (english)
  10. Taking a domain-based approach to the code structure makes it

    easy to understand what the code is there for, and easy to navigate to wherever you need to be for anything more complicated than “make that button light blue”. Instead, the layout of code—the directory names, the relationships of child and sibling folders, the grouping and naming of related files—should mirror the problem domain as closely as possible. Domain-Based Structure Domain-Based Boundaries “ “ Source: Dan North, CUPID—for joyful coding
  11. Web Business logic Data access @Repository Order Inventory … @Controller

    @Service Verification? Testing? Documentation? Observation?
  12. Some conventions… 01 10 M M 01 10 Allowed by

    the compiler Allowed by Moduliths Rejected by the compiler Rejected by Moduliths Public Package protected Bounded Context Java Package
  13. Module B moduleB Module A moduleA 57 ComponentA ComponentAImpl ComponentB

    ComponentBImpl Public Package protected Bounded Context Java Package 01 10 01 10
  14. package com.acme @SpringBootApplication class MyApplication { … } var modules

    = ApplicationModules.of(MyApplication.class); modules.verify(…); Applies package conventions Verifies rules for MyApplication
  15. Infrastructure Application Domain Primary (driving) Adapters @Controller @KafkaListener Spring beans

    Published events Event listeners Secondary (driven) Adapters Repositories Message publishers
  16. Infrastructure Application Domain Primary (driving) Adapters @Controller @KafkaListener Spring beans

    Published events Event listeners Secondary (driven) Adapters Repositories Message publishers
  17. Module A moduleA.foo Module B moduleB moduleA 66 ComponentA ComponentAImpl

    ComponentB ComponentBImpl moduleA.bar SupportA SupportAImpl 01 10 M 01 10 01 10 Public Package protected Bounded Context Java Package
  18. Infrastructure Application Domain Primary (driving) Adapters @Controller @KafkaListener Spring beans

    Published events Event listeners Secondary (driven) Adapters Repositories Message publishers
  19. Infrastructure Application Domain Primary (driving) Adapters @Controller @KafkaListener Spring beans

    Published events Event listeners Secondary (driven) Adapters Repositories Message publishers
  20. "A system is never the sum of its parts, it's

    the product of their interactions."
  21. Application events – Error Scenarios The service fails Only standard

    event listeners up until the failure will have been executed. Assuming the already triggered event listeners also execute transactional logic, the local transaction is rolled back and the system is still in a strongly consistent state. Transactional event listeners are not invoked in the first place.
  22. Application events – Error Scenarios A synchronous event listener fails

    In case a normal event listener fails the entire transaction will roll back. This enables strong consistency between the event producer and the listeners registered but also bears the risk of supporting functionality interfering with the primary one, causing the latter to fail for less important reasons. The tradeoff here could be to move to a transactional event listener and embrace eventual consistency.
  23. Application events – Error Scenarios A transactional event listener fails

    In case a transactional event lister fails or the application crashes while transactional event listeners are executed, the event is lost and functionality might not have been invoked. Other transactional event listeners will still be triggered. BONUS: An asynchronous event listener fails The event is lost but the primary functionality can still succeed as the event is handled in a separate thread. Retry mechanisms can (should?) be deployed in case some form of recovery is needed.
  24. Infrastructure Application Domain Primary (driving) Adapters @Controller @KafkaListener Spring beans

    Published events Event listeners Secondary (driven) Adapters Repositories Message publishers
  25. My Component Provided Interface Exposed Service API Spring Beans available

    for DI Exposed Aggregates Primary elements of the domain and constraints Published events Events the component emits Required Interface Consumed Service API External dependencies of Spring beans Configuration Spring Boot configuration properties Consumed events Events that the component reacts to
  26. Spring Modulith A convention to map modules to packages Simple

    set of access rules and API to verify Test support to bootstrap modules Event publication registry Documentation support Actuator and observability support
  27. Spring Modulith Additional implementations of the Event Publication Registry Automatic

    externalization of events to Kafka, AMQP, potentially Redis
  28. Resources Moduliths Project website on GitHub Majestic Modular Monoliths Video

    on Youtube Modular Monoliths Simon Brown – Video on YouTube Refactoring to a System of Systems Video on YouTube
  29. Resources Software Architecture for Developers Simon Brown – Books Just

    Enough Software Architecture George Fairbanks – Book Architecture, Design, Implementation Ammon H. Eden, Rick Kazman – Paper Sustainable Software Architecture Carola Lilienthal – Book The Programmer's Brain Felienne Hermans – Book