Revise use of Objects.requireNonNull()

Historically, we have rarely intentionally thrown a
NullPointerException in the Spring Framework. Instead, we prefer to
throw either an IllegalArgumentException or IllegalStateException
instead of a NullPointerException.

However, changes to the code in recent times have introduced the use of
Objects.requireNonNull(Object) which throws a NullPointerException
without an explicit error message.

The latter ends up providing less context than a NullPointerException
thrown by the JVM (since Java 14) due to actually de-referencing a
null-pointer. See https://openjdk.org/jeps/358.

In light of that, this commit revises our current use of
Objects.requireNonNull(Object) by removing it or replacing it with
Assert.notNull().

However, we still use Objects.requireNonNull(T, String) in a few places
where we are required to throw a NullPointerException in order to
comply with a third-party contract such as Reactive Streams.

Closes gh-32430
This commit is contained in:
Sam Brannen
2024-03-13 14:31:33 +01:00
parent d6422d368a
commit 986c4fd926
11 changed files with 37 additions and 27 deletions

View File

@@ -18,7 +18,6 @@ package org.springframework.test.context.bean.override;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Objects;
import org.junit.jupiter.api.Test;
@@ -49,7 +48,7 @@ class OverrideMetadataTests {
private static OverrideMetadata exampleOverride() throws Exception {
Field field = OverrideMetadataTests.class.getDeclaredField("annotated");
return new ConcreteOverrideMetadata(Objects.requireNonNull(field), field.getAnnotation(NonNull.class),
return new ConcreteOverrideMetadata(field, field.getAnnotation(NonNull.class),
ResolvableType.forClass(String.class), BeanOverrideStrategy.REPLACE_DEFINITION);
}

View File

@@ -19,7 +19,6 @@ package org.springframework.test.context.bean.override.convention;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
import org.junit.jupiter.api.Test;
@@ -91,7 +90,8 @@ class TestBeanOverrideProcessorTests {
Class<?> clazz = ExplicitMethodNameConf.class;
Class<?> returnType = ExampleService.class;
Field field = clazz.getField("a");
TestBean overrideAnnotation = Objects.requireNonNull(field.getAnnotation(TestBean.class));
TestBean overrideAnnotation = field.getAnnotation(TestBean.class);
assertThat(overrideAnnotation).isNotNull();
TestBeanOverrideProcessor processor = new TestBeanOverrideProcessor();
assertThatIllegalStateException()
@@ -106,7 +106,8 @@ class TestBeanOverrideProcessorTests {
void createMetaDataForKnownExplicitMethod() throws Exception {
Class<?> returnType = ExampleService.class;
Field field = ExplicitMethodNameConf.class.getField("b");
TestBean overrideAnnotation = Objects.requireNonNull(field.getAnnotation(TestBean.class));
TestBean overrideAnnotation = field.getAnnotation(TestBean.class);
assertThat(overrideAnnotation).isNotNull();
TestBeanOverrideProcessor processor = new TestBeanOverrideProcessor();
assertThat(processor.createMetadata(field, overrideAnnotation, ResolvableType.forClass(returnType)))
@@ -117,7 +118,8 @@ class TestBeanOverrideProcessorTests {
void createMetaDataWithDeferredCheckForExistenceOfConventionBasedFactoryMethod() throws Exception {
Class<?> returnType = ExampleService.class;
Field field = MethodConventionConf.class.getField("field");
TestBean overrideAnnotation = Objects.requireNonNull(field.getAnnotation(TestBean.class));
TestBean overrideAnnotation = field.getAnnotation(TestBean.class);
assertThat(overrideAnnotation).isNotNull();
TestBeanOverrideProcessor processor = new TestBeanOverrideProcessor();
// When in convention-based mode, createMetadata() will not verify that