GH-6 - More reference documentation.
Application module fundamentals, verification.
This commit is contained in:
@@ -17,12 +17,95 @@ In a Spring Boot application, an application module is a unit of functionality t
|
||||
Spring Moduliths provides different ways of expressing modules, primarily differing in the level of complexity involved in the overall arrangement.
|
||||
This allows developers to start simple and naturally move to more sophisticated means as and if needed.
|
||||
|
||||
|
||||
|
||||
[[fundamentals.modules.simple]]
|
||||
=== Simple Application Modules
|
||||
|
||||
The application's main package is the one that the main application class resides in.
|
||||
The class, that is annotated with `@SpringBootApplication` and usually contains the `main(…)` method used to run it.
|
||||
By default, each direct sub-package of the main package is considered an application module package.
|
||||
|
||||
If this package does not contain any sub-packages, it is considered a simple one.
|
||||
It allows to hide code inside it by using Java's package scope to hide types from being referred to by code residing in other packages and thus not subject for dependency injection into those.
|
||||
Thus, naturally, the module's API consists of all public types in the package.
|
||||
|
||||
Let us have a look at an example arrangement (icon:plus-circle[] denotes a public type, icon:minus-circle[] a package protected one).
|
||||
|
||||
[source, subs="macros"]
|
||||
----
|
||||
icon:cubes[] Example
|
||||
└─ icon:folder[] src/main/java
|
||||
├─ icon:cube[] example <1>
|
||||
| └─ icon:plus-circle[] Application.java
|
||||
└─ icon:cube[] example.inventory <2>
|
||||
├─ icon:plus-circle[] InventoryManagement.java
|
||||
└─ icon:minus-circle[] SomethingInventoryInternal.java
|
||||
----
|
||||
<1> The application's main package `example`.
|
||||
<2> An application module package `inventory`.
|
||||
|
||||
[[fundamentals.modules.advanced]]
|
||||
=== Advanced Application Modules
|
||||
|
||||
If an application module package contains sub-packages, types in those might need to be made public so that it can be referred to from code of the very same module.
|
||||
|
||||
[source, subs="macros"]
|
||||
----
|
||||
icon:cubes[] Example
|
||||
└─ icon:folder[] src/main/java
|
||||
├─ icon:cube[] example
|
||||
| └─ icon:plus-circle[] Application.java
|
||||
├─ icon:cube[] example.inventory
|
||||
| ├─ icon:plus-circle[] InventoryManagement.java
|
||||
| └─ icon:minus-circle[] SomethingInventoryInternal.java
|
||||
├─ icon:cube[] example.order
|
||||
| └─ icon:plus-circle[] OrderManagement.java
|
||||
└─ icon:cube[] example.order.internal
|
||||
└─ icon:plus-circle[] SomethingOrderInternal.java
|
||||
----
|
||||
|
||||
In such an arrangement, the `order` package is considered an API package.
|
||||
Code from other application modules is allowed to refer to types within that.
|
||||
`order.internal`, just as any other sub-package of the application module base package are considered _internal_ ones.
|
||||
Code within those must not be referred to from other modules.
|
||||
Note, how `SomethingOrderInternal` is a public type, likely because `OrderManagement` depends on it.
|
||||
This unfortunately means, that it can also be referred to from other packages such as the `inventory` one.
|
||||
|
||||
[[fundamentals.modules.application-modules]]
|
||||
=== The `ApplicationModules` Type
|
||||
|
||||
Spring Moduliths allows to inspect a codebase to derive an application module model based on the given arrangement and optional configuration.
|
||||
The `spring-modulith-core` artifact contains `ApplicationModules` that can be pointed to a Spring Boot application class:
|
||||
|
||||
[source, java]
|
||||
----
|
||||
var modules = ApplicationModules.of(Application.class);
|
||||
----
|
||||
|
||||
To get an impression about what the analyzed arrangement looks like, we can just write the individual modules contained in the overall model to the console:
|
||||
|
||||
[source, java]
|
||||
----
|
||||
modules.forEach(System.out::println);
|
||||
----
|
||||
|
||||
[source]
|
||||
----
|
||||
## example.inventory ##
|
||||
> Logical name: inventory
|
||||
> Base package: example.inventory
|
||||
> Spring beans:
|
||||
+ ….InventoryManagement
|
||||
o ….SomeInternalComponent
|
||||
|
||||
## example.order ##
|
||||
> Logical name: order
|
||||
> Base package: example.order
|
||||
> Spring beans:
|
||||
+ ….OrderManagement
|
||||
+ ….internal.SomeInternalComponent
|
||||
----
|
||||
|
||||
Note, how each module is listed and the contained Spring components are identified and the respective visibility is rendered, too.
|
||||
|
||||
[[fundamentals.modules.named-interface]]
|
||||
=== Named Interfaces
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
[[verification]]
|
||||
= Verifying Application Module Structure
|
||||
|
||||
[[verification.subheadline]]
|
||||
== Subheadline
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
We can verify whether our code arrangement adheres to the intended constraints by calling the `….verify()` method on our `ApplicationModules` instance:
|
||||
|
||||
[source, java]
|
||||
----
|
||||
ApplicationModules.of(Application.class).verify();
|
||||
----
|
||||
|
||||
The verification includes the following rules:
|
||||
|
||||
* _No cycles on the application module level_ -- the dependencies between modules have to form directed, acyclic graph.
|
||||
* _Efferent module access via API packages only_ -- All references to types that reside in application module internal packages are rejected. See <<fundamentals.modules.advanced>> for details.
|
||||
* _Explicitly allowed application module dependencies only_ (optional) -- An application module can optionally define allowed dependencies via `@ApplicationModule(allowedDependencies = …)`. If those are configured, dependencies to other application modules are rejected.
|
||||
|
||||
Spring Modulith optionally integrates with the jMolecules ArchUnit library and, if present, automatically triggers its verification rules described https://github.com/xmolecules/jmolecules-integrations/tree/main/jmolecules-archunit[here].
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
[[appendix]]
|
||||
= Appendix
|
||||
:jdbc-schema-base: ../../../spring-modulith-events/spring-modulith-events-jdbc/src/main/resources
|
||||
|
||||
Reference in New Issue
Block a user