Skip to content

Commit fd3542b

Browse files
committed
GH-1139 - Detect @NamedInterface on composed annotations.
1 parent 2fcde20 commit fd3542b

File tree

5 files changed

+68
-1
lines changed

5 files changed

+68
-1
lines changed

spring-modulith-core/src/main/java/org/springframework/modulith/core/NamedInterfaces.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ private static List<NamedInterface> ofAnnotatedTypes(Classes classes) {
291291
.filter(it -> !JavaPackage.isPackageInfoType(it)) //
292292
.forEach(it -> {
293293

294-
if (!it.isAnnotatedWith(org.springframework.modulith.NamedInterface.class)) {
294+
if (!it.isMetaAnnotatedWith(org.springframework.modulith.NamedInterface.class)) {
295295
return;
296296
}
297297

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.metani;
17+
18+
/**
19+
* @author Oliver Drotbohm
20+
*/
21+
@ModuleApi
22+
public class Exposed {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.metani;
17+
18+
import static java.lang.annotation.ElementType.*;
19+
import static java.lang.annotation.RetentionPolicy.*;
20+
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.Target;
23+
24+
import org.springframework.modulith.NamedInterface;
25+
26+
/**
27+
* @author Oliver Drotbohm
28+
*/
29+
@Retention(RUNTIME)
30+
@Target({ TYPE })
31+
@NamedInterface("api")
32+
public @interface ModuleApi {}

spring-modulith-core/src/test/java/org/springframework/modulith/core/ApplicationModulesUnitTests.java

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ void discoversComplexModuleArrangement() {
3737
.containsExactlyInAnyOrder(
3838
"invalid",
3939
"customId",
40+
"metani",
4041
"ni",
4142
"ni.nested",
4243
"ni.nested.b.first",

spring-modulith-core/src/test/java/org/springframework/modulith/core/NamedInterfacesUnitTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,18 @@ void doesNotExcludeAnyPackagesByDefault() {
142142
assertThat(interfaces).hasSizeGreaterThan(1);
143143
}
144144

145+
@Test // GH-1139
146+
void discoveredNamedInterfaceOnComposedAnnotation() {
147+
148+
var pkg = TestUtils.getPackage(example.metani.Exposed.class);
149+
150+
var result = NamedInterfaces.discoverNamedInterfaces(pkg);
151+
152+
assertThat(result).hasSize(2)
153+
.extracting(NamedInterface::getName)
154+
.containsExactlyInAnyOrder(NamedInterface.UNNAMED_NAME, "api");
155+
}
156+
145157
private static void assertInterfaceContains(NamedInterfaces interfaces, String name, Class<?>... types) {
146158

147159
var classNames = Arrays.stream(types).map(Class::getName).toArray(String[]::new);

0 commit comments

Comments
 (0)