Removed the inclusion of the spring-modulith-runtime artifact from the …-starter-core one to avoid issues in native images in a Spring Modulith default setup. As the artifact is still needed to support ApplicationModuleInitializer implementations, we now explicitly check for the presence of those and verify the artifact is actually available and hint the user at explicitly adding it if missing.
We now create artificial root application modules for all root packages to detect violations (for example, types located in root packages referring to module-internal types).
Prior to this commit, the lookup for an ApplicationModule would find modules solely depending on the reference string starting with the base package. That means that a module with base package com.acme.foo, a request for com.acme.foobar would've resulted in a positive match, which of course is wrong.
We now match against either the module's base package or against the reference starting with the base package followed by a dot.
The default for @ApplicationModule(allowedDependencies) is now a single element list with a dedicated token we recognize as "all dependencies allowed". This allows users to declare an empty array explicitly to disallow any outgoing dependencies for an application module. Previously, such a declaration would have allowed any dependency.
We now properly check whether one of a Spring bean's implemented interfaces is exposed by the module before including it in the default rendering of the Application Module Canvas.
The previous modularity verification arrangement assumed the default module detection strategy to be used. To properly support alternative implementations during the verification we now use a dedicated SliceAssignment implementation that assigns types to slices identified by the module they are located in.
Type based named interfaces on types declared in a module's API package still caused the type to be included in the unnamed interface. This is now fixed by explicitly removing named interface types from the unnamed interface.
We now also detect API package types assigned to a named interface without an explicit name as the package name defaulting doesn't work in this case.
Furthermore, named interfaces are now sorted alphabetically to make the unnamed one always appear first.
Both package- and type-level declarations now use the local package name as the named interface's name. This allows to, at the same time, easily declared named interfaces based on packages but also a nice decoupling of the interface definition and the package layout as individual types can be assigned to such interfaces no matter where they are actually declared.
Introduced ApplicationModulesExporter to render an ApplicationModules instances as JSON directly. To avoid a dependency to a JSON library and as we only have to be able to render rather simple arrangements, we just build up the JSON string ourselves.
ApplicationModulesEndpoint now caches the structure calculated once to avoid repeated work.
We now optionally integrate with the JGraphT library to calculate the topological order of modules based on their dependency structure. That order is then exposed in ApplicationModules' iteration and via ….getComparator().
Renamed FormattableJavaClass to FormattableType and allow it to be created from a plain Class as well.
Introduce Spring Modulith Actuator module to expose the application module structure as Spring Boot actuator. This required a Spring Modulith Runtime module to be extracted from the Spring Modulith Observability one. The former now contains the auto-configured ApplicationRuntime and ApplicationModulesRuntime bean instances to be able to bootstrap a ApplicationModules asynchronously on application startup. The actuator module then contains a Spring Boot @Endpoint implementation consuming the ApplicationModules to render JSON describing the application module structure.
Overhauled the module canvas in various ways. By default, we now skip "empty" rows. In other words, if we do not find any published events for example, we skip the entire row. CanvasOptions.revealEmptyRows() can be used to keep those empty rows around. We now also expose all value types and Spring bean references.
Refactored the dependency lookup APIs on ApplicationModule. Both DependencyType and DependencyDepth are now top-level types. Also, ApplicationModuleDependency and ApplicationModuleDependencies were introduced as explicit types. In the course of that, ApplicationModule.getDependencies(…) has got its return type changed from List<ApplicationModule> to ApplicationModuleDependencies. The internal ModuleDependency type has been renamed to QualifiedDependency.
We now render the module component diagrams in C4 style by default. Changed the implementation of ApplicationModuleInformation to fallback to the simple module name by default unless fully-qualified module names are enabled.
0fbf7b introduced a bug in which the named interface referenced by an explicit allowed dependency declaration was accidentally switched to be resolved against the source module, not the target one.
We now verify detected dependencies against optionally explicitly defined ones. Those can refer to named interfaces (via the "moduleName :: namedInterfaceName" syntax). If such an allowed dependency is defined, all dependencies towards other named interfaces (also the unnamed one) are rejected.
Some Javadoc polishing.