GH-87 - Expose module structure as actuator endpoint.
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.
This commit is contained in:
@@ -119,9 +119,8 @@ public class ApplicationModule {
|
||||
* @return will never be {@literal null} or empty.
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
|
||||
return information.getDisplayName()
|
||||
.orElseGet(() -> getName());
|
||||
.orElseGet(() -> StringUtils.capitalize(basePackage.getLocalName()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,8 +54,8 @@ import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition;
|
||||
public class ApplicationModules implements Iterable<ApplicationModule> {
|
||||
|
||||
private static final Map<CacheKey, ApplicationModules> CACHE = new HashMap<>();
|
||||
|
||||
private static final ApplicationModuleDetectionStrategy DETECTION_STRATEGY;
|
||||
private static final ImportOption IMPORT_OPTION = new ImportOption.DoNotIncludeTests();
|
||||
|
||||
static {
|
||||
|
||||
@@ -82,13 +82,12 @@ public class ApplicationModules implements Iterable<ApplicationModule> {
|
||||
|
||||
private boolean verified;
|
||||
|
||||
private ApplicationModules(ModulithMetadata metadata, Collection<String> packages,
|
||||
DescribedPredicate<JavaClass> ignored,
|
||||
boolean useFullyQualifiedModuleNames) {
|
||||
protected ApplicationModules(ModulithMetadata metadata, Collection<String> packages,
|
||||
DescribedPredicate<JavaClass> ignored, boolean useFullyQualifiedModuleNames, ImportOption option) {
|
||||
|
||||
this.metadata = metadata;
|
||||
this.allClasses = new ClassFileImporter() //
|
||||
.withImportOption(new ImportOption.DoNotIncludeTests()) //
|
||||
.withImportOption(option) //
|
||||
.importPackages(packages) //
|
||||
.that(not(ignored));
|
||||
|
||||
@@ -189,7 +188,7 @@ public class ApplicationModules implements Iterable<ApplicationModule> {
|
||||
basePackages.addAll(metadata.getAdditionalPackages());
|
||||
|
||||
ApplicationModules modules = new ApplicationModules(metadata, basePackages, key.getIgnored(),
|
||||
metadata.useFullyQualifiedModuleNames());
|
||||
metadata.useFullyQualifiedModuleNames(), IMPORT_OPTION);
|
||||
|
||||
Set<ApplicationModule> sharedModules = metadata.getSharedModuleNames() //
|
||||
.map(modules::getRequiredModule) //
|
||||
@@ -281,7 +280,7 @@ public class ApplicationModules implements Iterable<ApplicationModule> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute all verifications to be applied, unless the verifcation has been executed before.
|
||||
* Execute all verifications to be applied, unless the verification has been executed before.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.springframework.modulith.Modulithic;
|
||||
import org.springframework.modulith.model.Types.SpringTypes;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
interface ModulithMetadata {
|
||||
public interface ModulithMetadata {
|
||||
|
||||
static final String ANNOTATION_MISSING = "Modules can only be retrieved from a root type, but %s is not annotated with either @%s, @%s or @%s!";
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@ import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
class ModuleUnitTest {
|
||||
|
||||
ClassFileImporter importer = new ClassFileImporter();
|
||||
JavaClasses classes = importer.importPackages("com.acme.withatbean"); //
|
||||
JavaPackage javaPackage = JavaPackage.of(Classes.of(classes), "");
|
||||
String packageName = "com.acme.withatbean";
|
||||
JavaClasses classes = new ClassFileImporter().importPackages(packageName);
|
||||
JavaPackage javaPackage = JavaPackage.of(Classes.of(classes), packageName);
|
||||
|
||||
ApplicationModule module = new ApplicationModule(javaPackage, false);
|
||||
|
||||
@@ -69,4 +69,9 @@ class ModuleUnitTest {
|
||||
assertThat(it.getSources()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-87
|
||||
void usesCapitalizedNameAsDisplayNameByDefault() {
|
||||
assertThat(module.getDisplayName()).isEqualTo("Withatbean");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user