GH-1082 - 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.
This commit is contained in:
Oliver Drotbohm
2025-02-23 21:40:54 +01:00
parent 0ddb72bc97
commit f61e7d91a0
5 changed files with 54 additions and 17 deletions

View File

@@ -199,7 +199,7 @@ public class ApplicationModuleSource {
@Override
public Optional<ApplicationModuleIdentifier> lookupIdentifier(JavaPackage pkg) {
return pkg.getAnnotation(annotation)
return pkg.findAnnotation(annotation)
.map(extractor)
.filter(StringUtils::hasText)
.map(ApplicationModuleIdentifier::of);

View File

@@ -253,8 +253,9 @@ public class JavaPackage implements DescribedIterable<JavaClass>, Comparable<Jav
*/
public <A extends Annotation> Optional<A> getAnnotation(Class<A> annotationType) {
return packageClasses.that(have(simpleName(PACKAGE_INFO_NAME)) //
.and(are(metaAnnotatedWith(annotationType)))) //
var isPackageInfo = have(simpleName(PACKAGE_INFO_NAME)).or(are(metaAnnotatedWith(PackageInfo.class)));
return packageClasses.that(isPackageInfo.and(are(metaAnnotatedWith(annotationType)))) //
.toOptional() //
.map(it -> it.reflect())
.map(it -> AnnotatedElementUtils.getMergedAnnotation(it, annotationType));
@@ -366,23 +367,22 @@ public class JavaPackage implements DescribedIterable<JavaClass>, Comparable<Jav
*/
public <A extends Annotation> Optional<A> findAnnotation(Class<A> annotationType) {
return getAnnotation(annotationType)
.or(() -> {
var isPackageInfo = have(simpleName(PACKAGE_INFO_NAME)).or(are(metaAnnotatedWith(PackageInfo.class)));
var annotatedTypes = toSingle().packageClasses
.that(are(metaAnnotatedWith(PackageInfo.class).and(are(metaAnnotatedWith(annotationType)))))
.stream()
.map(it -> it.getAnnotationOfType(annotationType))
.toList();
var annotatedTypes = toSingle().packageClasses
.that(isPackageInfo.and(are(metaAnnotatedWith(annotationType))))
.stream()
.map(JavaClass::reflect)
.map(it -> AnnotatedElementUtils.findMergedAnnotation(it, annotationType))
.toList();
if (annotatedTypes.size() > 1) {
if (annotatedTypes.size() > 1) {
throw new IllegalStateException(MULTIPLE_TYPES_ANNOTATED_WITH.formatted(name,
FormattableType.of(annotationType).getAbbreviatedFullName(), annotatedTypes));
}
throw new IllegalStateException(MULTIPLE_TYPES_ANNOTATED_WITH.formatted(name,
FormattableType.of(annotationType).getAbbreviatedFullName(), annotatedTypes));
}
return annotatedTypes.isEmpty() ? Optional.empty() : Optional.of(annotatedTypes.get(0));
});
return annotatedTypes.isEmpty() ? Optional.empty() : Optional.of(annotatedTypes.get(0));
}
/**

View File

@@ -56,4 +56,17 @@ class ApplicationModuleSourceUnitTests {
.contains("module", // picked from package name not from annotation in nested package
"gh-1042-nested"); // from annotation in nested package
}
@Test // GH-1052
void detectsApplicationModuleMetadataOnAnnotatedType() {
var pkg = TestUtils.getPackage("reproducers");
var sources = ApplicationModuleSource.from(pkg, root -> root.getSubPackage("gh1052").stream(), false);
assertThat(sources).hasSize(1)
.extracting(ApplicationModuleSource::getIdentifier)
.extracting(ApplicationModuleIdentifier::toString)
.containsExactly("on-marker-type");
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2025 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 reproducers.gh1052;
import org.springframework.modulith.ApplicationModule;
/**
* @author Oliver Drotbohm
*/
@ApplicationModule(id = "on-marker-type")
class Marker {}

View File

@@ -53,7 +53,7 @@ class JavaPackageUnitTests {
void findsAnnotationOnPackageInfo() {
var annotation = JavaPackage.of(Classes.of(PKG_CLASSES), "pkg.onpackage") //
.getAnnotation(ApplicationModule.class);
.findAnnotation(ApplicationModule.class);
assertThat(annotation).hasValueSatisfying(it -> {
assertThat(it.displayName()).isEqualTo("onPackage");