Skip to content

Commit bf0c07e

Browse files
committed
GH-1052 - ApplicationModuleSource now uses JavaPackage.findAnnotation(…).
This is to make sure that marker types annotated with @PackageInfo are considered, too. Deprecate JavaPackage.getAnnotation(…) as it's not used anywhere anymore and we would like to consistently consider package info marker types when looking up package annotations.
1 parent cd36bd7 commit bf0c07e

File tree

5 files changed

+54
-17
lines changed

5 files changed

+54
-17
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ static <T extends Annotation> ApplicationModuleSourceMetadata forAnnotation(Clas
220220
@Override
221221
public Optional<ApplicationModuleIdentifier> lookupIdentifier(JavaPackage pkg) {
222222

223-
return pkg.getAnnotation(annotation)
223+
return pkg.findAnnotation(annotation)
224224
.map(extractor)
225225
.filter(StringUtils::hasText)
226226
.map(ApplicationModuleIdentifier::of);

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,9 @@ public Stream<JavaClass> stream() {
271271
*/
272272
public <A extends Annotation> Optional<A> getAnnotation(Class<A> annotationType) {
273273

274-
return packageClasses.that(have(simpleName(PACKAGE_INFO_NAME)) //
275-
.and(are(metaAnnotatedWith(annotationType)))) //
274+
var isPackageInfo = have(simpleName(PACKAGE_INFO_NAME)).or(are(metaAnnotatedWith(PackageInfo.class)));
275+
276+
return packageClasses.that(isPackageInfo.and(are(metaAnnotatedWith(annotationType)))) //
276277
.toOptional() //
277278
.map(it -> it.reflect())
278279
.map(it -> AnnotatedElementUtils.getMergedAnnotation(it, annotationType));
@@ -384,23 +385,22 @@ Optional<JavaPackage> getSubPackage(String localName) {
384385
*/
385386
public <A extends Annotation> Optional<A> findAnnotation(Class<A> annotationType) {
386387

387-
return getAnnotation(annotationType)
388-
.or(() -> {
388+
var isPackageInfo = have(simpleName(PACKAGE_INFO_NAME)).or(are(metaAnnotatedWith(PackageInfo.class)));
389389

390-
var annotatedTypes = toSingle().packageClasses
391-
.that(are(metaAnnotatedWith(PackageInfo.class).and(are(metaAnnotatedWith(annotationType)))))
392-
.stream()
393-
.map(it -> it.getAnnotationOfType(annotationType))
394-
.toList();
390+
var annotatedTypes = toSingle().packageClasses
391+
.that(isPackageInfo.and(are(metaAnnotatedWith(annotationType))))
392+
.stream()
393+
.map(JavaClass::reflect)
394+
.map(it -> AnnotatedElementUtils.findMergedAnnotation(it, annotationType))
395+
.toList();
395396

396-
if (annotatedTypes.size() > 1) {
397+
if (annotatedTypes.size() > 1) {
397398

398-
throw new IllegalStateException(MULTIPLE_TYPES_ANNOTATED_WITH.formatted(name,
399-
FormattableType.of(annotationType).getAbbreviatedFullName(), annotatedTypes));
400-
}
399+
throw new IllegalStateException(MULTIPLE_TYPES_ANNOTATED_WITH.formatted(name,
400+
FormattableType.of(annotationType).getAbbreviatedFullName(), annotatedTypes));
401+
}
401402

402-
return annotatedTypes.isEmpty() ? Optional.empty() : Optional.of(annotatedTypes.get(0));
403-
});
403+
return annotatedTypes.isEmpty() ? Optional.empty() : Optional.of(annotatedTypes.get(0));
404404
}
405405

406406
/**

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,17 @@ void doesNotPickUpIdFromNestedPackages() {
5656
.contains("module", // picked from package name not from annotation in nested package
5757
"gh-1042-nested"); // from annotation in nested package
5858
}
59+
60+
@Test // GH-1052
61+
void detectsApplicationModuleMetadataOnAnnotatedType() {
62+
63+
var pkg = TestUtils.getPackage("reproducers");
64+
65+
var sources = ApplicationModuleSource.from(pkg, root -> root.getSubPackage("gh1052").stream(), false);
66+
67+
assertThat(sources).hasSize(1)
68+
.extracting(ApplicationModuleSource::getIdentifier)
69+
.extracting(ApplicationModuleIdentifier::toString)
70+
.containsExactly("on-marker-type");
71+
}
5972
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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 reproducers.gh1052;
17+
18+
import org.springframework.modulith.ApplicationModule;
19+
20+
/**
21+
* @author Oliver Drotbohm
22+
*/
23+
@ApplicationModule(id = "on-marker-type")
24+
class Marker {}

spring-modulith-integration-test/src/test/java/org/springframework/modulith/core/JavaPackageUnitTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void detectsDirectSubPackages() throws Exception {
5353
void findsAnnotationOnPackageInfo() {
5454

5555
var annotation = JavaPackage.of(Classes.of(PKG_CLASSES), "pkg.onpackage") //
56-
.getAnnotation(ApplicationModule.class);
56+
.findAnnotation(ApplicationModule.class);
5757

5858
assertThat(annotation).hasValueSatisfying(it -> {
5959
assertThat(it.displayName()).isEqualTo("onPackage");

0 commit comments

Comments
 (0)