From 4656f82089dfbc0f9eefc451d678980fd56ae42c Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Sun, 30 Apr 2023 14:18:36 +0200 Subject: [PATCH] GH-187 - Do not include non-exposed Spring beans that implement interfaces in Application Module Canvas by default. 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. --- .../modulith/core/SpringBean.java | 8 ++-- .../internal/ServiceImplementation.java | 24 +++++++++++ .../springbean/internal/ServiceInterface.java | 21 ++++++++++ .../modulith/core/SpringBeanUnitTests.java | 41 +++++++++++++++++++ .../modulith/core/TestUtils.java | 16 ++++++++ 5 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 spring-modulith-core/src/test/java/example/springbean/internal/ServiceImplementation.java create mode 100644 spring-modulith-core/src/test/java/example/springbean/internal/ServiceInterface.java create mode 100644 spring-modulith-core/src/test/java/org/springframework/modulith/core/SpringBeanUnitTests.java diff --git a/spring-modulith-core/src/main/java/org/springframework/modulith/core/SpringBean.java b/spring-modulith-core/src/main/java/org/springframework/modulith/core/SpringBean.java index fd361ef9..66fa4ea5 100644 --- a/spring-modulith-core/src/main/java/org/springframework/modulith/core/SpringBean.java +++ b/spring-modulith-core/src/main/java/org/springframework/modulith/core/SpringBean.java @@ -77,12 +77,12 @@ public class SpringBean { /** * Returns whether the bean is considered to be an API bean, which means it is either a public type exposed in an API - * package of the module or implements a public API interface. - * - * @return + * package of the module or implements an exposed API interface. */ public boolean isApiBean() { - return module.isExposed(type) || !getInterfacesWithinModule().isEmpty(); + + return module.isExposed(type) + || getInterfacesWithinModule().stream().anyMatch(module::isExposed); } /** diff --git a/spring-modulith-core/src/test/java/example/springbean/internal/ServiceImplementation.java b/spring-modulith-core/src/test/java/example/springbean/internal/ServiceImplementation.java new file mode 100644 index 00000000..bdc38ac8 --- /dev/null +++ b/spring-modulith-core/src/test/java/example/springbean/internal/ServiceImplementation.java @@ -0,0 +1,24 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springbean.internal; + +import org.springframework.stereotype.Component; + +/** + * @author Oliver Drotbohm + */ +@Component +public class ServiceImplementation implements ServiceInterface {} diff --git a/spring-modulith-core/src/test/java/example/springbean/internal/ServiceInterface.java b/spring-modulith-core/src/test/java/example/springbean/internal/ServiceInterface.java new file mode 100644 index 00000000..f365322e --- /dev/null +++ b/spring-modulith-core/src/test/java/example/springbean/internal/ServiceInterface.java @@ -0,0 +1,21 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springbean.internal; + +/** + * @author Oliver Drotbohm + */ +public interface ServiceInterface {} diff --git a/spring-modulith-core/src/test/java/org/springframework/modulith/core/SpringBeanUnitTests.java b/spring-modulith-core/src/test/java/org/springframework/modulith/core/SpringBeanUnitTests.java new file mode 100644 index 00000000..67cbe799 --- /dev/null +++ b/spring-modulith-core/src/test/java/org/springframework/modulith/core/SpringBeanUnitTests.java @@ -0,0 +1,41 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.modulith.core; + +import static org.assertj.core.api.Assertions.*; + +import example.springbean.internal.ServiceImplementation; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link SpringBean}. + * + * @author Oliver Drotbohm + */ +class SpringBeanUnitTests { + + @Test // GH-187 + void doesNotConsiderInternalBeanImplementingInterfaceApiBean() { + + var module = TestUtils.getApplicationModule("example.springbean"); + + assertThat(module.getSpringBeans()) + .filteredOn(SpringBean::isApiBean) + .extracting(SpringBean::getFullyQualifiedTypeName) + .doesNotContain(ServiceImplementation.class.getName()); + } +} diff --git a/spring-modulith-core/src/test/java/org/springframework/modulith/core/TestUtils.java b/spring-modulith-core/src/test/java/org/springframework/modulith/core/TestUtils.java index 1272ef8b..577de560 100644 --- a/spring-modulith-core/src/test/java/org/springframework/modulith/core/TestUtils.java +++ b/spring-modulith-core/src/test/java/org/springframework/modulith/core/TestUtils.java @@ -74,4 +74,20 @@ class TestUtils { public static JavaPackage getPackage(Class packageType) { return JavaPackage.of(TestUtils.getClasses(packageType), packageType.getPackageName()); } + + public static ApplicationModule getApplicationModule(String packageName) { + return new ApplicationModule(getPackage(packageName), false); + } + + private static JavaPackage getPackage(String name) { + return JavaPackage.of(getClasses(name), name); + } + + private static Classes getClasses(String packageName) { + + Assert.hasText(packageName, "Package name must not be null or empty!"); + + return Classes.of(new ClassFileImporter() + .importPackages(packageName)); + } }