spring-modulith

https://docs.spring.io/spring-modulith/reference/index.html

Spring Modulith is an opinionated toolkit to build domain-driven, modular applications with Spring Boot. In the same way that Spring Boot has an opinion on the technical arrangement of an application, Spring Modulith implements an opinion on how to structure an app functionally and allows its individual, logical parts to interact with each other. As a result, Spring Modulith enables developers to build applications that are easier to update so they can accommodate changing business requirements over time.


Abstract

spring modulith can be used with jmolecules and archunit.

spring-modulith will:

  • verify your architecture and your code
  • visualize your system design and runtime
  • integrate modules and/or external systems

Verify

spring modulith translates logical functional architecture into a specific and pragmatic code structure.

The arrangement determines the visibility:

  • If some classes are inside a internal package, then it should not be called by another module package. The ApplicationModules.of(Application.class).verify(); to test the modularity will fail otherwise.
  • e.g. example.inventory cannot call the example.order.internal.

Visualize

Describe architecturally important aspects of your system.

You can generate documentation automatically.

Visualize and analyze inter-module traffic at runtime.

Every public API entry point, at every top level package, there’s going to be assigned a span ID generation.

Integrate

Support integration through events.

Example:

@Transactional
public void complete(Order order) {
  // handle order...
  inventory.update(order);
  rewards.update(order);
}

This is tightly coupled! Tightly coupled module with a single commit boundary.

Instead:

private ApplicationEventPublisher events;
@Transactional
public void complete(Order order) {
  events.publishEvent(new OrderCompleted(order));
}

Decouple modules by leveraging spring ApplicationEvents, but still in a single commit boundary!

So we can add a listener:

@ApplicationModuleListener
void on(OrderCompleted event) {
  // business logic
}
  • triggered after publisher’s commit boundary
  • runs asynchronously
  • creates its own commit boundary

However, what happens if the listener fails (we are dealing with in-memory messaging system)? Opt-in for automatic backup and replay of events with the Event Publication Registry by inserting rows in a event_publication table in the database. In other words, the application will be resilient to those failures and will automatically re-consume those events on application restart.

What about 3rd party subscribers? You can use @Externalized to easily transition to external messaging:

  • alpha modulespring framework message busgamma module
  • alpha modulerabbitmqbeta microservice

This will send the event in both message buses.

spring-modulith 1.2: open application modules.

  • You can more control on the boundaries.
  • E.g. have this package only access to 2 other packages.

Demo repository: GitHub - odrotbohm/spring-restbucks: Implementation of the sample from REST in Practice based on Spring projects