Skip to content

Commit e25e690

Browse files
committed
Assert preconditions for MergedAnnotations.from() factory methods
Prior to this commit, if null values were supplied for the RepeatableContainers or AnnotationFilter arguments to `from()` factory methods in MergedAnnotations, certain operations would eventually result in a NullPointerException. This is to be expected; however, the NullPointerException is often swallowed and only logged at INFO level with an exception message similar to the following. > Failed to introspect annotations on org.example.MyClass: NullPointerException In such cases, the INFO log message is not helpful in diagnosing the problem. Furthermore, since the exception is swallowed, the desired operation (e.g., MergedAnnotations.stream(...)) simply returns no results. This commit improves the user experience by eagerly asserting non-null preconditions for required arguments in MergedAnnotations.from() factory methods. Closes gh-25568
1 parent a614abe commit e25e690

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotations.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.stream.Stream;
2626

2727
import org.springframework.lang.Nullable;
28+
import org.springframework.util.Assert;
2829

2930
/**
3031
* Provides access to a collection of merged annotations, usually obtained
@@ -345,6 +346,8 @@ static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStr
345346
static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy,
346347
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
347348

349+
Assert.notNull(repeatableContainers, "RepeatableContainers must not be null");
350+
Assert.notNull(annotationFilter, "AnnotationFilter must not be null");
348351
return TypeMappedAnnotations.from(element, searchStrategy, repeatableContainers, annotationFilter);
349352
}
350353

@@ -405,6 +408,8 @@ static MergedAnnotations from(Object source, Annotation[] annotations, Repeatabl
405408
static MergedAnnotations from(Object source, Annotation[] annotations,
406409
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
407410

411+
Assert.notNull(repeatableContainers, "RepeatableContainers must not be null");
412+
Assert.notNull(annotationFilter, "AnnotationFilter must not be null");
408413
return TypeMappedAnnotations.from(source, annotations, repeatableContainers, annotationFilter);
409414
}
410415

spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import static java.lang.annotation.RetentionPolicy.RUNTIME;
5454
import static org.assertj.core.api.Assertions.assertThat;
5555
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
56+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
5657
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
5758
import static org.assertj.core.api.Assertions.entry;
5859

@@ -73,6 +74,26 @@
7374
*/
7475
class MergedAnnotationsTests {
7576

77+
@Test
78+
void fromPreconditions() {
79+
SearchStrategy strategy = SearchStrategy.DIRECT;
80+
RepeatableContainers containers = RepeatableContainers.standardRepeatables();
81+
82+
assertThatIllegalArgumentException()
83+
.isThrownBy(() -> MergedAnnotations.from(getClass(), strategy, null, AnnotationFilter.PLAIN))
84+
.withMessage("RepeatableContainers must not be null");
85+
assertThatIllegalArgumentException()
86+
.isThrownBy(() -> MergedAnnotations.from(getClass(), strategy, containers, null))
87+
.withMessage("AnnotationFilter must not be null");
88+
89+
assertThatIllegalArgumentException()
90+
.isThrownBy(() -> MergedAnnotations.from(getClass(), new Annotation[0], null, AnnotationFilter.PLAIN))
91+
.withMessage("RepeatableContainers must not be null");
92+
assertThatIllegalArgumentException()
93+
.isThrownBy(() -> MergedAnnotations.from(getClass(), new Annotation[0], containers, null))
94+
.withMessage("AnnotationFilter must not be null");
95+
}
96+
7697
@Test
7798
void streamWhenFromNonAnnotatedClass() {
7899
assertThat(MergedAnnotations.from(NonAnnotatedClass.class).

0 commit comments

Comments
 (0)