= Spring Modulith -- Building Spring Applications for Architecturally Curious Developers
This repository contains the sample code for my talk / workshop "Spring for architecturally curious developers".
It does not use a stable commit history but rather a commit per step in the demo that can be referred to via a tag.
This means that all tags starting with steps/…
are not stable either.
If you're looking for the state of the project for a particular event, skim through the tags starting with events/…
.
They keep a reference to the latest commit of the codebase for that particular event.
== Demo
=== Step 0 -- Spring Modulith Project Skeleton
.Goals
After this step you should…
==== Preparation
$ git checkout step/0
./etc/prepare-talk.sh
(Opens src/main/asciidoc/index.adoc
in browser with Asciidoctor plugin installed).==== Application Overview
customer
, order
, inventory
representing the functional blocks of our application.ModularityTests
-- creates documentation based on the module conventions and verifies the general structure.==== A -- Component References and Visibility
Run documentation tests of ModularityTest
.
** Show how the public Spring components appear in the documentation: component diagrams and Application Module Canvases (AMC).
** Reference Order
-> CustomIdentifier
is reflected in the component relationships with a depends-on-relationship.
Introduce OrderManagement
-> Inventory
dependency to invoke it from OrderManagement.complete(…)
.
** Show how the relationship is reflected in the component diagram as uses-relationship.
Introduce public InventoryRepository
as inventory-internal component.
** Show how it appears in the AMC.
** Introduce invalid dependency from OrderManagement
.
*** Option A -- Make it package private.
Component disappears from AMC and cannot be referred to, as enforced by the compiler.
*** Option B -- Move type into sub-package.
Component disappears from AMC but can still be referred to.
**** Run ModularityTests.verifyModularity()
and see the reference causing the test to fail as an internal component is referenced.
Additional discussion ** Further details of verification *** No cyclic dependencies *** No field injection *** jMolecules verifications (DDD building blocks)
==== Segue
==== B -- Application Module Integration Tests
Run InventoryIntegrationTests
-- Show log output.
Component scanning and auto-configuration restricted to only the inventory
package.
Run OrderIntegrationTests
-- The tests fails as the bean reference to Inventory
cannot be satisfied
** Option A -- Use @MockBean
to include a mock in the bootstrap.
** Option B -- Use @ApplicationModuleTest(bootstrapMode = …)
to include the inventory module in the bootstrap.
Additional discussion ** Domain model relationships important. Cross-references only into aggregate roots via identifiers.
==== Segue
OrderIntegrationTests
tests basic persistence and show JPA boilerplate annotations=== Step 1 -- Fully-implemented Application Modules (optional)
.Goals
After this step you should understand…
==== Preparation
$ git checkout step/1
ModularityTests.renderDocumentation()
.==== Intro
==== Observations
OrderManagement
actively triggers Inventory
.Order
parameter for Inventory.updateStock()
creates a module cycle. 😣==== Segue
=== Step 2 -- Event-based Application Module Integration
.Goals
After this step, you should understand…
==== Preparation
$ git checkout step/2
ModularityTests.renderDocumentation()
.==== Intro
Order.complete()
and implicitly publish it through the ….save(…)
call on the repository.OrderManagement
to Inventory
.Inventory
and rather test for the event publication only.==== Observation
=== Step 3 -- Switch to @ApplicationModuleListener
==== Preparation
$ git checkout step/3
ModularityTests.renderDocumentation()
.==== Intro
Inventory.updateStock(OrderCompletedEvent)
and discuss how the behavior changed.OrderIntegrationTests.completionCausesEventPublished(Scenario)
and discuss Scenario
API.==== Observation
==== Segue
=== Step 4 -- Event Publication Registry
.Goals
After this step, you should understand…
==== Preparation
$ git checkout step/4
==== Intro
==== Observations
EventPublicationRegistryTests
EventPublicationRegistryTests
=== Step 5 -- Actuators
.Goals
After this step you should understand…
==== Preparation
$ git checkout step/5
==== Intro
modulith
actuator was registered for web exposure in application.properties
.==== Observations
./mvnw spring-boot:run -Pactuator
).modulith
resource is exposed.=== Step 6 -- Observability
==== Preparation
$ git checkout step/6
=== Step 7 -- Test optimizations
==== Preparation
$ git checkout step/7
==== Intro
./mvnw clean test
.==== Observations
== Nerd Stuff
A couple of useful scripts to be found in etc
:
prepare-talk.sh
-- opens a browser pointing to the documentation source file.publish.sh
-- pushes current state, retags commits and pushes those as well.remove-remote-tags.sh
-- Removes all step tags from the remote repository.retag.sh
-- execute each time you change something about an individual commit to update the steps/…
tags to be used in demos.test-all-commits.sh
-- runs the Maven build for all commits of the main branch.test-all-tags.sh
-- runs the Maven build for all step/…
tags.