Add nullability annotations to tests in core/spring-boot

See gh-47263
This commit is contained in:
Moritz Halbritter
2025-10-02 14:34:34 +02:00
parent 1fda419b17
commit 418e057afc
214 changed files with 2074 additions and 1118 deletions
+6
View File
@@ -50,6 +50,8 @@ dependencies {
optional("org.yaml:snakeyaml")
optional("tools.jackson.core:jackson-databind")
testCompileOnly("com.google.code.findbugs:jsr305")
testFixturesCompileOnly(project(":test-support:spring-boot-test-support"))
testImplementation(project(":test-support:spring-boot-test-support"))
@@ -106,3 +108,7 @@ sourceSets {
}
}
}
tasks.named("compileTestJava") {
options.nullability.checking = "tests"
}
@@ -18,6 +18,7 @@ package org.springframework.boot;
import java.io.PrintStream;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -49,7 +50,7 @@ import static org.mockito.Mockito.reset;
@ExtendWith({ MockitoExtension.class, OutputCaptureExtension.class })
class BannerTests {
private ConfigurableApplicationContext context;
private @Nullable ConfigurableApplicationContext context;
@AfterEach
void cleanUp() {
@@ -59,6 +60,7 @@ class BannerTests {
}
@Captor
@SuppressWarnings("NullAway.Init")
private ArgumentCaptor<Class<?>> sourceClassCaptor;
@Test
@@ -123,7 +125,7 @@ class BannerTests {
static class DummyBanner implements Banner {
@Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
public void printBanner(Environment environment, @Nullable Class<?> sourceClass, PrintStream out) {
out.println("My Banner");
}
@@ -35,6 +35,7 @@ class DefaultApplicationArgumentsTests {
private static final String[] ARGS = new String[] { "--foo=bar", "--foo=baz", "--debug", "spring", "boot" };
@Test
@SuppressWarnings("NullAway") // Test null check
void argumentsMustNotBeNull() {
assertThatIllegalArgumentException().isThrownBy(() -> new DefaultApplicationArguments((String[]) null))
.withMessageContaining("'args' must not be null");
@@ -37,6 +37,7 @@ import static org.mockito.Mockito.withSettings;
class ExitCodeGeneratorsTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void addAllWhenGeneratorsIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> {
List<ExitCodeGenerator> generators = null;
@@ -45,6 +46,7 @@ class ExitCodeGeneratorsTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void addWhenGeneratorIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ExitCodeGenerators().add(null))
.withMessageContaining("'generator' must not be null");
@@ -16,6 +16,8 @@
package org.springframework.boot;
import org.jspecify.annotations.Nullable;
import org.springframework.mock.env.MockEnvironment;
/**
@@ -27,12 +29,12 @@ import org.springframework.mock.env.MockEnvironment;
public class MockApplicationEnvironment extends MockEnvironment {
@Override
protected String doGetActiveProfilesProperty() {
protected @Nullable String doGetActiveProfilesProperty() {
return null;
}
@Override
protected String doGetDefaultProfilesProperty() {
protected @Nullable String doGetDefaultProfilesProperty() {
return null;
}
@@ -16,6 +16,7 @@
package org.springframework.boot;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -35,7 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
class OverrideSourcesTests {
private ConfigurableApplicationContext context;
private @Nullable ConfigurableApplicationContext context;
@AfterEach
void cleanUp() {
@@ -22,6 +22,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -170,12 +171,12 @@ class ResourceBannerTests {
assertThat(banner).startsWith("banner bar");
}
private String printBanner(Resource resource, String bootVersion, String applicationVersion,
String applicationTitle) {
private String printBanner(Resource resource, @Nullable String bootVersion, @Nullable String applicationVersion,
@Nullable String applicationTitle) {
return printBanner(new MockResourceBanner(resource, bootVersion, applicationTitle), applicationVersion);
}
private String printBanner(ResourceBanner banner, String applicationVersion) {
private String printBanner(ResourceBanner banner, @Nullable String applicationVersion) {
MockEnvironment environment = new MockEnvironment();
if (applicationVersion != null) {
environment.setProperty("spring.application.version", applicationVersion);
@@ -189,23 +190,23 @@ class ResourceBannerTests {
static class MockResourceBanner extends ResourceBanner {
private final String bootVersion;
private final @Nullable String bootVersion;
private final String applicationTitle;
private final @Nullable String applicationTitle;
MockResourceBanner(Resource resource, String bootVersion, String applicationTitle) {
MockResourceBanner(Resource resource, @Nullable String bootVersion, @Nullable String applicationTitle) {
super(resource);
this.bootVersion = bootVersion;
this.applicationTitle = applicationTitle;
}
@Override
protected String getBootVersion() {
protected @Nullable String getBootVersion() {
return this.bootVersion;
}
@Override
protected String getApplicationTitle(Class<?> sourceClass) {
protected @Nullable String getApplicationTitle(@Nullable Class<?> sourceClass) {
return this.applicationTitle;
}
@@ -213,23 +214,23 @@ class ResourceBannerTests {
static class MutatingResourceBanner extends MockResourceBanner {
MutatingResourceBanner(Resource resource, String bootVersion, String applicationTitle) {
MutatingResourceBanner(Resource resource, String bootVersion, @Nullable String applicationTitle) {
super(resource, bootVersion, applicationTitle);
}
@Override
protected List<PropertyResolver> getPropertyResolvers(Environment environment, Class<?> sourceClass) {
protected List<PropertyResolver> getPropertyResolvers(Environment environment, @Nullable Class<?> sourceClass) {
List<PropertyResolver> resolvers = super.getPropertyResolvers(environment, sourceClass);
PropertyResolver resolver = new AbstractPropertyResolver() {
@Override
@SuppressWarnings("unchecked")
public <T> T getProperty(String key, Class<T> targetType) {
public <T> @Nullable T getProperty(String key, Class<T> targetType) {
return String.class.equals(targetType) ? (T) getPropertyAsRawString(key) : null;
}
@Override
protected String getPropertyAsRawString(String key) {
protected @Nullable String getPropertyAsRawString(String key) {
return ("foo".equals(key)) ? "bar" : null;
}
@@ -18,6 +18,7 @@ package org.springframework.boot;
import java.nio.file.Path;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
@@ -101,7 +102,7 @@ class SpringApplicationAotProcessorTests {
@Configuration(proxyBeanMethods = false)
public static class SampleApplication {
public static String[] argsHolder;
public static String @Nullable [] argsHolder;
public static boolean postRunInvoked;
@@ -25,6 +25,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.awaitility.Awaitility;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
@@ -152,6 +153,7 @@ class SpringApplicationShutdownHookTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void addHandlerActionWhenNullThrowsException() {
TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook();
assertThatIllegalArgumentException().isThrownBy(() -> shutdownHook.getHandlers().add(null))
@@ -168,6 +170,7 @@ class SpringApplicationShutdownHookTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void removeHandlerActionWhenNullThrowsException() {
TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook();
assertThatIllegalArgumentException().isThrownBy(() -> shutdownHook.getHandlers().remove(null))
@@ -244,15 +247,16 @@ class SpringApplicationShutdownHookTests {
private final List<Object> finished;
private final CountDownLatch closing;
private final @Nullable CountDownLatch closing;
private final CountDownLatch proceedWithClose;
private final @Nullable CountDownLatch proceedWithClose;
TestApplicationContext(List<Object> finished) {
this(finished, null, null);
}
TestApplicationContext(List<Object> finished, CountDownLatch closing, CountDownLatch proceedWithClose) {
TestApplicationContext(List<Object> finished, @Nullable CountDownLatch closing,
@Nullable CountDownLatch proceedWithClose) {
this.finished = finished;
this.closing = closing;
this.proceedWithClose = proceedWithClose;
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -32,6 +33,7 @@ import java.util.function.Supplier;
import jakarta.annotation.PostConstruct;
import org.assertj.core.api.Condition;
import org.awaitility.Awaitility;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -167,7 +169,7 @@ class SpringApplicationTests {
private String headlessProperty;
private ConfigurableApplicationContext context;
private @Nullable ConfigurableApplicationContext context;
private Environment getEnvironment() {
if (this.context != null) {
@@ -202,6 +204,8 @@ class SpringApplicationTests {
}
@Test
@SuppressWarnings("NullAway")
// Test null check
void sourcesMustNotBeNull() {
assertThatIllegalArgumentException().isThrownBy(() -> new SpringApplication((Class<?>[]) null).run())
.withMessageContaining("'primarySources' must not be null");
@@ -360,7 +364,9 @@ class SpringApplicationTests {
application.setWebApplicationType(WebApplicationType.NONE);
AtomicReference<ApplicationReadyEvent> reference = addListener(application, ApplicationReadyEvent.class);
this.context = application.run("--foo=bar");
assertThat(application).isSameAs(reference.get().getSpringApplication());
ApplicationReadyEvent event = reference.get();
assertThat(event).isNotNull();
assertThat(application).isSameAs(event.getSpringApplication());
}
@Test
@@ -369,7 +375,9 @@ class SpringApplicationTests {
application.setWebApplicationType(WebApplicationType.NONE);
AtomicReference<ContextRefreshedEvent> reference = addListener(application, ContextRefreshedEvent.class);
this.context = application.run("--foo=bar");
assertThat(this.context).isSameAs(reference.get().getApplicationContext());
ContextRefreshedEvent event = reference.get();
assertThat(event).isNotNull();
assertThat(this.context).isSameAs(event.getApplicationContext());
// Custom initializers do not switch off the defaults
assertThat(getEnvironment().getProperty("foo")).isEqualTo("bar");
}
@@ -487,6 +495,7 @@ class SpringApplicationTests {
assertThat(environment.getProperty("foo")).isEqualTo("bar");
CompositePropertySource composite = (CompositePropertySource) environment.getPropertySources()
.get("commandLineArgs");
assertThat(composite).isNotNull();
assertThat(composite.getPropertySources()).hasSize(2);
assertThat(composite.getPropertySources()).first()
.matches((source) -> source.getName().equals("springApplicationCommandLineArgs"),
@@ -878,8 +887,9 @@ class SpringApplicationTests {
@Test
void defaultCommandLineArgs() {
SpringApplication application = new SpringApplication(ExampleConfig.class);
application.setDefaultProperties(
StringUtils.splitArrayElementsIntoProperties(new String[] { "baz=", "bar=spam" }, "="));
Properties properties = StringUtils.splitArrayElementsIntoProperties(new String[] { "baz=", "bar=spam" }, "=");
assertThat(properties).isNotNull();
application.setDefaultProperties(properties);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run("--bar=foo", "bucket", "crap");
assertThat(this.context).isInstanceOf(AnnotationConfigApplicationContext.class);
@@ -936,7 +946,7 @@ class SpringApplicationTests {
this.context = application.run();
assertThat(events).hasAtLeastOneElementOfType(ApplicationPreparedEvent.class);
assertThat(events).hasAtLeastOneElementOfType(ContextRefreshedEvent.class);
verifyRegisteredListenerSuccessEvents();
verifyRegisteredListenerSuccessEvents(this.context);
}
@Test
@@ -949,12 +959,12 @@ class SpringApplicationTests {
this.context = application.run();
assertThat(events).hasAtLeastOneElementOfType(ApplicationPreparedEvent.class);
assertThat(events).hasAtLeastOneElementOfType(ContextRefreshedEvent.class);
verifyRegisteredListenerSuccessEvents();
verifyRegisteredListenerSuccessEvents(this.context);
}
@SuppressWarnings("unchecked")
private void verifyRegisteredListenerSuccessEvents() {
ApplicationListener<ApplicationEvent> listener = this.context.getBean("testApplicationListener",
private void verifyRegisteredListenerSuccessEvents(ConfigurableApplicationContext context) {
ApplicationListener<ApplicationEvent> listener = context.getBean("testApplicationListener",
ApplicationListener.class);
InOrder inOrder = Mockito.inOrder(listener);
then(listener).should(inOrder).onApplicationEvent(isA(ContextRefreshedEvent.class));
@@ -1224,9 +1234,11 @@ class SpringApplicationTests {
application.setWebApplicationType(WebApplicationType.NONE);
application.addBootstrapRegistryInitializer((bootstrapContext) -> {
bootstrapContext.register(String.class, InstanceSupplier.of("boot"));
bootstrapContext.addCloseListener((event) -> event.getApplicationContext()
.getBeanFactory()
.registerSingleton("test", event.getBootstrapContext().get(String.class)));
bootstrapContext.addCloseListener((event) -> {
String string = event.getBootstrapContext().get(String.class);
assertThat(string).isNotNull();
event.getApplicationContext().getBeanFactory().registerSingleton("test", string);
});
});
ConfigurableApplicationContext applicationContext = application.run();
assertThat(applicationContext.getBean("test")).isEqualTo("boot");
@@ -1272,8 +1284,9 @@ class SpringApplicationTests {
.map(ApplicationFailedEvent.class::cast)
.findFirst()
.get();
assertThat(SpringApplicationShutdownHookInstance.get())
.didNotRegisterApplicationContext(failure.getApplicationContext());
ConfigurableApplicationContext context = failure.getApplicationContext();
assertThat(context).isNotNull();
assertThat(SpringApplicationShutdownHookInstance.get()).didNotRegisterApplicationContext(context);
}
@Test
@@ -1283,6 +1296,7 @@ class SpringApplicationTests {
SpringApplicationRunListener runListener = mock(SpringApplicationRunListener.class);
SpringApplicationHook hook = (springApplication) -> runListener;
SpringApplication.withHook(hook, () -> this.context = application.run());
assertThat(this.context).isNotNull();
then(runListener).should().starting(any());
then(runListener).should().contextPrepared(this.context);
then(runListener).should().ready(eq(this.context), any());
@@ -1320,7 +1334,11 @@ class SpringApplicationTests {
SpringApplicationHook hook = (springApplication) -> runListener;
assertThatExceptionOfType(SpringApplication.AbandonedRunException.class)
.isThrownBy(() -> SpringApplication.withHook(hook, () -> application.run()))
.satisfies((ex) -> assertThat(ex.getApplicationContext().isRunning()).isFalse());
.satisfies((ex) -> {
ConfigurableApplicationContext context = ex.getApplicationContext();
assertThat(context).isNotNull();
assertThat(context.isRunning()).isFalse();
});
then(runListener).should().starting(any());
then(runListener).should().contextPrepared(any());
then(runListener).should(never()).ready(any(), any());
@@ -1389,7 +1407,10 @@ class SpringApplicationTests {
.with(SingleUseAdditionalConfig.class)
.run()
.getApplicationContext();
assertThatNoException().isThrownBy(() -> this.context.getBean(SingleUseAdditionalConfig.class));
assertThatNoException().isThrownBy(() -> {
assertThat(this.context).isNotNull();
this.context.getBean(SingleUseAdditionalConfig.class);
});
}
@Test
@@ -1540,7 +1561,7 @@ class SpringApplicationTests {
static class TestSpringApplication extends SpringApplication {
private BeanDefinitionLoader loader;
private @Nullable BeanDefinitionLoader loader;
private boolean useMockLoader;
@@ -1567,7 +1588,7 @@ class SpringApplicationTests {
return this.loader;
}
BeanDefinitionLoader getLoader() {
@Nullable BeanDefinitionLoader getLoader() {
return this.loader;
}
@@ -1855,6 +1876,7 @@ class SpringApplicationTests {
private final String[] expectedBefore;
@SuppressWarnings("NullAway.Init")
private ApplicationContext applicationContext;
private final int order;
@@ -1926,14 +1948,14 @@ class SpringApplicationTests {
static class ExitCodeListener implements ApplicationListener<ExitCodeEvent> {
private Integer exitCode;
private @Nullable Integer exitCode;
@Override
public void onApplicationEvent(ExitCodeEvent event) {
this.exitCode = event.getExitCode();
}
Integer getExitCode() {
@Nullable Integer getExitCode() {
return this.exitCode;
}
@@ -1971,7 +1993,9 @@ class SpringApplicationTests {
@SuppressWarnings("unchecked")
<E extends ApplicationEvent> E getEvent(Class<E> type) {
return (E) this.events.get(type).get(0);
List<ApplicationEvent> events = this.events.get(type);
assertThat(events).isNotNull();
return (E) events.get(0);
}
}
@@ -17,6 +17,7 @@
package org.springframework.boot;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -133,11 +134,11 @@ class StartupInfoLoggerTests {
private final long startTime = System.currentTimeMillis();
private final Long uptime;
private final @Nullable Long uptime;
private final String action;
TestStartup(Long uptime, String action) {
TestStartup(@Nullable Long uptime, String action) {
this.uptime = uptime;
this.action = action;
started();
@@ -149,7 +150,7 @@ class StartupInfoLoggerTests {
}
@Override
protected Long processUptime() {
protected @Nullable Long processUptime() {
return this.uptime;
}
@@ -24,6 +24,7 @@ import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -54,7 +55,7 @@ class SpringApplicationAdminMXBeanRegistrarTests {
private MBeanServer mBeanServer;
private ConfigurableApplicationContext context;
private @Nullable ConfigurableApplicationContext context;
@BeforeEach
void setup() {
@@ -90,15 +91,18 @@ class SpringApplicationAdminMXBeanRegistrarTests {
SpringApplicationAdminMXBeanRegistrar registrar = new SpringApplicationAdminMXBeanRegistrar(OBJECT_NAME);
ConfigurableApplicationContext context = mock(ConfigurableApplicationContext.class);
registrar.setApplicationContext(context);
registrar.onApplicationReadyEvent(new ApplicationReadyEvent(new SpringApplication(), null,
registrar.onApplicationReadyEvent(new ApplicationReadyEvent(new SpringApplication(), new String[0],
mock(ConfigurableApplicationContext.class), null));
assertThat(isApplicationReady(registrar)).isFalse();
registrar.onApplicationReadyEvent(new ApplicationReadyEvent(new SpringApplication(), null, context, null));
registrar
.onApplicationReadyEvent(new ApplicationReadyEvent(new SpringApplication(), new String[0], context, null));
assertThat(isApplicationReady(registrar)).isTrue();
}
private boolean isApplicationReady(SpringApplicationAdminMXBeanRegistrar registrar) {
return (Boolean) ReflectionTestUtils.getField(registrar, "ready");
Object field = ReflectionTestUtils.getField(registrar, "ready");
assertThat(field).isNotNull();
return (Boolean) field;
}
@Test
@@ -40,6 +40,7 @@ class AvailabilityChangeEventTests {
private final Object source = new Object();
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenStateIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new AvailabilityChangeEvent<>(this.source, null))
.withMessage("Payload must not be null");
@@ -18,9 +18,11 @@ package org.springframework.boot.bootstrap;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.AssertProvider;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.bootstrap.BootstrapRegistry.InstanceSupplier;
@@ -34,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIOException;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link DefaultBootstrapContext}.
@@ -49,12 +52,14 @@ class DefaultBootstrapContextTests {
private final StaticApplicationContext applicationContext = new StaticApplicationContext();
@Test
@SuppressWarnings("NullAway") // Test null check
void registerWhenTypeIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.context.register(null, InstanceSupplier.of(1)))
.withMessage("'type' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void registerWhenRegistrationIsNullThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.context.register(Integer.class, null))
.withMessage("'instanceSupplier' must not be null");
@@ -206,20 +211,23 @@ class DefaultBootstrapContextTests {
@Test
void getOrElseSupplyWhenNoRegistrationReturnsSupplied() {
this.context.register(Number.class, InstanceSupplier.of(1));
assertThat(this.context.getOrElseSupply(Long.class, () -> -1L)).isEqualTo(-1);
Supplier<@Nullable Long> supplier = () -> -1L;
assertThat(this.context.getOrElseSupply(Long.class, supplier)).isEqualTo(-1);
}
@Test
void getOrElseSupplyWhenRegisteredAsNullReturnsNull() {
this.context.register(Number.class, InstanceSupplier.of(null));
assertThat(this.context.getOrElseSupply(Number.class, () -> -1L)).isNull();
Supplier<@Nullable Number> supplier = () -> -1L;
assertThat(this.context.getOrElseSupply(Number.class, supplier)).isNull();
}
@Test
void getOrElseSupplyCreatesOnlyOneInstance() {
this.context.register(Integer.class, InstanceSupplier.from(this.counter::getAndIncrement));
assertThat(this.context.getOrElseSupply(Integer.class, () -> -1)).isZero();
assertThat(this.context.getOrElseSupply(Integer.class, () -> -1)).isZero();
Supplier<@Nullable Integer> supplier = () -> -1;
assertThat(this.context.getOrElseSupply(Integer.class, supplier)).isZero();
assertThat(this.context.getOrElseSupply(Integer.class, supplier)).isZero();
}
@Test
@@ -265,14 +273,14 @@ class DefaultBootstrapContextTests {
void instanceSupplierGetScopeWhenNotConfiguredReturnsSingleton() {
InstanceSupplier<String> supplier = InstanceSupplier.of("test");
assertThat(supplier.getScope()).isEqualTo(Scope.SINGLETON);
assertThat(supplier.get(null)).isEqualTo("test");
assertThat(supplier.get(mock(BootstrapContext.class))).isEqualTo("test");
}
@Test
void instanceSupplierWithScopeChangesScope() {
InstanceSupplier<String> supplier = InstanceSupplier.of("test").withScope(Scope.PROTOTYPE);
assertThat(supplier.getScope()).isEqualTo(Scope.PROTOTYPE);
assertThat(supplier.get(null)).isEqualTo("test");
assertThat(supplier.get(mock(BootstrapContext.class))).isEqualTo("test");
}
private static final class TestCloseListener
@@ -280,9 +288,9 @@ class DefaultBootstrapContextTests {
private int called;
private BootstrapContext bootstrapContext;
private @Nullable BootstrapContext bootstrapContext;
private ConfigurableApplicationContext applicationContext;
private @Nullable ConfigurableApplicationContext applicationContext;
@Override
public void onApplicationEvent(BootstrapContextClosedEvent event) {
@@ -19,8 +19,10 @@ package org.springframework.boot.builder;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.Properties;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -56,7 +58,7 @@ import static org.mockito.Mockito.spy;
*/
class SpringApplicationBuilderTests {
private ConfigurableApplicationContext context;
private @Nullable ConfigurableApplicationContext context;
@AfterEach
void close() {
@@ -64,7 +66,7 @@ class SpringApplicationBuilderTests {
SpringApplicationShutdownHookInstance.reset();
}
private void close(ApplicationContext context) {
private void close(@Nullable ApplicationContext context) {
if (context != null) {
if (context instanceof ConfigurableApplicationContext configurableContext) {
configurableContext.close();
@@ -103,9 +105,11 @@ class SpringApplicationBuilderTests {
@Test
void propertiesAsProperties() {
Properties properties = StringUtils.splitArrayElementsIntoProperties(new String[] { "bar=foo" }, "=");
assertThat(properties).isNotNull();
SpringApplicationBuilder application = new SpringApplicationBuilder().sources(ExampleConfig.class)
.contextFactory(ApplicationContextFactory.ofContextClass(StaticApplicationContext.class))
.properties(StringUtils.splitArrayElementsIntoProperties(new String[] { "bar=foo" }, "="));
.properties(properties);
this.context = application.run();
assertThat(this.context.getEnvironment().getProperty("bar")).isEqualTo("foo");
}
@@ -140,8 +144,9 @@ class SpringApplicationBuilderTests {
then(((SpyApplicationContext) this.context).getApplicationContext()).should()
.setParent(any(ApplicationContext.class));
assertThat(SpringApplicationShutdownHookInstance.get()).didNotRegisterApplicationContext(this.context);
assertThat(this.context.getParent().getBean(ApplicationArguments.class).getNonOptionArgs())
.contains("foo.bar=baz");
ApplicationContext parent = this.context.getParent();
assertThat(parent).isNotNull();
assertThat(parent.getBean(ApplicationArguments.class).getNonOptionArgs()).contains("foo.bar=baz");
assertThat(this.context.getBean(ApplicationArguments.class).getNonOptionArgs()).contains("foo.bar=baz");
}
@@ -154,7 +159,9 @@ class SpringApplicationBuilderTests {
then(((SpyApplicationContext) this.context).getApplicationContext()).should()
.setParent(any(ApplicationContext.class));
assertThat(SpringApplicationShutdownHookInstance.get()).didNotRegisterApplicationContext(this.context);
assertThat(this.context.getParent().getBean(ApplicationArguments.class).getNonOptionArgs()).contains("a=alpha");
ApplicationContext parent = this.context.getParent();
assertThat(parent).isNotNull();
assertThat(parent.getBean(ApplicationArguments.class).getNonOptionArgs()).contains("a=alpha");
assertThat(this.context.getBean(ApplicationArguments.class).getNonOptionArgs()).contains("b=bravo");
}
@@ -188,7 +195,9 @@ class SpringApplicationBuilderTests {
application.resourceLoader(new DefaultResourceLoader(classLoader));
application.parent(ExampleConfig.class);
this.context = application.run();
assertThat(((SpyApplicationContext) this.context).getResourceLoader().getClassLoader()).isEqualTo(classLoader);
ResourceLoader resourceLoader = ((SpyApplicationContext) this.context).getResourceLoader();
assertThat(resourceLoader).isNotNull();
assertThat(resourceLoader.getClassLoader()).isEqualTo(classLoader);
}
@Test
@@ -212,8 +221,10 @@ class SpringApplicationBuilderTests {
this.context = application.run();
assertThat(this.context.getEnvironment().acceptsProfiles(Profiles.of("node"))).isTrue();
assertThat(this.context.getEnvironment().getProperty("transport")).isEqualTo("redis");
assertThat(this.context.getParent().getEnvironment().acceptsProfiles(Profiles.of("node"))).isTrue();
assertThat(this.context.getParent().getEnvironment().getProperty("transport")).isEqualTo("redis");
ApplicationContext parent = this.context.getParent();
assertThat(parent).isNotNull();
assertThat(parent.getEnvironment().acceptsProfiles(Profiles.of("node"))).isTrue();
assertThat(parent.getEnvironment().getProperty("transport")).isEqualTo("redis");
// only defined in node profile
assertThat(this.context.getEnvironment().getProperty("bar")).isEqualTo("spam");
}
@@ -227,7 +238,9 @@ class SpringApplicationBuilderTests {
.web(WebApplicationType.NONE);
this.context = application.run();
assertThat(this.context.getEnvironment().acceptsProfiles(Profiles.of("node", "admin"))).isTrue();
assertThat(this.context.getParent().getEnvironment().acceptsProfiles(Profiles.of("admin"))).isFalse();
ApplicationContext parent = this.context.getParent();
assertThat(parent).isNotNull();
assertThat(parent.getEnvironment().acceptsProfiles(Profiles.of("admin"))).isFalse();
}
@Test
@@ -240,8 +253,10 @@ class SpringApplicationBuilderTests {
shared.profiles("parent");
this.context = application.run();
assertThat(this.context.getEnvironment().acceptsProfiles(Profiles.of("node", "admin"))).isTrue();
assertThat(this.context.getParent().getEnvironment().acceptsProfiles(Profiles.of("node", "parent"))).isTrue();
assertThat(this.context.getParent().getEnvironment().acceptsProfiles(Profiles.of("admin"))).isFalse();
ApplicationContext parent = this.context.getParent();
assertThat(parent).isNotNull();
assertThat(parent.getEnvironment().acceptsProfiles(Profiles.of("node", "parent"))).isTrue();
assertThat(parent.getEnvironment().acceptsProfiles(Profiles.of("admin"))).isFalse();
}
@Test
@@ -257,7 +272,9 @@ class SpringApplicationBuilderTests {
assertThat(this.context.getEnvironment().acceptsProfiles(Profiles.of("node", "admin"))).isTrue();
// Now they share an Environment explicitly so there's no way to keep the profiles
// separate
assertThat(this.context.getParent().getEnvironment().acceptsProfiles(Profiles.of("admin"))).isTrue();
ApplicationContext parent = this.context.getParent();
assertThat(parent).isNotNull();
assertThat(parent.getEnvironment().acceptsProfiles(Profiles.of("admin"))).isTrue();
}
@Test
@@ -330,7 +347,8 @@ class SpringApplicationBuilderTests {
SpringApplicationBuilder applicationBuilder = new SpringApplicationBuilder(resourceLoader,
ExampleConfig.class) {
@Override
protected SpringApplication createSpringApplication(ResourceLoader resourceLoader, Class<?>... sources) {
protected SpringApplication createSpringApplication(@Nullable ResourceLoader resourceLoader,
Class<?>... sources) {
return new CustomSpringApplication(resourceLoader, sources);
}
};
@@ -351,9 +369,9 @@ class SpringApplicationBuilderTests {
static class CustomSpringApplication extends SpringApplication {
private final ResourceLoader resourceLoader;
private final @Nullable ResourceLoader resourceLoader;
CustomSpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
CustomSpringApplication(@Nullable ResourceLoader resourceLoader, Class<?>... primarySources) {
super(resourceLoader, primarySources);
this.resourceLoader = resourceLoader;
}
@@ -364,10 +382,10 @@ class SpringApplicationBuilderTests {
private final ConfigurableApplicationContext applicationContext = spy(new AnnotationConfigApplicationContext());
private ResourceLoader resourceLoader;
private @Nullable ResourceLoader resourceLoader;
@Override
public void setParent(ApplicationContext parent) {
public void setParent(@Nullable ApplicationContext parent) {
this.applicationContext.setParent(parent);
}
@@ -381,7 +399,7 @@ class SpringApplicationBuilderTests {
this.resourceLoader = resourceLoader;
}
ResourceLoader getResourceLoader() {
@Nullable ResourceLoader getResourceLoader() {
return this.resourceLoader;
}
@@ -392,7 +410,7 @@ class SpringApplicationBuilderTests {
}
@Override
public ApplicationContext getParent() {
public @Nullable ApplicationContext getParent() {
return this.applicationContext.getParent();
}
@@ -58,6 +58,7 @@ class CloudPlatformTests {
void getActiveWhenHasVcapApplicationShouldReturnCloudFoundry() {
Environment environment = new MockEnvironment().withProperty("VCAP_APPLICATION", "---");
CloudPlatform platform = CloudPlatform.getActive(environment);
assertThat(platform).isNotNull();
assertThat(platform).isEqualTo(CloudPlatform.CLOUD_FOUNDRY);
assertThat(platform.isActive(environment)).isTrue();
}
@@ -66,6 +67,7 @@ class CloudPlatformTests {
void getActiveWhenHasVcapServicesShouldReturnCloudFoundry() {
Environment environment = new MockEnvironment().withProperty("VCAP_SERVICES", "---");
CloudPlatform platform = CloudPlatform.getActive(environment);
assertThat(platform).isNotNull();
assertThat(platform).isEqualTo(CloudPlatform.CLOUD_FOUNDRY);
assertThat(platform.isActive(environment)).isTrue();
}
@@ -74,6 +76,7 @@ class CloudPlatformTests {
void getActiveWhenHasDynoShouldReturnHeroku() {
Environment environment = new MockEnvironment().withProperty("DYNO", "---");
CloudPlatform platform = CloudPlatform.getActive(environment);
assertThat(platform).isNotNull();
assertThat(platform).isEqualTo(CloudPlatform.HEROKU);
assertThat(platform.isActive(environment)).isTrue();
}
@@ -82,6 +85,7 @@ class CloudPlatformTests {
void getActiveWhenHasHcLandscapeShouldReturnSap() {
Environment environment = new MockEnvironment().withProperty("HC_LANDSCAPE", "---");
CloudPlatform platform = CloudPlatform.getActive(environment);
assertThat(platform).isNotNull();
assertThat(platform).isEqualTo(CloudPlatform.SAP);
assertThat(platform.isActive(environment)).isTrue();
}
@@ -90,6 +94,7 @@ class CloudPlatformTests {
void getActiveWhenHasNomadAllocIdShouldReturnNomad() {
Environment environment = new MockEnvironment().withProperty("NOMAD_ALLOC_ID", "---");
CloudPlatform platform = CloudPlatform.getActive(environment);
assertThat(platform).isNotNull();
assertThat(platform).isEqualTo(CloudPlatform.NOMAD);
assertThat(platform.isActive(environment)).isTrue();
}
@@ -101,6 +106,7 @@ class CloudPlatformTests {
envVars.put("KUBERNETES_SERVICE_PORT", "8080");
Environment environment = getEnvironmentWithEnvVariables(envVars);
CloudPlatform platform = CloudPlatform.getActive(environment);
assertThat(platform).isNotNull();
assertThat(platform).isEqualTo(CloudPlatform.KUBERNETES);
assertThat(platform.isActive(environment)).isTrue();
}
@@ -128,6 +134,7 @@ class CloudPlatformTests {
envVars.put("EXAMPLE_SERVICE_PORT", "8080");
Environment environment = getEnvironmentWithEnvVariables(envVars);
CloudPlatform platform = CloudPlatform.getActive(environment);
assertThat(platform).isNotNull();
assertThat(platform).isEqualTo(CloudPlatform.KUBERNETES);
assertThat(platform.isActive(environment)).isTrue();
}
@@ -149,6 +156,7 @@ class CloudPlatformTests {
envVars.put("WEBSITE_SKU", "1234");
Environment environment = getEnvironmentWithEnvVariables(envVars);
CloudPlatform platform = CloudPlatform.getActive(environment);
assertThat(platform).isNotNull();
assertThat(platform).isEqualTo(CloudPlatform.AZURE_APP_SERVICE);
assertThat(platform.isActive(environment)).isTrue();
}
@@ -57,6 +57,7 @@ class ApplicationPidFileWriterTests {
new String[] {}, mock(ConfigurableApplicationContext.class));
@TempDir
@SuppressWarnings("NullAway.Init")
File tempDir;
@BeforeEach
@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -87,7 +88,8 @@ class ContextIdApplicationContextInitializerTests {
assertThat(createContext(parent).getId()).isEqualTo("application");
}
private ConfigurableApplicationContext createContext(ConfigurableApplicationContext parent, String... properties) {
private ConfigurableApplicationContext createContext(@Nullable ConfigurableApplicationContext parent,
String... properties) {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context, properties);
if (parent != null) {
@@ -16,6 +16,7 @@
package org.springframework.boot.context;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -39,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*/
class TypeExcludeFilterTests {
private AnnotationConfigApplicationContext context;
private @Nullable AnnotationConfigApplicationContext context;
@AfterEach
void cleanUp() {
@@ -56,8 +57,10 @@ class TypeExcludeFilterTests {
this.context.register(Config.class);
this.context.refresh();
assertThat(this.context.getBean(ExampleComponent.class)).isNotNull();
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.context.getBean(ExampleFilteredComponent.class));
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() -> {
assertThat(this.context).isNotNull();
this.context.getBean(ExampleFilteredComponent.class);
});
}
@Configuration(proxyBeanMethods = false)
@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.core.Ordered;
@@ -44,6 +45,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class ConfigurationsTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenClassesIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new TestConfigurations((Collection<Class<?>>) null))
.withMessageContaining("'classes' must not be null");
@@ -91,7 +93,7 @@ class ConfigurationsTests {
}
TestConfigurations(UnaryOperator<Collection<Class<?>>> sorter, Collection<Class<?>> classes,
Function<Class<?>, String> beanNameGenerator) {
@Nullable Function<Class<?>, String> beanNameGenerator) {
super(sorter, classes, beanNameGenerator);
}
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.origin.Origin;
@@ -120,7 +121,9 @@ class ConfigDataEnvironmentContributorPlaceholdersResolverTests {
private Consumer<InactiveConfigDataAccessException> propertyNameAndOriginOf(String propertyName, String origin) {
return (ex) -> {
assertThat(ex.getPropertyName()).isEqualTo(propertyName);
assertThat(((PropertySourceOrigin) (ex.getOrigin())).getPropertySource().getName()).isEqualTo(origin);
PropertySourceOrigin actualOrigin = (PropertySourceOrigin) (ex.getOrigin());
assertThat(actualOrigin).isNotNull();
assertThat(actualOrigin.getPropertySource().getName()).isEqualTo(origin);
};
}
@@ -135,7 +138,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolverTests {
}
@Override
public Origin getOrigin(String key) {
public @Nullable Origin getOrigin(String key) {
if (getSource().containsKey(key)) {
return new PropertySourceOrigin(this, key);
}
@@ -155,7 +158,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolverTests {
}
@Override
boolean isActive(ConfigDataActivationContext activationContext) {
boolean isActive(@Nullable ConfigDataActivationContext activationContext) {
return this.active;
}
@@ -23,6 +23,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.cloud.CloudPlatform;
@@ -30,7 +31,9 @@ import org.springframework.boot.context.config.ConfigData.Option;
import org.springframework.boot.context.config.ConfigData.PropertySourceOptions;
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.mock.env.MockPropertySource;
@@ -110,9 +113,11 @@ class ConfigDataEnvironmentContributorTests {
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(null, null,
false, configData, 0, this.conversionService, ConfigDataEnvironmentUpdateListener.NONE);
assertThat(contributor.getConfigurationPropertySource()
.getConfigurationProperty(ConfigurationPropertyName.of("spring"))
.getValue()).isEqualTo("boot");
ConfigurationPropertySource source = contributor.getConfigurationPropertySource();
assertThat(source).isNotNull();
ConfigurationProperty spring = source.getConfigurationProperty(ConfigurationPropertyName.of("spring"));
assertThat(spring).isNotNull();
assertThat(spring.getValue()).isEqualTo("boot");
}
@Test
@@ -379,8 +384,8 @@ class ConfigDataEnvironmentContributorTests {
new ConfigData(Collections.singleton(new MockPropertySource())), 0);
}
private ConfigDataEnvironmentContributor createBoundContributor(ConfigDataResource resource, ConfigData configData,
int propertySourceIndex) {
private ConfigDataEnvironmentContributor createBoundContributor(@Nullable ConfigDataResource resource,
ConfigData configData, int propertySourceIndex) {
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(TEST_LOCATION,
resource, false, configData, propertySourceIndex, this.conversionService,
ConfigDataEnvironmentUpdateListener.NONE);
@@ -394,7 +399,9 @@ class ConfigDataEnvironmentContributorTests {
}
private String getLocationName(ConfigDataEnvironmentContributor contributor) {
return contributor.getResource().toString();
ConfigDataResource resource = contributor.getResource();
assertThat(resource).isNotNull();
return resource.toString();
}
static class TestResource extends ConfigDataResource {
@@ -63,6 +63,7 @@ class ConfigDataEnvironmentPostProcessorImportCombinedWithProfileSpecificIntegra
private SpringApplication application;
@TempDir
@SuppressWarnings("NullAway.Init")
public File temp;
@BeforeEach
@@ -32,6 +32,7 @@ import java.util.Properties;
import java.util.UUID;
import org.assertj.core.api.Condition;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -84,6 +85,7 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
private SpringApplication application;
@TempDir
@SuppressWarnings("NullAway.Init")
public File temp;
@BeforeEach
@@ -814,7 +816,7 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
MapPropertySource propertySource = new MapPropertySource("defaultProperties", source) {
@Override
public Object getProperty(String name) {
public @Nullable Object getProperty(String name) {
if ("spring.config.name".equals(name)) {
return "gh17001";
}
@@ -1088,8 +1090,11 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
binder.bind("my.value", Bindable.of(String.class), bindHandler);
assertThat(properties).hasSize(1);
Origin origin = properties.get(0).getOrigin();
assertThat(origin).isNotNull();
assertThat(origin.toString()).contains("imported.properties");
assertThat(origin.getParent().toString()).contains("application.properties");
Origin parent = origin.getParent();
assertThat(parent).isNotNull();
assertThat(parent.toString()).contains("application.properties");
}
@Test
@@ -1315,7 +1320,7 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
static class Loader implements ConfigDataLoader<TestConfigDataResource> {
@Override
public ConfigData load(ConfigDataLoaderContext context, TestConfigDataResource resource)
public @Nullable ConfigData load(ConfigDataLoaderContext context, TestConfigDataResource resource)
throws IOException, ConfigDataResourceNotFoundException {
if (resource.isOptional()) {
return null;
@@ -19,6 +19,7 @@ package org.springframework.boot.context.config;
import java.util.Collections;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
@@ -51,13 +52,15 @@ class ConfigDataEnvironmentPostProcessorTests {
private final SpringApplication application = new SpringApplication();
private ConfigDataEnvironment configDataEnvironment;
private @Nullable ConfigDataEnvironment configDataEnvironment;
private ConfigDataEnvironmentPostProcessor postProcessor;
private @Nullable ConfigDataEnvironmentPostProcessor postProcessor;
@Test
void postProcessEnvironmentWhenNoLoaderCreatesDefaultLoaderInstance() {
setupMocksAndSpies();
assertThat(this.configDataEnvironment).isNotNull();
assertThat(this.postProcessor).isNotNull();
willReturn(this.configDataEnvironment).given(this.postProcessor).getConfigDataEnvironment(any(), any(), any());
this.postProcessor.postProcessEnvironment(this.environment, this.application);
then(this.postProcessor).should()
@@ -70,6 +73,8 @@ class ConfigDataEnvironmentPostProcessorTests {
@Test
void postProcessEnvironmentWhenCustomLoaderUsesSpecifiedLoaderInstance() {
setupMocksAndSpies();
assertThat(this.configDataEnvironment).isNotNull();
assertThat(this.postProcessor).isNotNull();
ResourceLoader resourceLoader = mock(ResourceLoader.class);
this.application.setResourceLoader(resourceLoader);
willReturn(this.configDataEnvironment).given(this.postProcessor).getConfigDataEnvironment(any(), any(), any());
@@ -83,6 +88,8 @@ class ConfigDataEnvironmentPostProcessorTests {
@Test
void postProcessEnvironmentWhenHasAdditionalProfilesOnSpringApplicationUsesAdditionalProfiles() {
setupMocksAndSpies();
assertThat(this.configDataEnvironment).isNotNull();
assertThat(this.postProcessor).isNotNull();
this.application.setAdditionalProfiles("dev");
willReturn(this.configDataEnvironment).given(this.postProcessor).getConfigDataEnvironment(any(), any(), any());
this.postProcessor.postProcessEnvironment(this.environment, this.application);
@@ -95,6 +102,8 @@ class ConfigDataEnvironmentPostProcessorTests {
@Test
void postProcessEnvironmentWhenNoActiveProfiles() {
setupMocksAndSpies();
assertThat(this.configDataEnvironment).isNotNull();
assertThat(this.postProcessor).isNotNull();
willReturn(this.configDataEnvironment).given(this.postProcessor).getConfigDataEnvironment(any(), any(), any());
this.postProcessor.postProcessEnvironment(this.environment, this.application);
then(this.postProcessor).should().getConfigDataEnvironment(any(), any(ResourceLoader.class), any());
@@ -113,7 +122,9 @@ class ConfigDataEnvironmentPostProcessorTests {
assertThat(this.environment.getPropertySources()).hasSizeGreaterThan(before);
assertThat(this.environment.getActiveProfiles()).containsExactly("dev");
assertThat(listener.getAddedPropertySources()).isNotEmpty();
assertThat(listener.getProfiles().getActive()).containsExactly("dev");
Profiles profiles = listener.getProfiles();
assertThat(profiles).isNotNull();
assertThat(profiles.getActive()).containsExactly("dev");
assertThat(listener.getAddedPropertySources().stream().anyMatch((added) -> hasDevProfile(added.getResource())))
.isTrue();
}
@@ -147,7 +158,7 @@ class ConfigDataEnvironmentPostProcessorTests {
this.postProcessor = spy(new ConfigDataEnvironmentPostProcessor(Supplier::get, new DefaultBootstrapContext()));
}
private boolean hasDevProfile(ConfigDataResource resource) {
private boolean hasDevProfile(@Nullable ConfigDataResource resource) {
return (resource instanceof StandardConfigDataResource standardResource)
&& "dev".equals(standardResource.getProfile());
}
@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.function.Supplier;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.params.ParameterizedTest;
@@ -81,8 +82,9 @@ class ConfigDataEnvironmentTests {
this.environment.setProperty("spring", "boot");
TestConfigDataEnvironment configDataEnvironment = new TestConfigDataEnvironment(this.logFactory,
this.bootstrapContext, this.environment, this.resourceLoader, this.additionalProfiles, null);
assertThat(configDataEnvironment.getConfigDataLocationResolversBinder().bind("spring", String.class).get())
.isEqualTo("boot");
Binder binder = configDataEnvironment.getConfigDataLocationResolversBinder();
assertThat(binder).isNotNull();
assertThat(binder.bind("spring", String.class).get()).isEqualTo("boot");
}
@Test
@@ -335,8 +337,9 @@ class ConfigDataEnvironmentTests {
AddedPropertySource addedPropertySource = listener.getAddedPropertySources().get(0);
assertThat(addedPropertySource.getPropertySource().getProperty("spring")).isEqualTo("boot");
assertThat(addedPropertySource.getLocation()).hasToString("classpath:custom/config.properties");
assertThat(addedPropertySource.getResource().toString()).contains("class path resource")
.contains("custom/config.properties");
ConfigDataResource resource = addedPropertySource.getResource();
assertThat(resource).isNotNull();
assertThat(resource.toString()).contains("class path resource").contains("custom/config.properties");
}
@Test
@@ -346,7 +349,9 @@ class ConfigDataEnvironmentTests {
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles, listener);
configDataEnvironment.processAndApply();
assertThat(listener.getProfiles().getActive()).containsExactly("one", "two", "three");
Profiles profiles = listener.getProfiles();
assertThat(profiles).isNotNull();
assertThat(profiles.getActive()).containsExactly("one", "two", "three");
}
@Test
@@ -384,11 +389,12 @@ class ConfigDataEnvironmentTests {
static class TestConfigDataEnvironment extends ConfigDataEnvironment {
private Binder configDataLocationResolversBinder;
private @Nullable Binder configDataLocationResolversBinder;
TestConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment, ResourceLoader resourceLoader,
Collection<String> additionalProfiles, ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
Collection<String> additionalProfiles,
@Nullable ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
super(logFactory, bootstrapContext, environment, resourceLoader, additionalProfiles,
environmentUpdateListener);
}
@@ -400,7 +406,7 @@ class ConfigDataEnvironmentTests {
return super.createConfigDataLocationResolvers(logFactory, bootstrapContext, binder, resourceLoader);
}
Binder getConfigDataLocationResolversBinder() {
@Nullable Binder getConfigDataLocationResolversBinder() {
return this.configDataLocationResolversBinder;
}
@@ -409,7 +415,7 @@ class ConfigDataEnvironmentTests {
static class SeparateClassLoaderConfigDataLoader implements ConfigDataLoader<ConfigDataResource> {
@Override
public ConfigData load(ConfigDataLoaderContext context, ConfigDataResource resource)
public @Nullable ConfigData load(ConfigDataLoaderContext context, ConfigDataResource resource)
throws IOException, ConfigDataResourceNotFoundException {
return null;
}
@@ -47,24 +47,31 @@ class ConfigDataImporterTests {
private final DeferredLogFactory logFactory = Supplier::get;
@Mock
@SuppressWarnings("NullAway.Init")
private ConfigDataLocationResolvers resolvers;
@Mock
@SuppressWarnings("NullAway.Init")
private ConfigDataLoaders loaders;
@Mock
@SuppressWarnings("NullAway.Init")
private Binder binder;
@Mock
@SuppressWarnings("NullAway.Init")
private ConfigDataLocationResolverContext locationResolverContext;
@Mock
@SuppressWarnings("NullAway.Init")
private ConfigDataLoaderContext loaderContext;
@Mock
@SuppressWarnings("NullAway.Init")
private ConfigDataActivationContext activationContext;
@Mock
@SuppressWarnings("NullAway.Init")
private Profiles profiles;
@BeforeEach
@@ -18,6 +18,7 @@ package org.springframework.boot.context.config;
import java.io.IOException;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -43,7 +44,8 @@ class ConfigDataLoaderTests {
static class TestConfigDataLoader implements ConfigDataLoader<TestConfigDataResource> {
@Override
public ConfigData load(ConfigDataLoaderContext context, TestConfigDataResource resource) throws IOException {
public @Nullable ConfigData load(ConfigDataLoaderContext context, TestConfigDataResource resource)
throws IOException {
return null;
}
@@ -16,7 +16,6 @@
package org.springframework.boot.context.config;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
@@ -25,7 +24,6 @@ import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.boot.bootstrap.BootstrapContext;
import org.springframework.boot.bootstrap.BootstrapRegistry;
@@ -56,9 +54,6 @@ class ConfigDataLoadersTests {
private final ConfigDataLoaderContext context = mock(ConfigDataLoaderContext.class);
@TempDir
private File tempDir;
@Test
void createWhenLoaderHasDeferredLogFactoryParameterInjectsDeferredLogFactory() {
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
@@ -103,6 +98,7 @@ class ConfigDataLoadersTests {
springFactoriesLoader);
TestConfigDataResource location = new TestConfigDataResource("test");
ConfigData loaded = loaders.load(this.context, location);
assertThat(loaded).isNotNull();
assertThat(getLoader(loaded)).isInstanceOf(TestConfigDataLoader.class);
}
@@ -136,11 +132,14 @@ class ConfigDataLoadersTests {
springFactoriesLoader);
TestConfigDataResource location = new TestConfigDataResource("test");
ConfigData loaded = loaders.load(this.context, location);
assertThat(loaded).isNotNull();
assertThat(getLoader(loaded)).isInstanceOf(SpecificConfigDataLoader.class);
}
private ConfigDataLoader<?> getLoader(ConfigData loaded) {
return (ConfigDataLoader<?>) loaded.getPropertySources().get(0).getProperty("loader");
ConfigDataLoader<?> result = (ConfigDataLoader<?>) loaded.getPropertySources().get(0).getProperty("loader");
assertThat(result).isNotNull();
return result;
}
private static ConfigData createConfigData(ConfigDataLoader<?> loader, ConfigDataResource resource) {
@@ -39,6 +39,7 @@ class ConfigDataLocationNotFoundExceptionTests {
this.location);
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenLocationIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ConfigDataLocationNotFoundException(null))
.withMessage("'location' must not be null");
@@ -16,10 +16,14 @@
package org.springframework.boot.context.config;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -37,7 +41,10 @@ class ConfigDataLocationResolverTests {
@Test
void resolveProfileSpecificReturnsEmptyList() {
assertThat(this.resolver.resolveProfileSpecific(this.context, null, null)).isEmpty();
ConfigDataLocation location = ConfigDataLocation.of("location");
MockEnvironment environment = new MockEnvironment();
Profiles profiles = new Profiles(environment, Binder.get(environment), null);
assertThat(this.resolver.resolveProfileSpecific(this.context, location, profiles)).isEmpty();
}
static class TestConfigDataLocationResolver implements ConfigDataLocationResolver<ConfigDataResource> {
@@ -50,7 +57,7 @@ class ConfigDataLocationResolverTests {
@Override
public List<ConfigDataResource> resolve(ConfigDataLocationResolverContext context,
ConfigDataLocation location) {
return null;
return Collections.emptyList();
}
}
@@ -56,15 +56,19 @@ class ConfigDataLocationResolversTests {
private final DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
@Mock
@SuppressWarnings("NullAway.Init")
private Binder binder;
@Mock
@SuppressWarnings("NullAway.Init")
private ConfigDataLocationResolverContext context;
@Mock
@SuppressWarnings("NullAway.Init")
private Profiles profiles;
@TempDir
@SuppressWarnings("NullAway.Init")
private File tempDir;
@Test
@@ -20,6 +20,7 @@ import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.ResourcePatternHint;
@@ -60,7 +61,7 @@ class ConfigDataLocationRuntimeHintsTests {
RuntimeHints hints = new RuntimeHints();
new TestConfigDataLocationRuntimeHints() {
@Override
protected List<String> getFileNames(ClassLoader classLoader) {
protected List<String> getFileNames(@Nullable ClassLoader classLoader) {
return List.of("test");
}
@@ -77,7 +78,7 @@ class ConfigDataLocationRuntimeHintsTests {
RuntimeHints hints = new RuntimeHints();
new TestConfigDataLocationRuntimeHints() {
@Override
protected List<String> getLocations(ClassLoader classLoader) {
protected List<String> getLocations(@Nullable ClassLoader classLoader) {
return List.of("config/");
}
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
@@ -93,7 +94,7 @@ class ConfigDataLocationRuntimeHintsTests {
RuntimeHints hints = new RuntimeHints();
new ConfigDataLocationRuntimeHints() {
@Override
protected List<String> getExtensions(ClassLoader classLoader) {
protected List<String> getExtensions(@Nullable ClassLoader classLoader) {
return List.of(".conf");
}
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
@@ -106,7 +107,7 @@ class ConfigDataLocationRuntimeHintsTests {
RuntimeHints hints = new RuntimeHints();
new ConfigDataLocationRuntimeHints() {
@Override
protected List<String> getLocations(ClassLoader classLoader) {
protected List<String> getLocations(@Nullable ClassLoader classLoader) {
return List.of(UUID.randomUUID().toString());
}
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
@@ -138,7 +139,7 @@ class ConfigDataLocationRuntimeHintsTests {
}
@Override
protected SpringFactoriesLoader getSpringFactoriesLoader(ClassLoader classLoader) {
protected SpringFactoriesLoader getSpringFactoriesLoader(@Nullable ClassLoader classLoader) {
return this.springFactoriesLoader;
}
@@ -38,6 +38,7 @@ class ConfigDataNotFoundFailureAnalyzerTests {
ConfigDataLocation location = ConfigDataLocation.of("test");
ConfigDataLocationNotFoundException exception = new ConfigDataLocationNotFoundException(location);
FailureAnalysis result = this.analyzer.analyze(exception);
assertThat(result).isNotNull();
assertThat(result.getDescription()).isEqualTo("Config data location 'test' does not exist");
assertThat(result.getAction())
.isEqualTo("Check that the value 'test' is correct, or prefix it with 'optional:'");
@@ -48,6 +49,7 @@ class ConfigDataNotFoundFailureAnalyzerTests {
ConfigDataLocation location = ConfigDataLocation.of("optional:test");
ConfigDataLocationNotFoundException exception = new ConfigDataLocationNotFoundException(location);
FailureAnalysis result = this.analyzer.analyze(exception);
assertThat(result).isNotNull();
assertThat(result.getDescription()).isEqualTo("Config data location 'optional:test' does not exist");
assertThat(result.getAction()).isEqualTo("Check that the value 'optional:test' is correct");
}
@@ -57,6 +59,7 @@ class ConfigDataNotFoundFailureAnalyzerTests {
ConfigDataLocation location = ConfigDataLocation.of("test").withOrigin(new TestOrigin("origin"));
ConfigDataLocationNotFoundException exception = new ConfigDataLocationNotFoundException(location);
FailureAnalysis result = this.analyzer.analyze(exception);
assertThat(result).isNotNull();
assertThat(result.getDescription()).isEqualTo("Config data location 'test' does not exist");
assertThat(result.getAction())
.isEqualTo("Check that the value 'test' at origin is correct, or prefix it with 'optional:'");
@@ -67,6 +70,7 @@ class ConfigDataNotFoundFailureAnalyzerTests {
ConfigDataResource resource = new TestConfigDataResource("myresource");
ConfigDataResourceNotFoundException exception = new ConfigDataResourceNotFoundException(resource);
FailureAnalysis result = this.analyzer.analyze(exception);
assertThat(result).isNotNull();
assertThat(result.getDescription()).isEqualTo("Config data resource 'myresource' does not exist");
assertThat(result.getAction()).isEqualTo("Check that the value is correct");
}
@@ -78,6 +82,7 @@ class ConfigDataNotFoundFailureAnalyzerTests {
ConfigDataResourceNotFoundException exception = new ConfigDataResourceNotFoundException(resource)
.withLocation(location);
FailureAnalysis result = this.analyzer.analyze(exception);
assertThat(result).isNotNull();
assertThat(result.getDescription())
.isEqualTo("Config data resource 'myresource' via location 'test' does not exist");
assertThat(result.getAction())
@@ -20,6 +20,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.cloud.CloudPlatform;
@@ -39,9 +40,9 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
class ConfigDataPropertiesTests {
private static final CloudPlatform NULL_CLOUD_PLATFORM = null;
private static final @Nullable CloudPlatform NULL_CLOUD_PLATFORM = null;
private static final Profiles NULL_PROFILES = null;
private static final @Nullable Profiles NULL_PROFILES = null;
private static final List<ConfigDataLocation> NO_IMPORTS = Collections.emptyList();
@@ -173,6 +174,7 @@ class ConfigDataPropertiesTests {
ConfigDataProperties properties = ConfigDataProperties.get(binder);
ConfigDataActivationContext context = new ConfigDataActivationContext(CloudPlatform.KUBERNETES,
createTestProfiles());
assertThat(properties).isNotNull();
assertThat(properties.isActive(context)).isTrue();
}
@@ -185,6 +187,7 @@ class ConfigDataPropertiesTests {
ConfigDataProperties properties = ConfigDataProperties.get(binder);
ConfigDataActivationContext context = new ConfigDataActivationContext(CloudPlatform.KUBERNETES,
createTestProfiles());
assertThat(properties).isNotNull();
assertThat(properties.isActive(context)).isFalse();
}
@@ -197,6 +200,7 @@ class ConfigDataPropertiesTests {
ConfigDataProperties properties = ConfigDataProperties.get(binder);
ConfigDataActivationContext context = new ConfigDataActivationContext(CloudPlatform.KUBERNETES,
createTestProfiles());
assertThat(properties).isNotNull();
assertThat(properties.isActive(context)).isFalse();
}
@@ -208,6 +212,7 @@ class ConfigDataPropertiesTests {
ConfigDataProperties properties = ConfigDataProperties.get(binder);
ConfigDataActivationContext context = new ConfigDataActivationContext(NULL_CLOUD_PLATFORM,
createTestProfiles());
assertThat(properties).isNotNull();
assertThat(properties.isActive(context)).isTrue();
}
@@ -217,6 +222,7 @@ class ConfigDataPropertiesTests {
source.put("spring.config.import", "one,two,three");
Binder binder = new Binder(source);
ConfigDataProperties properties = ConfigDataProperties.get(binder);
assertThat(properties).isNotNull();
assertThat(properties.getImports().get(1).getOrigin())
.hasToString("\"spring.config.import\" from property source \"source\"");
}
@@ -229,6 +235,7 @@ class ConfigDataPropertiesTests {
source.put("spring.config.import[2]", "three");
Binder binder = new Binder(source);
ConfigDataProperties properties = ConfigDataProperties.get(binder);
assertThat(properties).isNotNull();
assertThat(properties.getImports().get(1).getOrigin())
.hasToString("\"spring.config.import[1]\" from property source \"source\"");
}
@@ -49,6 +49,7 @@ class ConfigDataResourceNotFoundExceptionTests {
private File missing;
@TempDir
@SuppressWarnings("NullAway.Init")
File temp;
@BeforeEach
@@ -61,6 +62,7 @@ class ConfigDataResourceNotFoundExceptionTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenResourceIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ConfigDataResourceNotFoundException(null))
.withMessage("'resource' must not be null");
@@ -42,12 +42,14 @@ import static org.mockito.Mockito.mock;
class ConfigDataTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenPropertySourcesIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ConfigData(null))
.withMessage("'propertySources' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenOptionsIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ConfigData(Collections.emptyList(), (Option[]) null))
.withMessage("'options' must not be null");
@@ -127,8 +129,9 @@ class ConfigDataTests {
@Test
void propertySourceOptionsAlwaysReturnsSameOptionsEachTime() {
PropertySourceOptions options = PropertySourceOptions.always(Option.IGNORE_IMPORTS, Option.IGNORE_PROFILES);
assertThat(options.get(mock(PropertySource.class)).asSet()).containsExactly(Option.IGNORE_IMPORTS,
Option.IGNORE_PROFILES);
Options propertySourceOptions = options.get(mock(PropertySource.class));
assertThat(propertySourceOptions).isNotNull();
assertThat(propertySourceOptions.asSet()).containsExactly(Option.IGNORE_IMPORTS, Option.IGNORE_PROFILES);
}
}
@@ -44,6 +44,7 @@ class ConfigTreeConfigDataLoaderTests {
private final ConfigDataLoaderContext loaderContext = mock(ConfigDataLoaderContext.class);
@TempDir
@SuppressWarnings("NullAway.Init")
Path directory;
@Test
@@ -42,6 +42,7 @@ class ConfigTreeConfigDataLocationResolverTests {
private final ConfigDataLocationResolverContext context = mock(ConfigDataLocationResolverContext.class);
@TempDir
@SuppressWarnings("NullAway.Init")
File temp;
@Test
@@ -33,12 +33,14 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class ConfigTreeConfigDataResourceTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void constructorWhenPathStringIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ConfigTreeConfigDataResource((String) null))
.withMessage("'path' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void constructorWhenPathIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ConfigTreeConfigDataResource((Path) null))
.withMessage("'path' must not be null");
@@ -40,6 +40,7 @@ class LocationResourceLoaderTests {
private final LocationResourceLoader loader = new LocationResourceLoader(new DefaultResourceLoader());
@TempDir
@SuppressWarnings("NullAway.Init")
File temp;
@Test
@@ -258,7 +258,7 @@ class StandardConfigDataLocationResolverTests {
assertThat(locations).hasSize(1);
StandardConfigDataResource resolved = locations.get(0);
assertThat(resolved.getResource().getFilename()).endsWith("application-props-no-extension");
ConfigData loaded = new StandardConfigDataLoader().load(null, resolved);
ConfigData loaded = new StandardConfigDataLoader().load(mock(ConfigDataLoaderContext.class), resolved);
PropertySource<?> propertySource = loaded.getPropertySources().get(0);
assertThat(propertySource.getProperty("withnoextension")).isEqualTo("test");
}
@@ -46,12 +46,14 @@ class StandardConfigDataResourceTests {
private final Resource resource = mock(Resource.class);
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenReferenceIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new StandardConfigDataResource(null, this.resource))
.withMessage("'reference' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenResourceIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new StandardConfigDataResource(this.reference, null))
.withMessage("'resource' must not be null");
@@ -78,6 +80,7 @@ class StandardConfigDataResourceTests {
@WithResource(name = "test.resource", content = "test")
void equalsAndHashCodeWhenSameUnderlyingResource(@ResourcePath("test.resource") Path path) throws IOException {
Path directory = path.getParent();
assertThat(directory).isNotNull();
URLClassLoader classLoader = new URLClassLoader(new URL[] { directory.toUri().toURL() },
getClass().getClassLoader());
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
@@ -21,12 +21,16 @@ import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.bootstrap.BootstrapContextClosedEvent;
import org.springframework.boot.bootstrap.BootstrapRegistry.InstanceSupplier;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.MapPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test classes used with
* {@link ConfigDataEnvironmentPostProcessorBootstrapContextIntegrationTests} to show how
@@ -50,6 +54,7 @@ class TestConfigDataBootstrap {
context.getBootstrapContext()
.registerIfAbsent(ResolverHelper.class, InstanceSupplier.from(() -> new ResolverHelper(location)));
ResolverHelper helper = context.getBootstrapContext().get(ResolverHelper.class);
assertThat(helper).isNotNull();
return Collections.singletonList(new Resource(helper));
}
@@ -63,6 +68,7 @@ class TestConfigDataBootstrap {
.registerIfAbsent(LoaderHelper.class,
(bootstrapContext) -> new LoaderHelper(location, () -> bootstrapContext.get(Binder.class)));
LoaderHelper helper = context.getBootstrapContext().get(LoaderHelper.class);
assertThat(helper).isNotNull();
context.getBootstrapContext().addCloseListener(helper);
return new ConfigData(
Collections.singleton(new MapPropertySource("loaded", Collections.singletonMap("test", "test"))));
@@ -118,11 +124,11 @@ class TestConfigDataBootstrap {
return this.location;
}
String getBound() {
@Nullable String getBound() {
return this.binder.get().bind("myprop", String.class).orElse(null);
}
String getProfileBound() {
@Nullable String getProfileBound() {
return this.binder.get().bind("myprofileprop", String.class).orElse(null);
}
@@ -20,17 +20,19 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.core.env.PropertySource;
class TestConfigDataEnvironmentUpdateListener implements ConfigDataEnvironmentUpdateListener {
private final List<AddedPropertySource> addedPropertySources = new ArrayList<>();
private Profiles profiles;
private @Nullable Profiles profiles;
@Override
public void onPropertySourceAdded(PropertySource<?> propertySource, ConfigDataLocation location,
ConfigDataResource resource) {
public void onPropertySourceAdded(PropertySource<?> propertySource, @Nullable ConfigDataLocation location,
@Nullable ConfigDataResource resource) {
this.addedPropertySources.add(new AddedPropertySource(propertySource, location, resource));
}
@@ -43,7 +45,7 @@ class TestConfigDataEnvironmentUpdateListener implements ConfigDataEnvironmentUp
return Collections.unmodifiableList(this.addedPropertySources);
}
Profiles getProfiles() {
@Nullable Profiles getProfiles() {
return this.profiles;
}
@@ -51,12 +53,12 @@ class TestConfigDataEnvironmentUpdateListener implements ConfigDataEnvironmentUp
private final PropertySource<?> propertySource;
private final ConfigDataLocation location;
private final @Nullable ConfigDataLocation location;
private final ConfigDataResource resource;
private final @Nullable ConfigDataResource resource;
AddedPropertySource(PropertySource<?> propertySource, ConfigDataLocation location,
ConfigDataResource resource) {
AddedPropertySource(PropertySource<?> propertySource, @Nullable ConfigDataLocation location,
@Nullable ConfigDataResource resource) {
this.propertySource = propertySource;
this.location = location;
this.resource = resource;
@@ -66,11 +68,11 @@ class TestConfigDataEnvironmentUpdateListener implements ConfigDataEnvironmentUp
return this.propertySource;
}
ConfigDataLocation getLocation() {
@Nullable ConfigDataLocation getLocation() {
return this.location;
}
ConfigDataResource getResource() {
@Nullable ConfigDataResource getResource() {
return this.resource;
}
@@ -32,6 +32,7 @@ import org.springframework.context.ApplicationListener;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
@@ -45,6 +46,8 @@ import static org.mockito.Mockito.mock;
*/
class EventPublishingRunListenerTests {
private static final String[] NO_ARGS = new String[0];
@Test
void shouldPublishLifecycleEvents() {
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
@@ -52,11 +55,11 @@ class EventPublishingRunListenerTests {
TestApplicationListener applicationListener = new TestApplicationListener();
SpringApplication application = mock(SpringApplication.class);
given(application.getListeners()).willReturn(Collections.singleton(applicationListener));
EventPublishingRunListener publishingListener = new EventPublishingRunListener(application, null);
EventPublishingRunListener publishingListener = new EventPublishingRunListener(application, NO_ARGS);
applicationListener.assertReceivedNoEvents();
publishingListener.starting(bootstrapContext);
applicationListener.assertReceivedEvent(ApplicationStartingEvent.class);
publishingListener.environmentPrepared(bootstrapContext, null);
publishingListener.environmentPrepared(bootstrapContext, new MockEnvironment());
applicationListener.assertReceivedEvent(ApplicationEnvironmentPreparedEvent.class);
publishingListener.contextPrepared(context);
applicationListener.assertReceivedEvent(ApplicationContextInitializedEvent.class);
@@ -78,7 +81,7 @@ class EventPublishingRunListenerTests {
ApplicationListener<ApplicationStartingEvent> listener = (event) -> event.getSpringApplication()
.addListeners(lateAddedApplicationListener);
application.addListeners(listener);
EventPublishingRunListener runListener = new EventPublishingRunListener(application, null);
EventPublishingRunListener runListener = new EventPublishingRunListener(application, NO_ARGS);
runListener.starting(bootstrapContext);
runListener.environmentPrepared(bootstrapContext, environment);
lateAddedApplicationListener.assertReceivedEvent(ApplicationEnvironmentPreparedEvent.class);
@@ -18,6 +18,7 @@ package org.springframework.boot.context.logging;
import java.io.File;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
@@ -103,7 +104,7 @@ class LoggingApplicationListenerIntegrationTests {
private final LoggingSystem loggingSystem;
private final LogFile logFile;
private final @Nullable LogFile logFile;
SampleService(LoggingSystem loggingSystem, ObjectProvider<LogFile> logFile) {
this.loggingSystem = loggingSystem;
@@ -40,6 +40,7 @@ import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -59,6 +60,7 @@ import org.springframework.boot.logging.AbstractLoggingSystem;
import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggerConfiguration;
import org.springframework.boot.logging.LoggerGroup;
import org.springframework.boot.logging.LoggerGroups;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.LoggingSystem;
@@ -118,6 +120,7 @@ class LoggingApplicationListenerTests {
private final GenericApplicationContext context = new GenericApplicationContext();
@TempDir
@SuppressWarnings("NullAway.Init")
public Path tempDir;
private File logFile;
@@ -149,14 +152,12 @@ class LoggingApplicationListenerTests {
System.clearProperty(LoggingSystem.class.getName());
System.clearProperty(LoggingSystem.SYSTEM_PROPERTY);
System.getProperties().keySet().retainAll(this.systemPropertyNames);
if (this.context != null) {
this.context.close();
}
this.context.close();
}
@Test
void baseConfigLocation() {
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.info("Hello world", new RuntimeException("Expected"));
assertThat(this.output).contains("Hello world");
assertThat(this.output).doesNotContain("???");
@@ -168,7 +169,7 @@ class LoggingApplicationListenerTests {
@WithNonDefaultXmlResource
void overrideConfigLocation() {
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.info("Hello world");
assertThat(this.output).contains("Hello world").doesNotContain("???").startsWith("null ").endsWith("BOOTBOOT");
}
@@ -179,7 +180,7 @@ class LoggingApplicationListenerTests {
multicastEvent(this.listener,
new ApplicationStartingEvent(this.bootstrapContext, new SpringApplication(), NO_ARGS));
assertThatIllegalStateException()
.isThrownBy(() -> this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader()));
.isThrownBy(() -> this.listener.initialize(this.context.getEnvironment(), getClassLoader()));
assertThat(output).contains("Deliberately broken");
}
@@ -187,7 +188,7 @@ class LoggingApplicationListenerTests {
@WithNonDefaultXmlResource
void trailingWhitespaceInLoggingConfigShouldBeTrimmed() {
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml ");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.info("Hello world");
assertThat(this.output).contains("Hello world").doesNotContain("???").startsWith("null ").endsWith("BOOTBOOT");
}
@@ -196,7 +197,7 @@ class LoggingApplicationListenerTests {
void overrideConfigDoesNotExist() {
addPropertiesToEnvironment(this.context, "logging.config=doesnotexist.xml");
assertThatIllegalStateException()
.isThrownBy(() -> this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader()));
.isThrownBy(() -> this.listener.initialize(this.context.getEnvironment(), getClassLoader()));
assertThat(this.output)
.contains("Logging system failed to initialize using configuration from 'doesnotexist.xml'")
.doesNotContain("JoranException");
@@ -206,7 +207,7 @@ class LoggingApplicationListenerTests {
void azureDefaultLoggingConfigDoesNotCauseAFailure() {
addPropertiesToEnvironment(this.context,
"logging.config=-Djava.util.logging.config.file=\"d:\\home\\site\\wwwroot\\bin\\apache-tomcat-7.0.52\\conf\\logging.properties\"");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.info("Hello world");
assertThat(this.output).contains("Hello world").doesNotContain("???");
assertThat(new File(this.tempDir.toFile(), "/spring.log")).doesNotExist();
@@ -215,7 +216,7 @@ class LoggingApplicationListenerTests {
@Test
void tomcatNopLoggingConfigDoesNotCauseAFailure() {
addPropertiesToEnvironment(this.context, "LOGGING_CONFIG=-Dnop");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.info("Hello world");
assertThat(this.output).contains("Hello world").doesNotContain("???");
assertThat(new File(this.tempDir.toFile(), "/spring.log")).doesNotExist();
@@ -225,7 +226,7 @@ class LoggingApplicationListenerTests {
void overrideConfigBroken() {
addPropertiesToEnvironment(this.context, "logging.config=classpath:logback-broken.xml");
assertThatIllegalStateException().isThrownBy(() -> {
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
assertThat(this.output).contains(
"Logging system failed to initialize using configuration from 'classpath:logback-broken.xml'");
assertThat(this.output).contains("ConsolAppender");
@@ -237,7 +238,7 @@ class LoggingApplicationListenerTests {
void addLogFileProperty() {
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml",
"logging.file.name=" + this.logFile);
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
String existingOutput = this.output.toString();
logger.info("Hello world");
@@ -249,7 +250,7 @@ class LoggingApplicationListenerTests {
void addLogFilePropertyWithDefault() {
assertThat(this.logFile).doesNotExist();
addPropertiesToEnvironment(this.context, "logging.file.name=" + this.logFile);
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
logger.info("Hello world");
assertThat(this.logFile).isFile();
@@ -260,7 +261,7 @@ class LoggingApplicationListenerTests {
void addLogPathProperty() {
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml",
"logging.file.path=" + this.tempDir);
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
String existingOutput = this.output.toString();
logger.info("Hello world");
@@ -271,7 +272,7 @@ class LoggingApplicationListenerTests {
@Test
void parseDebugArg() {
addPropertiesToEnvironment(this.context, "debug");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
this.logger.trace("testattrace");
assertThat(this.output).contains("testatdebug");
@@ -281,19 +282,22 @@ class LoggingApplicationListenerTests {
@Test
void parseDebugArgExpandGroups() {
addPropertiesToEnvironment(this.context, "debug");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.loggerContext.getLogger("org.springframework.boot.actuate.endpoint.web").debug("testdebugwebgroup");
this.loggerContext.getLogger("org.hibernate.SQL").debug("testdebugsqlgroup");
assertThat(this.output).contains("testdebugwebgroup");
assertThat(this.output).contains("testdebugsqlgroup");
LoggerGroups loggerGroups = (LoggerGroups) ReflectionTestUtils.getField(this.listener, "loggerGroups");
assertThat(loggerGroups.get("web").getConfiguredLevel()).isEqualTo(LogLevel.DEBUG);
assertThat(loggerGroups).isNotNull();
LoggerGroup loggerGroup = loggerGroups.get("web");
assertThat(loggerGroup).isNotNull();
assertThat(loggerGroup.getConfiguredLevel()).isEqualTo(LogLevel.DEBUG);
}
@Test
void parseTraceArg() {
addPropertiesToEnvironment(this.context, "trace");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
this.logger.trace("testattrace");
assertThat(this.output).contains("testatdebug");
@@ -312,7 +316,7 @@ class LoggingApplicationListenerTests {
private void disableDebugTraceArg(String... environment) {
addPropertiesToEnvironment(this.context, environment);
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
this.logger.trace("testattrace");
assertThat(this.output).doesNotContain("testatdebug");
@@ -322,7 +326,7 @@ class LoggingApplicationListenerTests {
@Test
void parseLevels() {
addPropertiesToEnvironment(this.context, "logging.level.org.springframework.boot=TRACE");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
this.logger.trace("testattrace");
assertThat(this.output).contains("testatdebug");
@@ -332,7 +336,7 @@ class LoggingApplicationListenerTests {
@Test
void parseLevelsCaseInsensitive() {
addPropertiesToEnvironment(this.context, "logging.level.org.springframework.boot=TrAcE");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
this.logger.trace("testattrace");
assertThat(this.output).contains("testatdebug");
@@ -342,7 +346,7 @@ class LoggingApplicationListenerTests {
@Test
void parseLevelsTrimsWhitespace() {
addPropertiesToEnvironment(this.context, "logging.level.org.springframework.boot= trace ");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
this.logger.trace("testattrace");
assertThat(this.output).contains("testatdebug");
@@ -352,7 +356,7 @@ class LoggingApplicationListenerTests {
@Test
void parseLevelsWithPlaceholder() {
addPropertiesToEnvironment(this.context, "foo=TRACE", "logging.level.org.springframework.boot=${foo}");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
this.logger.trace("testattrace");
assertThat(this.output).contains("testatdebug");
@@ -364,13 +368,13 @@ class LoggingApplicationListenerTests {
this.logger.setLevel(Level.INFO);
addPropertiesToEnvironment(this.context, "logging.level.org.springframework.boot=GARBAGE");
assertThatExceptionOfType(BindException.class)
.isThrownBy(() -> this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader()));
.isThrownBy(() -> this.listener.initialize(this.context.getEnvironment(), getClassLoader()));
}
@Test
void parseLevelsNone() {
addPropertiesToEnvironment(this.context, "logging.level.org.springframework.boot=OFF");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
this.logger.error("testaterror");
assertThat(this.output).doesNotContain("testatdebug").doesNotContain("testaterror");
@@ -379,7 +383,7 @@ class LoggingApplicationListenerTests {
@Test
void parseLevelsMapsFalseToOff() {
addPropertiesToEnvironment(this.context, "logging.level.org.springframework.boot=false");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
this.logger.error("testaterror");
assertThat(this.output).doesNotContain("testatdebug").doesNotContain("testaterror");
@@ -389,7 +393,7 @@ class LoggingApplicationListenerTests {
void parseArgsDisabled() {
this.listener.setParseArgs(false);
addPropertiesToEnvironment(this.context, "debug");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
assertThat(this.output).doesNotContain("testatdebug");
}
@@ -400,7 +404,7 @@ class LoggingApplicationListenerTests {
this.listener.setParseArgs(false);
multicastEvent(new ApplicationStartingEvent(this.bootstrapContext, this.springApplication,
new String[] { "--debug" }));
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
assertThat(this.output).doesNotContain("testatdebug");
}
@@ -414,7 +418,7 @@ class LoggingApplicationListenerTests {
@Test
void defaultExceptionConversionWord() {
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.info("Hello world", new RuntimeException("Wrapper", new RuntimeException("Expected")));
assertThat(this.output).contains("Hello world");
assertThat(this.output).doesNotContain("Wrapped by: java.lang.RuntimeException: Wrapper");
@@ -423,7 +427,7 @@ class LoggingApplicationListenerTests {
@Test
void overrideExceptionConversionWord() {
addPropertiesToEnvironment(this.context, "logging.exceptionConversionWord=%rEx");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.info("Hello world", new RuntimeException("Wrapper", new RuntimeException("Expected")));
assertThat(this.output).contains("Hello world");
assertThat(this.output).contains("Wrapped by: java.lang.RuntimeException: Wrapper");
@@ -434,13 +438,16 @@ class LoggingApplicationListenerTests {
TestLoggingApplicationListener listener = new TestLoggingApplicationListener();
Object registered = ReflectionTestUtils.getField(listener, TestLoggingApplicationListener.class,
"shutdownHookRegistered");
assertThat(registered).isNotNull();
((AtomicBoolean) registered).set(false);
System.setProperty(LoggingSystem.class.getName(), TestShutdownHandlerLoggingSystem.class.getName());
multicastEvent(listener, new ApplicationStartingEvent(this.bootstrapContext, new SpringApplication(), NO_ARGS));
listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
listener.initialize(this.context.getEnvironment(), getClassLoader());
assertThat(listener.shutdownHook).isNotNull();
listener.shutdownHook.run();
assertThat(TestShutdownHandlerLoggingSystem.shutdownLatch.await(30, TimeUnit.SECONDS)).isTrue();
CountDownLatch shutdownLatch = TestShutdownHandlerLoggingSystem.shutdownLatch;
assertThat(shutdownLatch).isNotNull();
assertThat(shutdownLatch.await(30, TimeUnit.SECONDS)).isTrue();
}
@Test
@@ -448,11 +455,12 @@ class LoggingApplicationListenerTests {
TestLoggingApplicationListener listener = new TestLoggingApplicationListener();
Object registered = ReflectionTestUtils.getField(listener, TestLoggingApplicationListener.class,
"shutdownHookRegistered");
assertThat(registered).isNotNull();
((AtomicBoolean) registered).set(false);
System.setProperty(LoggingSystem.class.getName(), TestShutdownHandlerLoggingSystem.class.getName());
addPropertiesToEnvironment(this.context, "logging.register_shutdown_hook=false");
multicastEvent(listener, new ApplicationStartingEvent(this.bootstrapContext, new SpringApplication(), NO_ARGS));
listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
listener.initialize(this.context.getEnvironment(), getClassLoader());
assertThat(listener.shutdownHook).isNull();
}
@@ -462,6 +470,7 @@ class LoggingApplicationListenerTests {
multicastEvent(new ApplicationStartingEvent(this.bootstrapContext, this.springApplication, new String[0]));
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils.getField(this.listener,
"loggingSystem");
assertThat(loggingSystem).isNotNull();
assertThat(loggingSystem.cleanedUp).isFalse();
multicastEvent(new ContextClosedEvent(this.context));
assertThat(loggingSystem.cleanedUp).isTrue();
@@ -473,6 +482,7 @@ class LoggingApplicationListenerTests {
multicastEvent(new ApplicationStartingEvent(this.bootstrapContext, this.springApplication, new String[0]));
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils.getField(this.listener,
"loggingSystem");
assertThat(loggingSystem).isNotNull();
assertThat(loggingSystem.cleanedUp).isFalse();
GenericApplicationContext childContext = new GenericApplicationContext();
childContext.setParent(this.context);
@@ -489,7 +499,7 @@ class LoggingApplicationListenerTests {
"logging.file.name=" + this.logFile, "logging.file.path=path", "logging.pattern.console=console",
"logging.pattern.file=file", "logging.pattern.level=level", "logging.pattern.correlation=correlation",
"logging.pattern.rolling-file-name=my.log.%d{yyyyMMdd}.%i.gz");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
assertThat(getSystemProperty(LoggingSystemProperty.CONSOLE_PATTERN)).isEqualTo("console");
assertThat(getSystemProperty(LoggingSystemProperty.FILE_PATTERN)).isEqualTo("file");
assertThat(getSystemProperty(LoggingSystemProperty.EXCEPTION_CONVERSION_WORD)).isEqualTo("conversion");
@@ -503,14 +513,14 @@ class LoggingApplicationListenerTests {
void environmentPropertiesIgnoreUnresolvablePlaceholders() {
// gh-7719
addPropertiesToEnvironment(this.context, "logging.pattern.console=console ${doesnotexist}");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
assertThat(getSystemProperty(LoggingSystemProperty.CONSOLE_PATTERN)).isEqualTo("console ${doesnotexist}");
}
@Test
void environmentPropertiesResolvePlaceholders() {
addPropertiesToEnvironment(this.context, "logging.pattern.console=console ${pid}");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
assertThat(getSystemProperty(LoggingSystemProperty.CONSOLE_PATTERN))
.isEqualTo(this.context.getEnvironment().getProperty("logging.pattern.console"));
}
@@ -518,7 +528,7 @@ class LoggingApplicationListenerTests {
@Test
void logFilePropertiesCanReferenceSystemProperties() {
addPropertiesToEnvironment(this.context, "logging.file.name=" + this.tempDir + "${PID}.log");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
assertThat(getSystemProperty(LoggingSystemProperty.LOG_FILE))
.isEqualTo(this.tempDir + new ApplicationPid().toString() + ".log");
}
@@ -529,6 +539,7 @@ class LoggingApplicationListenerTests {
multicastEvent(new ApplicationStartingEvent(this.bootstrapContext, this.springApplication, new String[0]));
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils.getField(this.listener,
"loggingSystem");
assertThat(loggingSystem).isNotNull();
assertThat(loggingSystem.cleanedUp).isFalse();
multicastEvent(new ApplicationFailedEvent(this.springApplication, new String[0],
new GenericApplicationContext(), new Exception()));
@@ -547,6 +558,7 @@ class LoggingApplicationListenerTests {
.get();
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils.getField(listener,
"loggingSystem");
assertThat(loggingSystem).isNotNull();
assertThat(loggingSystem.cleanedUp).isFalse();
WebServerStyleLifecycle lifecycle = context.getBean(WebServerStyleLifecycle.class);
AtomicBoolean called = new AtomicBoolean();
@@ -567,7 +579,7 @@ class LoggingApplicationListenerTests {
propertySources
.addFirst(new MapPropertySource("test1", Collections.singletonMap("logging.level.ROOT", "DEBUG")));
propertySources.addLast(new MapPropertySource("test2", Collections.singletonMap("logging.level.root", "WARN")));
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
this.logger.debug("testatdebug");
assertThat(this.output).contains("testatdebug");
}
@@ -575,7 +587,7 @@ class LoggingApplicationListenerTests {
@Test
void loggingGroupsDefaultsAreApplied() {
addPropertiesToEnvironment(this.context, "logging.level.web=TRACE");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
assertTraceEnabled("org.springframework.core", false);
assertTraceEnabled("org.springframework.core.codec", true);
assertTraceEnabled("org.springframework.http", true);
@@ -588,12 +600,18 @@ class LoggingApplicationListenerTests {
void loggingGroupsCanBeDefined() {
addPropertiesToEnvironment(this.context, "logging.group.foo=com.foo.bar,com.foo.baz",
"logging.level.foo=TRACE");
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
this.listener.initialize(this.context.getEnvironment(), getClassLoader());
assertTraceEnabled("com.foo", false);
assertTraceEnabled("com.foo.bar", true);
assertTraceEnabled("com.foo.baz", true);
}
private ClassLoader getClassLoader() {
ClassLoader classLoader = this.context.getClassLoader();
assertThat(classLoader).isNotNull();
return classLoader;
}
private String getSystemProperty(LoggingSystemProperty property) {
return System.getProperty(property.getEnvironmentVariableName());
}
@@ -636,7 +654,7 @@ class LoggingApplicationListenerTests {
static class TestShutdownHandlerLoggingSystem extends AbstractLoggingSystem {
private static CountDownLatch shutdownLatch;
private static @Nullable CountDownLatch shutdownLatch;
TestShutdownHandlerLoggingSystem(ClassLoader classLoader) {
super(classLoader);
@@ -649,38 +667,42 @@ class LoggingApplicationListenerTests {
}
@Override
protected void loadDefaults(LoggingInitializationContext initializationContext, LogFile logFile) {
protected void loadDefaults(LoggingInitializationContext initializationContext, @Nullable LogFile logFile) {
}
@Override
protected void loadConfiguration(LoggingInitializationContext initializationContext, String location,
LogFile logFile) {
@Nullable LogFile logFile) {
}
@Override
public void setLogLevel(String loggerName, LogLevel level) {
public void setLogLevel(@Nullable String loggerName, @Nullable LogLevel level) {
}
@Override
public List<LoggerConfiguration> getLoggerConfigurations() {
return null;
return Collections.emptyList();
}
@Override
public LoggerConfiguration getLoggerConfiguration(String loggerName) {
public @Nullable LoggerConfiguration getLoggerConfiguration(String loggerName) {
return null;
}
@Override
public Runnable getShutdownHandler() {
return () -> TestShutdownHandlerLoggingSystem.shutdownLatch.countDown();
return () -> {
CountDownLatch shutdownLatch = TestShutdownHandlerLoggingSystem.shutdownLatch;
assertThat(shutdownLatch).isNotNull();
shutdownLatch.countDown();
};
}
}
static class TestLoggingApplicationListener extends LoggingApplicationListener {
private Runnable shutdownHook;
private @Nullable Runnable shutdownHook;
@Override
void registerShutdownHook(Runnable shutdownHook) {
@@ -701,16 +723,16 @@ class LoggingApplicationListenerTests {
}
@Override
public void setLogLevel(String loggerName, LogLevel level) {
public void setLogLevel(@Nullable String loggerName, @Nullable LogLevel level) {
}
@Override
public List<LoggerConfiguration> getLoggerConfigurations() {
return null;
return Collections.emptyList();
}
@Override
public LoggerConfiguration getLoggerConfiguration(String loggerName) {
public @Nullable LoggerConfiguration getLoggerConfiguration(String loggerName) {
return null;
}
@@ -732,22 +754,22 @@ class LoggingApplicationListenerTests {
}
@Override
public void initialize(LoggingInitializationContext initializationContext, String configLocation,
LogFile logFile) {
public void initialize(LoggingInitializationContext initializationContext, @Nullable String configLocation,
@Nullable LogFile logFile) {
throw new Error("Deliberately broken");
}
@Override
public void setLogLevel(String loggerName, LogLevel level) {
public void setLogLevel(@Nullable String loggerName, @Nullable LogLevel level) {
}
@Override
public List<LoggerConfiguration> getLoggerConfigurations() {
return null;
return Collections.emptyList();
}
@Override
public LoggerConfiguration getLoggerConfiguration(String loggerName) {
public @Nullable LoggerConfiguration getLoggerConfiguration(String loggerName) {
return null;
}
@@ -763,7 +785,7 @@ class LoggingApplicationListenerTests {
private volatile boolean running;
Runnable onStop;
@Nullable Runnable onStop;
@Override
public void start() {
@@ -773,7 +795,9 @@ class LoggingApplicationListenerTests {
@Override
public void stop() {
this.running = false;
this.onStop.run();
if (this.onStop != null) {
this.onStop.run();
}
}
@Override
@@ -21,6 +21,7 @@ import java.util.stream.Stream;
import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.AssertProvider;
import org.assertj.core.error.BasicErrorMessageFactory;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.TypeHint;
@@ -28,6 +29,7 @@ import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.beans.factory.aot.AotServices;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
import org.springframework.beans.factory.aot.BeanFactoryInitializationCode;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.context.properties.ConfigurationPropertiesBeanFactoryInitializationAotProcessor.ConfigurationPropertiesReflectionHintsContribution;
@@ -38,6 +40,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link ConfigurationPropertiesBeanFactoryInitializationAotProcessor}.
@@ -67,6 +70,7 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("test", new SampleProperties());
ConfigurationPropertiesReflectionHintsContribution contribution = process(beanFactory);
assertThat(contribution).isNotNull();
assertThat(singleBindable(contribution)).hasBindMethod(BindMethod.JAVA_BEAN).hasType(SampleProperties.class);
assertThat(typeHints(contribution).map(TypeHint::getType))
.containsExactly(TypeReference.of(SampleProperties.class));
@@ -75,6 +79,7 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
@Test
void javaBeanConfigurationPropertiesBindAsJavaBean() {
ConfigurationPropertiesReflectionHintsContribution contribution = process(EnableJavaBeanProperties.class);
assertThat(contribution).isNotNull();
assertThat(singleBindable(contribution)).hasBindMethod(BindMethod.JAVA_BEAN).hasType(JavaBeanProperties.class);
assertThat(typeHints(contribution).map(TypeHint::getType))
.containsExactly(TypeReference.of(JavaBeanProperties.class));
@@ -84,6 +89,7 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
void constructorBindingConfigurationPropertiesBindAsValueObject() {
ConfigurationPropertiesReflectionHintsContribution contribution = process(
EnableConstructorBindingProperties.class);
assertThat(contribution).isNotNull();
assertThat(singleBindable(contribution)).hasBindMethod(BindMethod.VALUE_OBJECT)
.hasType(ConstructorBindingProperties.class);
assertThat(typeHints(contribution).map(TypeHint::getType))
@@ -94,6 +100,7 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
void possibleConstructorBindingPropertiesDefinedThroughBeanMethodBindAsJavaBean() {
ConfigurationPropertiesReflectionHintsContribution contribution = process(
PossibleConstructorBindingPropertiesBeanMethodConfiguration.class);
assertThat(contribution).isNotNull();
assertThat(singleBindable(contribution)).hasBindMethod(BindMethod.JAVA_BEAN)
.hasType(PossibleConstructorBindingProperties.class);
assertThat(typeHints(contribution).map(TypeHint::getType))
@@ -104,6 +111,7 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
void possibleConstructorBindingPropertiesDefinedThroughEnabledAnnotationBindAsValueObject() {
ConfigurationPropertiesReflectionHintsContribution contribution = process(
EnablePossibleConstructorBindingProperties.class);
assertThat(contribution).isNotNull();
assertThat(singleBindable(contribution)).hasBindMethod(BindMethod.VALUE_OBJECT)
.hasType(PossibleConstructorBindingProperties.class);
assertThat(typeHints(contribution).map(TypeHint::getType))
@@ -112,17 +120,18 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
private Stream<TypeHint> typeHints(ConfigurationPropertiesReflectionHintsContribution contribution) {
TestGenerationContext generationContext = new TestGenerationContext();
contribution.applyTo(generationContext, null);
contribution.applyTo(generationContext, mock(BeanFactoryInitializationCode.class));
return generationContext.getRuntimeHints().reflection().typeHints();
}
private ConfigurationPropertiesReflectionHintsContribution process(Class<?> config) {
private @Nullable ConfigurationPropertiesReflectionHintsContribution process(Class<?> config) {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(config)) {
return process(context.getBeanFactory());
}
}
private ConfigurationPropertiesReflectionHintsContribution process(ConfigurableListableBeanFactory beanFactory) {
private @Nullable ConfigurationPropertiesReflectionHintsContribution process(
ConfigurableListableBeanFactory beanFactory) {
return this.processor.processAheadOfTime(beanFactory);
}
@@ -144,13 +153,13 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
@ConfigurationProperties("java-bean")
static class JavaBeanProperties {
private String value;
private @Nullable String value;
String getValue() {
@Nullable String getValue() {
return this.value;
}
void setValue(String value) {
void setValue(@Nullable String value) {
this.value = value;
}
@@ -195,17 +204,17 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
@ConfigurationProperties("possible-constructor-binding")
static class PossibleConstructorBindingProperties {
private String value;
private @Nullable String value;
PossibleConstructorBindingProperties(String arg) {
}
String getValue() {
@Nullable String getValue() {
return this.value;
}
void setValue(String value) {
void setValue(@Nullable String value) {
this.value = value;
}
@@ -19,6 +19,7 @@ package org.springframework.boot.context.properties;
import java.util.Arrays;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.aot.test.generate.TestGenerationContext;
@@ -81,7 +82,7 @@ class ConfigurationPropertiesBeanRegistrationAotProcessorTests {
assertThat(contribution).isNotNull();
}
private BeanRegistrationAotContribution process(Class<?> type) {
private @Nullable BeanRegistrationAotContribution process(Class<?> type) {
ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(this.beanFactory);
beanRegistrar.register(type);
RegisteredBean registeredBean = RegisteredBean.of(this.beanFactory,
@@ -177,13 +178,13 @@ class ConfigurationPropertiesBeanRegistrationAotProcessorTests {
@ConfigurationProperties("test")
public static class JavaBeanSampleBean {
private String name;
private @Nullable String name;
public String getName() {
public @Nullable String getName() {
return this.name;
}
public void setName(String name) {
public void setName(@Nullable String name) {
this.name = name;
}
@@ -22,6 +22,7 @@ import java.util.Map;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.description.annotation.AnnotationDescription;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.ThrowingConsumer;
@@ -60,18 +61,21 @@ class ConfigurationPropertiesBeanTests {
Map<String, ConfigurationPropertiesBean> all = ConfigurationPropertiesBean.getAll(context);
assertThat(all).containsOnlyKeys("annotatedComponent", "annotatedBean", ValueObject.class.getName());
ConfigurationPropertiesBean component = all.get("annotatedComponent");
assertThat(component).isNotNull();
assertThat(component.getName()).isEqualTo("annotatedComponent");
assertThat(component.getInstance()).isInstanceOf(AnnotatedComponent.class);
assertThat(component.getAnnotation()).isNotNull();
assertThat(component.getType()).isEqualTo(AnnotatedComponent.class);
assertThat(component.asBindTarget().getBindMethod()).isEqualTo(BindMethod.JAVA_BEAN);
ConfigurationPropertiesBean bean = all.get("annotatedBean");
assertThat(bean).isNotNull();
assertThat(bean.getName()).isEqualTo("annotatedBean");
assertThat(bean.getInstance()).isInstanceOf(AnnotatedBean.class);
assertThat(bean.getType()).isEqualTo(AnnotatedBean.class);
assertThat(bean.getAnnotation()).isNotNull();
assertThat(bean.asBindTarget().getBindMethod()).isEqualTo(BindMethod.JAVA_BEAN);
ConfigurationPropertiesBean valueObject = all.get(ValueObject.class.getName());
assertThat(valueObject).isNotNull();
assertThat(valueObject.getName()).isEqualTo(ValueObject.class.getName());
assertThat(valueObject.getInstance()).isInstanceOf(ValueObject.class);
assertThat(valueObject.getType()).isEqualTo(ValueObject.class);
@@ -157,6 +161,7 @@ class ConfigurationPropertiesBeanTests {
@Test
void getWhenHasFactoryMethodBindsUsingMethodReturnType() throws Throwable {
get(NonAnnotatedGenericBeanConfiguration.class, "nonAnnotatedGenericBean", (propertiesBean) -> {
assertThat(propertiesBean).isNotNull();
assertThat(propertiesBean.getType()).isEqualTo(NonAnnotatedGenericBean.class);
assertThat(propertiesBean.asBindTarget().getBindMethod()).isEqualTo(BindMethod.JAVA_BEAN);
ResolvableType type = propertiesBean.asBindTarget().getType();
@@ -168,6 +173,7 @@ class ConfigurationPropertiesBeanTests {
@Test
void getWhenHasFactoryMethodWithoutAnnotationBindsUsingMethodType() throws Throwable {
get(AnnotatedGenericBeanConfiguration.class, "annotatedGenericBean", (propertiesBean) -> {
assertThat(propertiesBean).isNotNull();
assertThat(propertiesBean.getType()).isEqualTo(AnnotatedGenericBean.class);
assertThat(propertiesBean.asBindTarget().getBindMethod()).isEqualTo(BindMethod.JAVA_BEAN);
ResolvableType type = propertiesBean.asBindTarget().getType();
@@ -179,6 +185,7 @@ class ConfigurationPropertiesBeanTests {
@Test
void getWhenHasNoFactoryMethodBindsUsingObjectType() throws Throwable {
get(AnnotatedGenericComponent.class, "annotatedGenericComponent", (propertiesBean) -> {
assertThat(propertiesBean).isNotNull();
assertThat(propertiesBean.getType()).isEqualTo(AnnotatedGenericComponent.class);
assertThat(propertiesBean.asBindTarget().getBindMethod()).isEqualTo(BindMethod.JAVA_BEAN);
ResolvableType type = propertiesBean.asBindTarget().getType();
@@ -189,14 +196,18 @@ class ConfigurationPropertiesBeanTests {
@Test
void getWhenHasFactoryMethodAndBeanAnnotationFavorsFactoryMethod() throws Throwable {
get(AnnotatedBeanConfiguration.class, "annotatedBean",
(propertiesBean) -> assertThat(propertiesBean.getAnnotation().prefix()).isEqualTo("factory"));
get(AnnotatedBeanConfiguration.class, "annotatedBean", (propertiesBean) -> {
assertThat(propertiesBean).isNotNull();
assertThat(propertiesBean.getAnnotation().prefix()).isEqualTo("factory");
});
}
@Test
void getWhenHasValidatedBeanBindsWithBeanAnnotation() throws Throwable {
get(ValidatedBeanConfiguration.class, "validatedBean", (propertiesBean) -> {
assertThat(propertiesBean).isNotNull();
Validated validated = propertiesBean.asBindTarget().getAnnotation(Validated.class);
assertThat(validated).isNotNull();
assertThat(validated.value()).containsExactly(BeanGroup.class);
});
}
@@ -204,7 +215,9 @@ class ConfigurationPropertiesBeanTests {
@Test
void getWhenHasValidatedFactoryMethodBindsWithFactoryMethodAnnotation() throws Throwable {
get(ValidatedMethodConfiguration.class, "annotatedBean", (propertiesBean) -> {
assertThat(propertiesBean).isNotNull();
Validated validated = propertiesBean.asBindTarget().getAnnotation(Validated.class);
assertThat(validated).isNotNull();
assertThat(validated.value()).containsExactly(FactoryMethodGroup.class);
});
}
@@ -212,7 +225,9 @@ class ConfigurationPropertiesBeanTests {
@Test
void getWhenHasValidatedBeanAndFactoryMethodBindsWithFactoryMethodAnnotation() throws Throwable {
get(ValidatedMethodAndBeanConfiguration.class, "validatedBean", (propertiesBean) -> {
assertThat(propertiesBean).isNotNull();
Validated validated = propertiesBean.asBindTarget().getAnnotation(Validated.class);
assertThat(validated).isNotNull();
assertThat(validated.value()).containsExactly(FactoryMethodGroup.class);
});
}
@@ -336,18 +351,18 @@ class ConfigurationPropertiesBeanTests {
assertThat(bindType).isEqualTo(BindMethod.JAVA_BEAN);
}
private void get(Class<?> configuration, String beanName, ThrowingConsumer<ConfigurationPropertiesBean> consumer)
throws Throwable {
private void get(Class<?> configuration, String beanName,
ThrowingConsumer<@Nullable ConfigurationPropertiesBean> consumer) throws Throwable {
get(configuration, beanName, true, consumer);
}
private void getWithoutBeanMetadataCaching(Class<?> configuration, String beanName,
ThrowingConsumer<ConfigurationPropertiesBean> consumer) throws Throwable {
ThrowingConsumer<@Nullable ConfigurationPropertiesBean> consumer) throws Throwable {
get(configuration, beanName, false, consumer);
}
private void get(Class<?> configuration, String beanName, boolean cacheBeanMetadata,
ThrowingConsumer<ConfigurationPropertiesBean> consumer) throws Throwable {
ThrowingConsumer<@Nullable ConfigurationPropertiesBean> consumer) throws Throwable {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
context.getBeanFactory().setCacheBeanMetadata(cacheBeanMetadata);
context.register(configuration);
@@ -36,6 +36,7 @@ class ConfigurationPropertiesBindExceptionTests {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Example.class);
ConfigurationPropertiesBean bean = ConfigurationPropertiesBean.get(applicationContext,
applicationContext.getBean(Example.class), "example");
assertThat(bean).isNotNull();
ConfigurationPropertiesBindException exception = new ConfigurationPropertiesBindException(bean,
new IllegalStateException());
assertThat(exception.getMessage()).isEqualTo("Error creating bean with name 'example': "
@@ -20,6 +20,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -57,9 +58,11 @@ class ConfigurationPropertiesBindHandlerAdvisorTests {
"foo.bar.bindings.output.destination=d2");
BindingServiceProperties properties = this.context.getBean(BindingServiceProperties.class);
BindingProperties input = properties.getBindings().get("input");
assertThat(input).isNotNull();
assertThat(input.getDestination()).isEqualTo("d1");
assertThat(input.getContentType()).isEqualTo("text/xml");
BindingProperties output = properties.getBindings().get("output");
assertThat(output).isNotNull();
assertThat(output.getDestination()).isEqualTo("d2");
assertThat(output.getContentType()).isEqualTo("application/json");
}
@@ -71,9 +74,11 @@ class ConfigurationPropertiesBindHandlerAdvisorTests {
"foo.bar.bindings.output.destination=d2");
BindingServiceProperties properties = this.context.getBean(BindingServiceProperties.class);
BindingProperties input = properties.getBindings().get("input");
assertThat(input).isNotNull();
assertThat(input.getDestination()).isEqualTo("d1");
assertThat(input.getContentType()).isEqualTo("text/xml");
BindingProperties output = properties.getBindings().get("output");
assertThat(output).isNotNull();
assertThat(output.getDestination()).isEqualTo("d2");
assertThat(output.getContentType()).isEqualTo("text/plain");
}
@@ -124,7 +129,8 @@ class ConfigurationPropertiesBindHandlerAdvisorTests {
}
@Override
public <T> Bindable<T> onStart(ConfigurationPropertyName name, Bindable<T> target, BindContext context) {
public <T> @Nullable Bindable<T> onStart(ConfigurationPropertyName name, Bindable<T> target,
BindContext context) {
ConfigurationPropertyName defaultName = getDefaultName(name);
if (defaultName != null) {
BindResult<T> result = context.getBinder().bind(defaultName, target);
@@ -135,7 +141,7 @@ class ConfigurationPropertiesBindHandlerAdvisorTests {
return super.onStart(name, target, context);
}
private ConfigurationPropertyName getDefaultName(ConfigurationPropertyName name) {
private @Nullable ConfigurationPropertyName getDefaultName(ConfigurationPropertyName name) {
for (Map.Entry<ConfigurationPropertyName, ConfigurationPropertyName> mapping : this.mappings.entrySet()) {
ConfigurationPropertyName from = mapping.getKey();
ConfigurationPropertyName to = mapping.getValue();
@@ -161,15 +167,15 @@ class ConfigurationPropertiesBindHandlerAdvisorTests {
static class BindingProperties {
private String destination;
private @Nullable String destination;
private String contentType = "application/json";
String getDestination() {
@Nullable String getDestination() {
return this.destination;
}
void setDestination(String destination) {
void setDestination(@Nullable String destination) {
this.destination = destination;
}
@@ -19,6 +19,7 @@ package org.springframework.boot.context.properties;
import java.io.IOException;
import java.util.Objects;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -151,7 +152,7 @@ class ConfigurationPropertiesScanTests {
}
@Override
public boolean equals(Object o) {
public boolean equals(@Nullable Object o) {
return (this == o);
}
@@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
class ConfigurationPropertiesTestBeanTests {
@TestBean
@SuppressWarnings("NullAway.Init")
private ImmutableProperties properties;
@Autowired
@@ -38,6 +38,7 @@ import jakarta.annotation.PostConstruct;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -56,6 +57,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesTests.JavaBeanNestedConstructorBindingProperties.Nested;
import org.springframework.boot.context.properties.bind.BindException;
import org.springframework.boot.context.properties.bind.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
@@ -368,7 +370,9 @@ class ConfigurationPropertiesTests {
void loadShouldBindToJavaTimeDuration() {
load(BasicConfiguration.class, "duration=PT1M");
BasicProperties bean = this.context.getBean(BasicProperties.class);
assertThat(bean.getDuration().getSeconds()).isEqualTo(60);
Duration duration = bean.getDuration();
assertThat(duration).isNotNull();
assertThat(duration.getSeconds()).isEqualTo(60);
}
@Test
@@ -480,7 +484,9 @@ class ConfigurationPropertiesTests {
void loadShouldBindToMapWithNumericKey() {
load(MapWithNumericKeyProperties.class, "sample.properties.1.name=One");
MapWithNumericKeyProperties bean = this.context.getBean(MapWithNumericKeyProperties.class);
assertThat(bean.getProperties().get("1").name).isEqualTo("One");
BasicProperties one = bean.getProperties().get("1");
assertThat(one).isNotNull();
assertThat(one.name).isEqualTo("One");
}
@Test
@@ -491,8 +497,10 @@ class ConfigurationPropertiesTests {
Collections.singletonMap("TEST_MAP_FOO_BAR", "baz")));
load(WithComplexMapProperties.class);
WithComplexMapProperties bean = this.context.getBean(WithComplexMapProperties.class);
assertThat(bean.getMap()).containsOnlyKeys("foo");
assertThat(bean.getMap().get("foo")).containsOnly(entry("bar", "baz"));
Map<String, Map<String, String>> map = bean.getMap();
assertThat(map).isNotNull();
assertThat(map).containsOnlyKeys("foo");
assertThat(map.get("foo")).containsOnly(entry("bar", "baz"));
}
@Test
@@ -692,6 +700,7 @@ class ConfigurationPropertiesTests {
void loadShouldUseConverterBean() {
prepareConverterContext(PersonConverterConfiguration.class, PersonProperties.class);
Person person = this.context.getBean(PersonProperties.class).getPerson();
assertThat(person).isNotNull();
assertThat(person.firstName).isEqualTo("John");
assertThat(person.lastName).isEqualTo("Smith");
}
@@ -727,6 +736,7 @@ class ConfigurationPropertiesTests {
this.context.getEnvironment().getPropertySources().addLast(testProperties);
this.context.refresh();
Person person = this.context.getBean(PersonProperties.class).getPerson();
assertThat(person).isNotNull();
assertThat(person.firstName).isEqualTo("John");
assertThat(person.lastName).isEqualTo("Smith");
}
@@ -739,9 +749,13 @@ class ConfigurationPropertiesTests {
load(new Class<?>[] { PersonConverterConfiguration.class, PersonAndAlienProperties.class },
"test.person=John Smith", "test.alien=Alf Tanner");
PersonAndAlienProperties properties = this.context.getBean(PersonAndAlienProperties.class);
assertThat(properties.getPerson().firstName).isEqualTo("John");
assertThat(properties.getPerson().lastName).isEqualTo("Smith");
assertThat(properties.getAlien().name).isEqualTo("rennaT flA");
Person person = properties.getPerson();
assertThat(person).isNotNull();
assertThat(person.firstName).isEqualTo("John");
assertThat(person.lastName).isEqualTo("Smith");
Alien alien = properties.getAlien();
assertThat(alien).isNotNull();
assertThat(alien.name).isEqualTo("rennaT flA");
}
@Test
@@ -752,9 +766,13 @@ class ConfigurationPropertiesTests {
load(new Class<?>[] { AlienConverterConfiguration.class, PersonAndAlienProperties.class },
"test.person=John Smith", "test.alien=Alf Tanner");
PersonAndAlienProperties properties = this.context.getBean(PersonAndAlienProperties.class);
assertThat(properties.getPerson().firstName).isEqualTo("John");
assertThat(properties.getPerson().lastName).isEqualTo("Smith");
assertThat(properties.getAlien().name).isEqualTo("rennaT flA");
Person person = properties.getPerson();
assertThat(person).isNotNull();
assertThat(person.firstName).isEqualTo("John");
assertThat(person.lastName).isEqualTo("Smith");
Alien alien = properties.getAlien();
assertThat(alien).isNotNull();
assertThat(alien.name).isEqualTo("rennaT flA");
}
@Test // gh-38734
@@ -765,10 +783,14 @@ class ConfigurationPropertiesTests {
load(new Class<?>[] { AlienConverterConfiguration.class, PersonAndAliensProperties.class },
"test.person=John Smith", "test.aliens=Alf Tanner,Gilbert");
PersonAndAliensProperties properties = this.context.getBean(PersonAndAliensProperties.class);
assertThat(properties.getPerson().firstName).isEqualTo("John");
assertThat(properties.getPerson().lastName).isEqualTo("Smith");
assertThat(properties.getAliens().get(0).name).isEqualTo("rennaT flA");
assertThat(properties.getAliens().get(1).name).isEqualTo("trebliG");
Person person = properties.getPerson();
assertThat(person).isNotNull();
assertThat(person.firstName).isEqualTo("John");
assertThat(person.lastName).isEqualTo("Smith");
List<Alien> aliens = properties.getAliens();
assertThat(aliens).isNotNull();
assertThat(aliens.get(0).name).isEqualTo("rennaT flA");
assertThat(aliens.get(1).name).isEqualTo("trebliG");
}
@Test
@@ -782,6 +804,7 @@ class ConfigurationPropertiesTests {
void loadShouldUseGenericConverterBean() {
prepareConverterContext(GenericConverterConfiguration.class, PersonProperties.class);
Person person = this.context.getBean(PersonProperties.class).getPerson();
assertThat(person).isNotNull();
assertThat(person.firstName).isEqualTo("John");
assertThat(person.lastName).isEqualTo("Smith");
}
@@ -790,6 +813,7 @@ class ConfigurationPropertiesTests {
void loadShouldUseFormatterBean() {
prepareConverterContext(FormatterConfiguration.class, PersonProperties.class);
Person person = this.context.getBean(PersonProperties.class).getPerson();
assertThat(person).isNotNull();
assertThat(person.firstName).isEqualTo("John");
assertThat(person.lastName).isEqualTo("Smith");
}
@@ -875,8 +899,10 @@ class ConfigurationPropertiesTests {
this.context.getBeanFactory().registerCustomEditor(Person.class, PersonPropertyEditor.class);
load(PersonProperties.class, "test.person=boot,spring");
PersonProperties bean = this.context.getBean(PersonProperties.class);
assertThat(bean.getPerson().firstName).isEqualTo("spring");
assertThat(bean.getPerson().lastName).isEqualTo("boot");
Person person = bean.getPerson();
assertThat(person).isNotNull();
assertThat(person.firstName).isEqualTo("spring");
assertThat(person.lastName).isEqualTo("boot");
}
@Test
@@ -918,11 +944,18 @@ class ConfigurationPropertiesTests {
sources.addLast(new MapPropertySource("test", source));
load(WithIntegerMapProperties.class);
WithIntegerMapProperties bean = this.context.getBean(WithIntegerMapProperties.class);
Map<Integer, Foo> x = bean.getMap().get("x");
assertThat(x.get(-1).getA()).isEqualTo("baz");
assertThat(x.get(-1).getB()).isZero();
assertThat(x.get(1).getA()).isEqualTo("bar");
assertThat(x.get(1).getB()).isOne();
Map<String, Map<Integer, Foo>> map = bean.getMap();
assertThat(map).isNotNull();
Map<Integer, Foo> x = map.get("x");
assertThat(x).isNotNull();
Foo minus1 = x.get(-1);
assertThat(minus1).isNotNull();
assertThat(minus1.getA()).isEqualTo("baz");
assertThat(minus1.getB()).isZero();
Foo one = x.get(1);
assertThat(one).isNotNull();
assertThat(one.getA()).isEqualTo("bar");
assertThat(one.getB()).isOne();
}
@Test
@@ -1133,7 +1166,9 @@ class ConfigurationPropertiesTests {
load(JavaBeanNestedConstructorBindingPropertiesConfiguration.class);
JavaBeanNestedConstructorBindingProperties bean = this.context
.getBean(JavaBeanNestedConstructorBindingProperties.class);
assertThat(bean.getNested().getAge()).isEqualTo(5);
Nested nested = bean.getNested();
assertThat(nested).isNotNull();
assertThat(nested.getAge()).isEqualTo(5);
}
@Test
@@ -1156,7 +1191,9 @@ class ConfigurationPropertiesTests {
load(JavaBeanNonDefaultConstructorPropertiesConfiguration.class);
JavaBeanNonDefaultConstructorProperties bean = this.context
.getBean(JavaBeanNonDefaultConstructorProperties.class);
assertThat(bean.getNested().getAge()).isEqualTo(10);
JavaBeanNonDefaultConstructorProperties.Nested nested = bean.getNested();
assertThat(nested).isNotNull();
assertThat(nested.getAge()).isEqualTo(10);
}
@Test // gh-18652
@@ -1177,7 +1214,9 @@ class ConfigurationPropertiesTests {
load(ConstructorBindingWithOuterClassConstructorBoundConfiguration.class);
ConstructorBindingWithOuterClassConstructorBoundProperties bean = this.context
.getBean(ConstructorBindingWithOuterClassConstructorBoundProperties.class);
assertThat(bean.getNested().getOuter().getAge()).isEqualTo(5);
Outer outer = bean.getNested().getOuter();
assertThat(outer).isNotNull();
assertThat(outer.getAge()).isEqualTo(5);
}
@Test
@@ -1218,6 +1257,7 @@ class ConfigurationPropertiesTests {
void boundPropertiesShouldBeRecorded() {
load(NestedConfiguration.class, "name=foo", "nested.name=bar");
BoundConfigurationProperties bound = BoundConfigurationProperties.get(this.context);
assertThat(bound).isNotNull();
Set<ConfigurationPropertyName> keys = bound.getAll().keySet();
assertThat(keys.stream().map(ConfigurationPropertyName::toString)).contains("name", "nested.name");
}
@@ -1228,7 +1268,9 @@ class ConfigurationPropertiesTests {
load(WithCustomConverterAndObjectToObjectMethodConfiguration.class, "test.item=foo");
WithCustomConverterAndObjectToObjectMethodProperties bean = this.context
.getBean(WithCustomConverterAndObjectToObjectMethodProperties.class);
assertThat(bean.getItem().getValue()).isEqualTo("foo");
WithPublicObjectToObjectMethod item = bean.getItem();
assertThat(item).isNotNull();
assertThat(item.getValue()).isEqualTo("foo");
}
@Test // gh-33710
@@ -1465,15 +1507,15 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties
static class WithPostConstructConfiguration {
private String bar;
private @Nullable String bar;
private boolean initialized;
void setBar(String bar) {
void setBar(@Nullable String bar) {
this.bar = bar;
}
String getBar() {
@Nullable String getBar() {
return this.bar;
}
@@ -1564,13 +1606,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class PropertiesWithResource {
private Resource resource;
private @Nullable Resource resource;
Resource getResource() {
@Nullable Resource getResource() {
return this.resource;
}
void setResource(Resource resource) {
void setResource(@Nullable Resource resource) {
this.resource = resource;
}
@@ -1581,7 +1623,7 @@ class ConfigurationPropertiesTests {
static final String PREFIX = "test:/";
@Override
public Resource resolve(String location, ResourceLoader resourceLoader) {
public @Nullable Resource resolve(String location, ResourceLoader resourceLoader) {
if (location.startsWith(PREFIX)) {
String path = location.substring(PREFIX.length());
return new ClassPathResource(path);
@@ -1691,13 +1733,13 @@ class ConfigurationPropertiesTests {
static class AGenericClass<T> {
private T bar;
private @Nullable T bar;
T getBar() {
@Nullable T getBar() {
return this.bar;
}
void setBar(T bar) {
void setBar(@Nullable T bar) {
this.bar = bar;
}
@@ -1705,23 +1747,23 @@ class ConfigurationPropertiesTests {
static class PrototypeBean {
private String one;
private @Nullable String one;
private String two;
private @Nullable String two;
String getOne() {
@Nullable String getOne() {
return this.one;
}
void setOne(String one) {
void setOne(@Nullable String one) {
this.one = one;
}
String getTwo() {
@Nullable String getTwo() {
return this.two;
}
void setTwo(String two) {
void setTwo(@Nullable String two) {
this.two = two;
}
@@ -1737,7 +1779,7 @@ class ConfigurationPropertiesTests {
}
@Override
public Class<?> getObjectType() {
public @Nullable Class<?> getObjectType() {
return null;
}
@@ -1756,17 +1798,17 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties
public static class BasicProperties {
private String name;
private @Nullable String name;
private int[] array;
private int @Nullable [] array;
private List<Integer> list = new ArrayList<>();
private @Nullable List<Integer> list = new ArrayList<>();
private Duration duration;
private @Nullable Duration duration;
// No getter - you should be able to bind to a write-only bean
public void setName(String name) {
public void setName(@Nullable String name) {
// Must be public for XML
this.name = name;
}
@@ -1775,23 +1817,23 @@ class ConfigurationPropertiesTests {
this.array = values;
}
int[] getArray() {
int @Nullable [] getArray() {
return this.array;
}
List<Integer> getList() {
@Nullable List<Integer> getList() {
return this.list;
}
void setList(List<Integer> list) {
void setList(@Nullable List<Integer> list) {
this.list = list;
}
Duration getDuration() {
@Nullable Duration getDuration() {
return this.duration;
}
void setDuration(Duration duration) {
void setDuration(@Nullable Duration duration) {
this.duration = duration;
}
@@ -1800,11 +1842,11 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties
static class NestedProperties {
private String name;
private @Nullable String name;
private final Nested nested = new Nested();
void setName(String name) {
void setName(@Nullable String name) {
this.name = name;
}
@@ -1814,9 +1856,9 @@ class ConfigurationPropertiesTests {
static class Nested {
private String name;
private @Nullable String name;
void setName(String name) {
void setName(@Nullable String name) {
this.name = name;
}
@@ -1863,6 +1905,7 @@ class ConfigurationPropertiesTests {
static class Jsr303Properties extends BasicProperties {
@NotEmpty
@SuppressWarnings("NullAway.Init")
private String description;
String getDescription() {
@@ -1920,9 +1963,9 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties
static class WithoutAnnotationValueProperties {
private String name;
private @Nullable String name;
void setName(String name) {
void setName(@Nullable String name) {
this.name = name;
}
@@ -1934,13 +1977,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties
static class MapProperties {
private Map<String, String> mymap;
private @Nullable Map<String, String> mymap;
void setMymap(Map<String, String> mymap) {
void setMymap(@Nullable Map<String, String> mymap) {
this.mymap = mymap;
}
Map<String, String> getMymap() {
@Nullable Map<String, String> getMymap() {
return this.mymap;
}
@@ -1957,7 +2000,7 @@ class ConfigurationPropertiesTests {
assertThat(this.properties).isNotNull();
}
String getName() {
@Nullable String getName() {
return this.properties.name;
}
@@ -1974,6 +2017,7 @@ class ConfigurationPropertiesTests {
static class ValidatedImplementationProperties implements InterfaceForValidatedImplementation {
@NotNull
@SuppressWarnings("NullAway.Init")
private String foo;
@Override
@@ -1992,13 +2036,13 @@ class ConfigurationPropertiesTests {
static class WithPropertyPlaceholderValueProperties {
@Value("${default.value}")
private String value;
private @Nullable String value;
void setValue(String value) {
void setValue(@Nullable String value) {
this.value = value;
}
String getValue() {
@Nullable String getValue() {
return this.value;
}
@@ -2008,23 +2052,23 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class WithEnumProperties {
private FooEnum theValue;
private @Nullable FooEnum theValue;
private List<FooEnum> theValues;
private @Nullable List<FooEnum> theValues;
void setTheValue(FooEnum value) {
void setTheValue(@Nullable FooEnum value) {
this.theValue = value;
}
FooEnum getTheValue() {
@Nullable FooEnum getTheValue() {
return this.theValue;
}
List<FooEnum> getTheValues() {
@Nullable List<FooEnum> getTheValues() {
return this.theValues;
}
void setTheValues(List<FooEnum> theValues) {
void setTheValues(@Nullable List<FooEnum> theValues) {
this.theValues = theValues;
}
@@ -2040,13 +2084,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties(prefix = "test", ignoreUnknownFields = false)
static class WithCharArrayProperties {
private char[] chars;
private char @Nullable [] chars;
char[] getChars() {
char @Nullable [] getChars() {
return this.chars;
}
void setChars(char[] chars) {
void setChars(char @Nullable [] chars) {
this.chars = chars;
}
@@ -2056,23 +2100,23 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class WithRelaxedNamesProperties {
private String fooBar;
private @Nullable String fooBar;
private String barBAZ;
private @Nullable String barBAZ;
String getFooBar() {
@Nullable String getFooBar() {
return this.fooBar;
}
void setFooBar(String fooBar) {
void setFooBar(@Nullable String fooBar) {
this.fooBar = fooBar;
}
String getBarBAZ() {
@Nullable String getBarBAZ() {
return this.barBAZ;
}
void setBarBAZ(String barBAZ) {
void setBarBAZ(@Nullable String barBAZ) {
this.barBAZ = barBAZ;
}
@@ -2083,13 +2127,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class WithMapProperties {
private Map<String, String> map;
private @Nullable Map<String, String> map;
Map<String, String> getMap() {
@Nullable Map<String, String> getMap() {
return this.map;
}
void setMap(Map<String, String> map) {
void setMap(@Nullable Map<String, String> map) {
this.map = map;
}
@@ -2099,13 +2143,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class WithComplexMapProperties {
private Map<String, Map<String, String>> map;
private @Nullable Map<String, Map<String, String>> map;
Map<String, Map<String, String>> getMap() {
@Nullable Map<String, Map<String, String>> getMap() {
return this.map;
}
void setMap(Map<String, Map<String, String>> map) {
void setMap(@Nullable Map<String, Map<String, String>> map) {
this.map = map;
}
@@ -2115,13 +2159,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class WithIntegerMapProperties {
private Map<String, Map<Integer, Foo>> map;
private @Nullable Map<String, Map<Integer, Foo>> map;
Map<String, Map<Integer, Foo>> getMap() {
@Nullable Map<String, Map<Integer, Foo>> getMap() {
return this.map;
}
void setMap(Map<String, Map<Integer, Foo>> map) {
void setMap(@Nullable Map<String, Map<Integer, Foo>> map) {
this.map = map;
}
@@ -2133,13 +2177,13 @@ class ConfigurationPropertiesTests {
private int foo;
private String bar;
private @Nullable String bar;
String getBar() {
@Nullable String getBar() {
return this.bar;
}
void setBar(String bar) {
void setBar(@Nullable String bar) {
this.bar = bar;
}
@@ -2157,13 +2201,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class PersonProperties {
private Person person;
private @Nullable Person person;
Person getPerson() {
@Nullable Person getPerson() {
return this.person;
}
void setPerson(Person person) {
void setPerson(@Nullable Person person) {
this.person = person;
}
@@ -2173,23 +2217,23 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class PersonAndAlienProperties {
private Person person;
private @Nullable Person person;
private Alien alien;
private @Nullable Alien alien;
Person getPerson() {
@Nullable Person getPerson() {
return this.person;
}
void setPerson(Person person) {
void setPerson(@Nullable Person person) {
this.person = person;
}
Alien getAlien() {
@Nullable Alien getAlien() {
return this.alien;
}
void setAlien(Alien alien) {
void setAlien(@Nullable Alien alien) {
this.alien = alien;
}
@@ -2199,23 +2243,23 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class PersonAndAliensProperties {
private Person person;
private @Nullable Person person;
private List<Alien> aliens;
private @Nullable List<Alien> aliens;
Person getPerson() {
@Nullable Person getPerson() {
return this.person;
}
void setPerson(Person person) {
void setPerson(@Nullable Person person) {
this.person = person;
}
List<Alien> getAliens() {
@Nullable List<Alien> getAliens() {
return this.aliens;
}
void setAliens(List<Alien> aliens) {
void setAliens(@Nullable List<Alien> aliens) {
this.aliens = aliens;
}
@@ -2237,7 +2281,7 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties
static class ValidatorProperties implements Validator {
private String foo;
private @Nullable String foo;
@Override
public boolean supports(Class<?> type) {
@@ -2249,11 +2293,11 @@ class ConfigurationPropertiesTests {
ValidationUtils.rejectIfEmpty(errors, "foo", "TEST1");
}
String getFoo() {
@Nullable String getFoo() {
return this.foo;
}
void setFoo(String foo) {
void setFoo(@Nullable String foo) {
this.foo = foo;
}
@@ -2293,9 +2337,9 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class WithSetterThatThrowsValidationExceptionProperties {
private String foo;
private @Nullable String foo;
String getFoo() {
@Nullable String getFoo() {
return this.foo;
}
@@ -2311,13 +2355,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("custom")
static class WithCustomValidatorProperties {
private String foo;
private @Nullable String foo;
String getFoo() {
@Nullable String getFoo() {
return this.foo;
}
void setFoo(String foo) {
void setFoo(@Nullable String foo) {
this.foo = foo;
}
@@ -2327,13 +2371,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class ListOfGenericClassProperties {
private List<Class<? extends Throwable>> list;
private @Nullable List<Class<? extends Throwable>> list;
List<Class<? extends Throwable>> getList() {
@Nullable List<Class<? extends Throwable>> getList() {
return this.list;
}
void setList(List<Class<? extends Throwable>> list) {
void setList(@Nullable List<Class<? extends Throwable>> list) {
this.list = list;
}
@@ -2343,13 +2387,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class FileProperties {
private File file;
private @Nullable File file;
File getFile() {
@Nullable File getFile() {
return this.file;
}
void setFile(File file) {
void setFile(@Nullable File file) {
this.file = file;
}
@@ -2359,24 +2403,24 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class DataSizeProperties {
private DataSize size;
private @Nullable DataSize size;
@DataSizeUnit(DataUnit.KILOBYTES)
private DataSize anotherSize;
private @Nullable DataSize anotherSize;
DataSize getSize() {
@Nullable DataSize getSize() {
return this.size;
}
void setSize(DataSize size) {
void setSize(@Nullable DataSize size) {
this.size = size;
}
DataSize getAnotherSize() {
@Nullable DataSize getAnotherSize() {
return this.anotherSize;
}
void setAnotherSize(DataSize anotherSize) {
void setAnotherSize(@Nullable DataSize anotherSize) {
this.anotherSize = anotherSize;
}
@@ -2385,7 +2429,7 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class OtherInjectedProperties {
final DataSizeProperties dataSizeProperties;
final @Nullable DataSizeProperties dataSizeProperties;
OtherInjectedProperties(ObjectProvider<DataSizeProperties> dataSizeProperties) {
this.dataSizeProperties = dataSizeProperties.getIfUnique();
@@ -2578,6 +2622,7 @@ class ConfigurationPropertiesTests {
@Override
public Person convert(String source) {
String[] content = StringUtils.split(source, " ");
assertThat(content).isNotNull();
return new Person(content[0], content[1]);
}
@@ -2600,8 +2645,9 @@ class ConfigurationPropertiesTests {
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
String[] content = StringUtils.split((String) source, " ");
assertThat(content).isNotNull();
return new Person(content[0], content[1]);
}
@@ -2669,15 +2715,15 @@ class ConfigurationPropertiesTests {
static class Foo {
private String a;
private @Nullable String a;
private int b;
String getA() {
@Nullable String getA() {
return this.a;
}
void setA(String a) {
void setA(@Nullable String a) {
this.a = a;
}
@@ -2796,13 +2842,13 @@ class ConfigurationPropertiesTests {
static class Nested {
private Outer outer;
private @Nullable Outer outer;
Outer getOuter() {
@Nullable Outer getOuter() {
return this.outer;
}
void setOuter(Outer nested) {
void setOuter(@Nullable Outer nested) {
this.outer = nested;
}
@@ -2890,13 +2936,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class JavaBeanNestedConstructorBindingProperties {
private Nested nested;
private @Nullable Nested nested;
Nested getNested() {
@Nullable Nested getNested() {
return this.nested;
}
void setNested(Nested nested) {
void setNested(@Nullable Nested nested) {
this.nested = nested;
}
@@ -2926,13 +2972,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class JavaBeanNonDefaultConstructorProperties {
private Nested nested;
private @Nullable Nested nested;
Nested getNested() {
@Nullable Nested getNested() {
return this.nested;
}
void setNested(Nested nested) {
void setNested(@Nullable Nested nested) {
this.nested = nested;
}
@@ -3076,13 +3122,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class WithCustomConverterAndObjectToObjectMethodProperties {
private WithPublicObjectToObjectMethod item;
private @Nullable WithPublicObjectToObjectMethod item;
WithPublicObjectToObjectMethod getItem() {
@Nullable WithPublicObjectToObjectMethod getItem() {
return this.item;
}
void setItem(WithPublicObjectToObjectMethod item) {
void setItem(@Nullable WithPublicObjectToObjectMethod item) {
this.item = item;
}
@@ -3199,17 +3245,17 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class PotentiallyConstructorBoundProperties {
private String prop;
private @Nullable String prop;
PotentiallyConstructorBoundProperties(String notAProperty) {
}
String getProp() {
@Nullable String getProp() {
return this.prop;
}
void setProp(String prop) {
void setProp(@Nullable String prop) {
this.prop = prop;
}
@@ -3223,13 +3269,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class ResourceArrayProperties {
private Resource[] resources;
private Resource @Nullable [] resources;
Resource[] getResources() {
Resource @Nullable [] getResources() {
return this.resources;
}
void setResources(Resource[] resources) {
void setResources(Resource @Nullable [] resources) {
this.resources = resources;
}
@@ -3243,13 +3289,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class ResourceCollectionProperties {
private Collection<Resource> resources;
private @Nullable Collection<Resource> resources;
Collection<Resource> getResources() {
@Nullable Collection<Resource> getResources() {
return this.resources;
}
void setResources(Collection<Resource> resources) {
void setResources(@Nullable Collection<Resource> resources) {
this.resources = resources;
}
@@ -3311,13 +3357,13 @@ class ConfigurationPropertiesTests {
@ConfigurationProperties("test")
static class SetterBoundCustomListProperties {
private CustomList<String> values;
private @Nullable CustomList<String> values;
CustomList<String> getValues() {
@Nullable CustomList<String> getValues() {
return this.values;
}
void setValues(CustomList<String> values) {
void setValues(@Nullable CustomList<String> values) {
this.values = values;
}
@@ -70,6 +70,7 @@ class ConversionServiceDeducerTests {
applicationContext.getBeanFactory().setConversionService(conversionService);
ConversionServiceDeducer deducer = new ConversionServiceDeducer(applicationContext);
List<ConversionService> conversionServices = deducer.getConversionServices();
assertThat(conversionServices).isNotNull();
assertThat(conversionServices).containsOnly(conversionService);
assertThat(conversionServices.get(0)).isSameAs(conversionService);
}
@@ -106,6 +107,7 @@ class ConversionServiceDeducerTests {
ConversionServiceDeducer deducer = new ConversionServiceDeducer(applicationContext);
List<ConversionService> conversionServices = deducer.getConversionServices();
InputStream inputStream = new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8));
assertThat(conversionServices).isNotNull();
assertThat(conversionServices.get(0).convert(inputStream, String.class)).isEqualTo("test");
}
@@ -16,6 +16,7 @@
package org.springframework.boot.context.properties;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.diagnostics.FailureAnalysis;
@@ -32,13 +33,14 @@ class IncompatibleConfigurationFailureAnalyzerTests {
@Test
void incompatibleConfigurationListsKeys() {
FailureAnalysis failureAnalysis = performAnalysis("spring.first.key", "spring.second.key");
assertThat(failureAnalysis).isNotNull();
assertThat(failureAnalysis.getDescription()).contains(
"The following configuration properties have incompatible values: [spring.first.key, spring.second.key]");
assertThat(failureAnalysis.getAction())
.contains("Review the docs for spring.first.key, spring.second.key and change the configured values.");
}
private FailureAnalysis performAnalysis(String... keys) {
private @Nullable FailureAnalysis performAnalysis(String... keys) {
IncompatibleConfigurationException failure = new IncompatibleConfigurationException(keys);
return new IncompatibleConfigurationFailureAnalyzer().analyze(failure);
}
@@ -16,6 +16,8 @@
package org.springframework.boot.context.properties;
import org.jspecify.annotations.Nullable;
/**
* Class used to test multi-constructor binding. Must be public and have public
* constructors.
@@ -24,7 +26,7 @@ package org.springframework.boot.context.properties;
*/
public class MultiConstructorConfigurationProperties {
private String name;
private @Nullable String name;
private int age;
@@ -35,11 +37,11 @@ public class MultiConstructorConfigurationProperties {
this.name = name;
}
public String getName() {
public @Nullable String getName() {
return this.name;
}
public void setName(String name) {
public void setName(@Nullable String name) {
this.name = name;
}
@@ -16,6 +16,7 @@
package org.springframework.boot.context.properties;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.beans.FatalBeanException;
@@ -42,6 +43,7 @@ class NotConstructorBoundInjectionFailureAnalyzerTests {
void failureAnalysisForConfigurationPropertiesThatShouldHaveBeenConstructorBound() {
FailureAnalysis analysis = analyzeFailure(
createFailure(ShouldHaveUsedConstructorBindingPropertiesConfiguration.class));
assertThat(analysis).isNotNull();
assertThat(analysis.getDescription()).isEqualTo(ConstructorBoundProperties.class.getSimpleName()
+ " is annotated with @" + ConstructorBinding.class.getSimpleName()
+ " but it is defined as a regular bean which caused dependency injection to fail.");
@@ -57,7 +59,7 @@ class NotConstructorBoundInjectionFailureAnalyzerTests {
assertThat(analysis).isNull();
}
private FatalBeanException createFailure(Class<?> config) {
private @Nullable FatalBeanException createFailure(Class<?> config) {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
context.register(config);
context.refresh();
@@ -68,7 +70,7 @@ class NotConstructorBoundInjectionFailureAnalyzerTests {
}
}
private FailureAnalysis analyzeFailure(Exception failure) {
private @Nullable FailureAnalysis analyzeFailure(@Nullable Exception failure) {
assertThat(failure).isNotNull();
FailureAnalysis analysis = this.analyzer.analyze(failure);
if (analysis != null) {
@@ -101,18 +103,18 @@ class NotConstructorBoundInjectionFailureAnalyzerTests {
@ConfigurationProperties("test")
static class JavaBeanBoundProperties {
private String name;
private @Nullable String name;
@Autowired
JavaBeanBoundProperties(String dependency) {
}
String getName() {
@Nullable String getName() {
return this.name;
}
void setName(String name) {
void setName(@Nullable String name) {
this.name = name;
}
@@ -22,6 +22,7 @@ import java.util.function.Function;
import java.util.function.Supplier;
import org.assertj.core.api.Assertions;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -63,6 +64,7 @@ class PropertyMapperTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void fromWhenSupplierIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.map.from((Supplier<?>) null))
.withMessageContaining("'supplier' must not be null");
@@ -80,6 +82,7 @@ class PropertyMapperTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void toWhenConsumerIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.map.from(() -> "").to(null))
.withMessageContaining("'consumer' must not be null");
@@ -100,6 +103,7 @@ class PropertyMapperTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void asWhenAdapterIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.map.from(() -> "").as(null))
.withMessageContaining("'adapter' must not be null");
@@ -262,7 +266,10 @@ class PropertyMapperTests {
@Test
void asWhenNull() {
String value = this.map.from((String) null).always().as(String::valueOf).toInstance((string) -> string);
String value = this.map.from((String) null).always().as(String::valueOf).toInstance((string) -> {
assertThat(string).isNotNull();
return string;
});
assertThat(value).isEqualTo("null");
}
@@ -336,16 +343,16 @@ class PropertyMapperTests {
static class ExampleDest {
private String name;
private @Nullable String name;
boolean setNameCalled;
void setName(String name) {
void setName(@Nullable String name) {
this.name = name;
this.setNameCalled = true;
}
String getName() {
@Nullable String getName() {
return this.name;
}
@@ -355,21 +362,21 @@ class PropertyMapperTests {
private final String name;
private final Integer age;
private final @Nullable Integer age;
final boolean withAgeCalled;
Immutable(String name, Integer age) {
Immutable(String name, @Nullable Integer age) {
this(name, age, false);
}
private Immutable(String name, Integer age, boolean withAgeCalled) {
private Immutable(String name, @Nullable Integer age, boolean withAgeCalled) {
this.name = name;
this.age = age;
this.withAgeCalled = withAgeCalled;
}
Immutable withAge(Integer age) {
Immutable withAge(@Nullable Integer age) {
return new Immutable(this.name, age, true);
}
@@ -16,6 +16,8 @@
package org.springframework.boot.context.properties;
import org.jspecify.annotations.Nullable;
/**
* A {@link ConfigurationProperties @ConfigurationProperties} with an additional
* single-arg public constructor. Used in {@link ConfigurationPropertiesTests}.
@@ -25,7 +27,7 @@ package org.springframework.boot.context.properties;
@ConfigurationProperties("test")
public class WithPublicStringConstructorProperties {
private String a;
private @Nullable String a;
public WithPublicStringConstructorProperties() {
}
@@ -34,11 +36,11 @@ public class WithPublicStringConstructorProperties {
this.a = a;
}
public String getA() {
public @Nullable String getA() {
return this.a;
}
public void setA(String a) {
public void setA(@Nullable String a) {
this.a = a;
}
@@ -142,7 +142,9 @@ class ArrayBinderTests {
this.sources.add(source);
assertThatExceptionOfType(BindException.class).isThrownBy(() -> this.binder.bind("foo", INTEGER_ARRAY))
.satisfies((ex) -> {
Set<ConfigurationProperty> unbound = ((UnboundConfigurationPropertiesException) ex.getCause())
Throwable cause = ex.getCause();
assertThat(cause).isNotNull();
Set<ConfigurationProperty> unbound = ((UnboundConfigurationPropertiesException) cause)
.getUnboundProperties();
assertThat(unbound).hasSize(1);
ConfigurationProperty property = unbound.iterator().next();
@@ -18,6 +18,7 @@ package org.springframework.boot.context.properties.bind;
import java.util.Collections;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.core.env.StandardEnvironment;
@@ -60,13 +61,13 @@ class BackCompatibilityBinderIntegrationTests {
static class ExampleCamelCaseBean {
private String zkNodes;
private @Nullable String zkNodes;
String getZkNodes() {
@Nullable String getZkNodes() {
return this.zkNodes;
}
void setZkNodes(String zkNodes) {
void setZkNodes(@Nullable String zkNodes) {
this.zkNodes = zkNodes;
}
@@ -74,13 +75,13 @@ class BackCompatibilityBinderIntegrationTests {
static class PasswordProperties {
private String password;
private @Nullable String password;
String getPassword() {
@Nullable String getPassword() {
return this.password;
}
void setPassword(String password) {
void setPassword(@Nullable String password) {
this.password = password;
}
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
@@ -53,6 +54,7 @@ import static org.mockito.BDDMockito.then;
class BindConverterTests {
@Mock
@SuppressWarnings("NullAway.Init")
private Consumer<PropertyEditorRegistry> propertyEditorInitializer;
@Test
@@ -121,6 +123,7 @@ class BindConverterTests {
void convertWhenHasCustomEditorShouldConvert() {
BindConverter bindConverter = getPropertyEditorOnlyBindConverter(this::registerSampleTypeEditor);
SampleType converted = bindConverter.convert("test", ResolvableType.forClass(SampleType.class));
assertThat(converted).isNotNull();
assertThat(converted.getText()).isEqualTo("test");
}
@@ -128,6 +131,7 @@ class BindConverterTests {
void convertWhenHasEditorByConventionShouldConvert() {
BindConverter bindConverter = getPropertyEditorOnlyBindConverter(null);
ConventionType converted = bindConverter.convert("test", ResolvableType.forClass(ConventionType.class));
assertThat(converted).isNotNull();
assertThat(converted.getText()).isEqualTo("test");
}
@@ -144,6 +148,7 @@ class BindConverterTests {
void convertWhenHasEditorForArrayElementShouldConvert() {
BindConverter bindConverter = getPropertyEditorOnlyBindConverter(this::registerSampleTypeEditor);
SampleType[] converted = bindConverter.convert("test", ResolvableType.forClass(SampleType[].class));
assertThat(converted).isNotNull();
assertThat(converted).isNotEmpty();
assertThat(converted[0].getText()).isEqualTo("test");
}
@@ -152,6 +157,7 @@ class BindConverterTests {
void convertWhenConversionServiceCanConvertShouldConvert() {
BindConverter bindConverter = getBindConverter(new SampleTypeConverter());
SampleType converted = bindConverter.convert("test", ResolvableType.forClass(SampleType.class));
assertThat(converted).isNotNull();
assertThat(converted.getText()).isEqualTo("test");
}
@@ -169,6 +175,7 @@ class BindConverterTests {
BindConverter bindConverter = BindConverter.get(Collections.singletonList(new GenericConversionService()),
null);
File result = bindConverter.convert(".", ResolvableType.forClass(File.class));
assertThat(result).isNotNull();
assertThat(result.getPath()).isEqualTo(".");
}
@@ -177,6 +184,7 @@ class BindConverterTests {
BindConverter bindConverter = BindConverter.get(Collections.singletonList(new GenericConversionService()),
null);
Duration result = bindConverter.convert("10s", ResolvableType.forClass(Duration.class));
assertThat(result).isNotNull();
assertThat(result.getSeconds()).isEqualTo(10);
}
@@ -215,7 +223,7 @@ class BindConverterTests {
}
private BindConverter getPropertyEditorOnlyBindConverter(
Consumer<PropertyEditorRegistry> propertyEditorInitializer) {
@Nullable Consumer<PropertyEditorRegistry> propertyEditorInitializer) {
return BindConverter.get(Collections.singletonList(new ThrowingConversionService()), propertyEditorInitializer);
}
@@ -231,9 +239,9 @@ class BindConverterTests {
static class SampleType {
private String text;
private @Nullable String text;
String getText() {
@Nullable String getText() {
return this.text;
}
@@ -266,9 +274,9 @@ class BindConverterTests {
static class ConventionType {
private String text;
private @Nullable String text;
String getText() {
@Nullable String getText() {
return this.text;
}
@@ -291,22 +299,22 @@ class BindConverterTests {
static class ThrowingConversionService implements ConversionService {
@Override
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
public boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType) {
throw new AssertionError("Should not call conversion service");
}
@Override
public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
throw new AssertionError("Should not call conversion service");
}
@Override
public <T> T convert(Object source, Class<T> targetType) {
public <T> T convert(@Nullable Object source, Class<T> targetType) {
throw new AssertionError("Should not call conversion service");
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
public Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
throw new AssertionError("Should not call conversion service");
}
@@ -44,12 +44,15 @@ import static org.mockito.BDDMockito.then;
class BindResultTests {
@Mock
@SuppressWarnings("NullAway.Init")
private Consumer<String> consumer;
@Mock
@SuppressWarnings("NullAway.Init")
private Function<String, String> mapper;
@Mock
@SuppressWarnings("NullAway.Init")
private Supplier<String> supplier;
@Test
@@ -78,6 +81,7 @@ class BindResultTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void ifBoundWhenConsumerIsNullShouldThrowException() {
BindResult<String> result = BindResult.of("foo");
assertThatIllegalArgumentException().isThrownBy(() -> result.ifBound(null))
@@ -99,6 +103,7 @@ class BindResultTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void mapWhenMapperIsNullShouldThrowException() {
BindResult<String> result = BindResult.of("foo");
assertThatIllegalArgumentException().isThrownBy(() -> result.map(null))
@@ -25,6 +25,7 @@ import java.util.Map;
import java.util.function.Consumer;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.ExecutableHint;
@@ -295,7 +296,7 @@ class BindableRuntimeHintsRegistrarTests {
throws NoSuchMethodException, SecurityException {
Constructor<?> constructor = PoolProperties.InterceptorProperty.class.getConstructor(String.class,
String.class);
String[] parameterNames = new StandardReflectionParameterNameDiscoverer().getParameterNames(constructor);
@Nullable String[] parameterNames = new StandardReflectionParameterNameDiscoverer().getParameterNames(constructor);
assertThat(parameterNames).isNull();
assertThatNoException().isThrownBy(() -> registerHints(PoolProperties.class));
}
@@ -425,24 +426,24 @@ class BindableRuntimeHintsRegistrarTests {
public static class WithExternalNested {
private String name;
private @Nullable String name;
@NestedConfigurationProperty
private SampleType sampleType;
private @Nullable SampleType sampleType;
public String getName() {
public @Nullable String getName() {
return this.name;
}
public void setName(String name) {
public void setName(@Nullable String name) {
this.name = name;
}
public SampleType getSampleType() {
public @Nullable SampleType getSampleType() {
return this.sampleType;
}
public void setSampleType(SampleType sampleType) {
public void setSampleType(@Nullable SampleType sampleType) {
this.sampleType = sampleType;
}
@@ -451,13 +452,13 @@ class BindableRuntimeHintsRegistrarTests {
public static class WithRecursive {
@NestedConfigurationProperty
private Recursive recursive;
private @Nullable Recursive recursive;
public Recursive getRecursive() {
public @Nullable Recursive getRecursive() {
return this.recursive;
}
public void setRecursive(Recursive recursive) {
public void setRecursive(@Nullable Recursive recursive) {
this.recursive = recursive;
}
@@ -466,9 +467,9 @@ class BindableRuntimeHintsRegistrarTests {
public static class ImmutableWithRecursive {
@NestedConfigurationProperty
private final ImmutableRecursive recursive;
private final @Nullable ImmutableRecursive recursive;
ImmutableWithRecursive(ImmutableRecursive recursive) {
ImmutableWithRecursive(@Nullable ImmutableRecursive recursive) {
this.recursive = recursive;
}
@@ -476,8 +477,10 @@ class BindableRuntimeHintsRegistrarTests {
public static class WithWellKnownTypes implements ApplicationContextAware, EnvironmentAware {
@SuppressWarnings("NullAway.Init")
private ApplicationContext applicationContext;
@SuppressWarnings("NullAway.Init")
private Environment environment;
public ApplicationContext getApplicationContext() {
@@ -516,23 +519,23 @@ class BindableRuntimeHintsRegistrarTests {
public static class PackagePrivateGettersAndSetters {
private String alpha;
private @Nullable String alpha;
private Map<String, String> bravo;
private @Nullable Map<String, String> bravo;
String getAlpha() {
@Nullable String getAlpha() {
return this.alpha;
}
void setAlpha(String alpha) {
void setAlpha(@Nullable String alpha) {
this.alpha = alpha;
}
Map<String, String> getBravo() {
@Nullable Map<String, String> getBravo() {
return this.bravo;
}
void setBravo(Map<String, String> bravo) {
void setBravo(@Nullable Map<String, String> bravo) {
this.bravo = bravo;
}
@@ -563,13 +566,13 @@ class BindableRuntimeHintsRegistrarTests {
public static class Recursive {
private Recursive recursive;
private @Nullable Recursive recursive;
public Recursive getRecursive() {
public @Nullable Recursive getRecursive() {
return this.recursive;
}
public void setRecursive(Recursive recursive) {
public void setRecursive(@Nullable Recursive recursive) {
this.recursive = recursive;
}
@@ -578,9 +581,9 @@ class BindableRuntimeHintsRegistrarTests {
public static class ImmutableRecursive {
@SuppressWarnings("unused")
private final ImmutableRecursive recursive;
private final @Nullable ImmutableRecursive recursive;
ImmutableRecursive(ImmutableRecursive recursive) {
ImmutableRecursive(@Nullable ImmutableRecursive recursive) {
this.recursive = recursive;
}
@@ -589,13 +592,13 @@ class BindableRuntimeHintsRegistrarTests {
public static class WithCrossReference {
@NestedConfigurationProperty
private CrossReferenceA crossReferenceA;
private @Nullable CrossReferenceA crossReferenceA;
public void setCrossReferenceA(CrossReferenceA crossReferenceA) {
public void setCrossReferenceA(@Nullable CrossReferenceA crossReferenceA) {
this.crossReferenceA = crossReferenceA;
}
public CrossReferenceA getCrossReferenceA() {
public @Nullable CrossReferenceA getCrossReferenceA() {
return this.crossReferenceA;
}
@@ -604,13 +607,13 @@ class BindableRuntimeHintsRegistrarTests {
public static class CrossReferenceA {
@NestedConfigurationProperty
private CrossReferenceB crossReferenceB;
private @Nullable CrossReferenceB crossReferenceB;
public void setCrossReferenceB(CrossReferenceB crossReferenceB) {
public void setCrossReferenceB(@Nullable CrossReferenceB crossReferenceB) {
this.crossReferenceB = crossReferenceB;
}
public CrossReferenceB getCrossReferenceB() {
public @Nullable CrossReferenceB getCrossReferenceB() {
return this.crossReferenceB;
}
@@ -618,13 +621,13 @@ class BindableRuntimeHintsRegistrarTests {
public static class CrossReferenceB {
private CrossReferenceA crossReferenceA;
private @Nullable CrossReferenceA crossReferenceA;
public void setCrossReferenceA(CrossReferenceA crossReferenceA) {
public void setCrossReferenceA(@Nullable CrossReferenceA crossReferenceA) {
this.crossReferenceA = crossReferenceA;
}
public CrossReferenceA getCrossReferenceA() {
public @Nullable CrossReferenceA getCrossReferenceA() {
return this.crossReferenceA;
}
@@ -633,9 +636,9 @@ class BindableRuntimeHintsRegistrarTests {
public static class WithGeneric {
@NestedConfigurationProperty
private GenericObject<?> generic;
private @Nullable GenericObject<?> generic;
public GenericObject<?> getGeneric() {
public @Nullable GenericObject<?> getGeneric() {
return this.generic;
}
@@ -665,13 +668,13 @@ class BindableRuntimeHintsRegistrarTests {
public static class Nested {
private String field;
private @Nullable String field;
public String getField() {
public @Nullable String getField() {
return this.field;
}
public void setField(String field) {
public void setField(@Nullable String field) {
this.field = field;
}
@@ -697,13 +700,13 @@ class BindableRuntimeHintsRegistrarTests {
public static class Nested {
private String field;
private @Nullable String field;
public String getField() {
public @Nullable String getField() {
return this.field;
}
public void setField(String field) {
public void setField(@Nullable String field) {
this.field = field;
}
@@ -715,25 +718,25 @@ class BindableRuntimeHintsRegistrarTests {
public abstract static class BaseProperties {
private InheritedNested inheritedNested;
private @Nullable InheritedNested inheritedNested;
public InheritedNested getInheritedNested() {
public @Nullable InheritedNested getInheritedNested() {
return this.inheritedNested;
}
public void setInheritedNested(InheritedNested inheritedNested) {
public void setInheritedNested(@Nullable InheritedNested inheritedNested) {
this.inheritedNested = inheritedNested;
}
public static class InheritedNested {
private String alpha;
private @Nullable String alpha;
public String getAlpha() {
public @Nullable String getAlpha() {
return this.alpha;
}
public void setAlpha(String alpha) {
public void setAlpha(@Nullable String alpha) {
this.alpha = alpha;
}
@@ -743,13 +746,13 @@ class BindableRuntimeHintsRegistrarTests {
public static class ExtendingProperties extends BaseProperties {
private String bravo;
private @Nullable String bravo;
public String getBravo() {
public @Nullable String getBravo() {
return this.bravo;
}
public void setBravo(String bravo) {
public void setBravo(@Nullable String bravo) {
this.bravo = bravo;
}
@@ -19,6 +19,7 @@ package org.springframework.boot.context.properties.bind;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
@@ -41,12 +42,14 @@ import static org.mockito.Mockito.mock;
class BindableTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void ofClassWhenTypeIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> Bindable.of((Class<?>) null))
.withMessageContaining("'type' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void ofTypeWhenTypeIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> Bindable.of((ResolvableType) null))
.withMessageContaining("'type' must not be null");
@@ -68,18 +71,23 @@ class BindableTests {
String instance = "foo";
ResolvableType type = ResolvableType.forClass(String.class);
assertThat(Bindable.ofInstance(instance).getType()).isEqualTo(type);
assertThat(Bindable.ofInstance(instance).getValue().get()).isEqualTo("foo");
Supplier<String> value = Bindable.ofInstance(instance).getValue();
assertThat(value).isNotNull();
assertThat(value.get()).isEqualTo("foo");
}
@Test
void ofClassWithExistingValueShouldSetTypeAndExistingValue() {
assertThat(Bindable.of(String.class).withExistingValue("foo").getValue().get()).isEqualTo("foo");
Supplier<String> value = Bindable.of(String.class).withExistingValue("foo").getValue();
assertThat(value).isNotNull();
assertThat(value.get()).isEqualTo("foo");
}
@Test
void ofTypeWithExistingValueShouldSetTypeAndExistingValue() {
assertThat(Bindable.of(ResolvableType.forClass(String.class)).withExistingValue("foo").getValue().get())
.isEqualTo("foo");
Supplier<Object> value = Bindable.of(ResolvableType.forClass(String.class)).withExistingValue("foo").getValue();
assertThat(value).isNotNull();
assertThat(value.get()).isEqualTo("foo");
}
@Test
@@ -93,7 +101,9 @@ class BindableTests {
void ofTypeWhenPrimitiveWithExistingValueWrapperShouldNotThrowException() {
Bindable<Integer> bindable = Bindable.<Integer>of(ResolvableType.forClass(int.class)).withExistingValue(123);
assertThat(bindable.getType().resolve()).isEqualTo(int.class);
assertThat(bindable.getValue().get()).isEqualTo(123);
Supplier<Integer> value = bindable.getValue();
assertThat(value).isNotNull();
assertThat(value.get()).isEqualTo(123);
}
@Test
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import jakarta.validation.Validation;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
@@ -71,12 +72,14 @@ class BinderTests {
private Binder binder = new Binder(this.sources);
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenSourcesIsNullArrayShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new Binder((ConfigurationPropertySource[]) null))
.withMessageContaining("'sources' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenSourcesIsNullIterableShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new Binder((Iterable<ConfigurationPropertySource>) null))
.withMessageContaining("'sources' must not be null");
@@ -95,6 +98,7 @@ class BinderTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void bindWhenNameIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.binder.bind((ConfigurationPropertyName) null, Bindable.of(String.class),
@@ -103,6 +107,7 @@ class BinderTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void bindWhenTargetIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.binder.bind(ConfigurationPropertyName.of("foo"), null, BindHandler.DEFAULT))
@@ -268,7 +273,7 @@ class BinderTests {
ConfigurationPropertySources.from(new PropertySource<String>("test") {
@Override
public Object getProperty(String name) {
public @Nullable Object getProperty(String name) {
return null;
}
@@ -301,7 +306,7 @@ class BinderTests {
Map<String, Object> source = new HashMap<>();
source.put("value", "hello");
source.put("", "bar");
Iterable<ConfigurationPropertySource> propertySources = ConfigurationPropertySources
Iterable<@Nullable ConfigurationPropertySource> propertySources = ConfigurationPropertySources
.from(new MapPropertySource("test", source));
propertySources.forEach(this.sources::add);
Bindable<JavaBean> target = Bindable.of(JavaBean.class);
@@ -330,7 +335,8 @@ class BinderTests {
BindResult<JavaBean> result = this.binder.bind("foo", Bindable.of(JavaBean.class), new BindHandler() {
@Override
public <T> Bindable<T> onStart(ConfigurationPropertyName name, Bindable<T> target, BindContext context) {
public <T> @Nullable Bindable<T> onStart(ConfigurationPropertyName name, Bindable<T> target,
BindContext context) {
return null;
}
@@ -372,15 +378,15 @@ class BinderTests {
static class JavaBean {
private String value;
private @Nullable String value;
private final List<String> items = Collections.emptyList();
String getValue() {
@Nullable String getValue() {
return this.value;
}
void setValue(String value) {
void setValue(@Nullable String value) {
this.value = value;
}
@@ -433,13 +439,13 @@ class BinderTests {
@Validated
static class ResourceBean {
private Resource resource;
private @Nullable Resource resource;
Resource getResource() {
@Nullable Resource getResource() {
return this.resource;
}
void setResource(Resource resource) {
void setResource(@Nullable Resource resource) {
this.resource = resource;
}
@@ -447,13 +453,13 @@ class BinderTests {
static class CycleBean1 {
private CycleBean2 two;
private @Nullable CycleBean2 two;
CycleBean2 getTwo() {
@Nullable CycleBean2 getTwo() {
return this.two;
}
void setTwo(CycleBean2 two) {
void setTwo(@Nullable CycleBean2 two) {
this.two = two;
}
@@ -461,13 +467,13 @@ class BinderTests {
static class CycleBean2 {
private CycleBean1 one;
private @Nullable CycleBean1 one;
CycleBean1 getOne() {
@Nullable CycleBean1 getOne() {
return this.one;
}
void setOne(CycleBean1 one) {
void setOne(@Nullable CycleBean1 one) {
this.one = one;
}
@@ -475,13 +481,13 @@ class BinderTests {
static class GenericBean<T> {
private T bar;
private @Nullable T bar;
T getBar() {
@Nullable T getBar() {
return this.bar;
}
void setBar(T bar) {
void setBar(@Nullable T bar) {
this.bar = bar;
}
@@ -49,6 +49,7 @@ class BoundPropertiesTrackingBindHandlerTests {
private Binder binder;
@Mock
@SuppressWarnings("NullAway.Init")
private Consumer<ConfigurationProperty> consumer;
@BeforeEach
@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.properties.bind.BinderTests.ExampleEnum;
@@ -117,7 +118,9 @@ class CollectionBinderTests {
this.sources.add(source);
assertThatExceptionOfType(BindException.class).isThrownBy(() -> this.binder.bind("foo", INTEGER_LIST))
.satisfies((ex) -> {
Set<ConfigurationProperty> unbound = ((UnboundConfigurationPropertiesException) ex.getCause())
Throwable cause = ex.getCause();
assertThat(cause).isNotNull();
Set<ConfigurationProperty> unbound = ((UnboundConfigurationPropertiesException) cause)
.getUnboundProperties();
assertThat(unbound).singleElement().satisfies((property) -> {
assertThat(property.getName()).hasToString("foo[3]");
@@ -137,7 +140,9 @@ class CollectionBinderTests {
assertThatExceptionOfType(BindException.class)
.isThrownBy(() -> this.binder.bind("foo", Bindable.listOf(Name.class)))
.satisfies((ex) -> {
Set<ConfigurationProperty> unbound = ((UnboundConfigurationPropertiesException) ex.getCause())
Throwable cause = ex.getCause();
assertThat(cause).isNotNull();
Set<ConfigurationProperty> unbound = ((UnboundConfigurationPropertiesException) cause)
.getUnboundProperties();
assertThat(unbound).singleElement().satisfies((property) -> {
assertThat(property.getName()).hasToString("foo[1].missing");
@@ -171,7 +176,9 @@ class CollectionBinderTests {
Bindable<List<JavaBean>> target = Bindable.listOf(JavaBean.class);
assertThatExceptionOfType(BindException.class).isThrownBy(() -> this.binder.bind("foo", target))
.satisfies((ex) -> {
Set<ConfigurationProperty> unbound = ((UnboundConfigurationPropertiesException) ex.getCause())
Throwable cause = ex.getCause();
assertThat(cause).isNotNull();
Set<ConfigurationProperty> unbound = ((UnboundConfigurationPropertiesException) cause)
.getUnboundProperties();
assertThat(unbound).singleElement().satisfies((property) -> {
assertThat(property.getName()).hasToString("foo[4].value");
@@ -394,8 +401,10 @@ class CollectionBinderTests {
Bindable<BeanWithNestedCollection> target = Bindable.of(BeanWithNestedCollection.class);
BeanWithNestedCollection foo = this.binder.bind("foo", target).get();
assertThat(foo.getValue()).isEqualTo("one");
assertThat(foo.getFoos().get(0).getValue()).isEqualTo("two");
assertThat(foo.getFoos().get(1).getValue()).isEqualTo("three");
List<BeanWithNestedCollection> foos = foo.getFoos();
assertThat(foos).isNotNull();
assertThat(foos.get(0).getValue()).isEqualTo("two");
assertThat(foos.get(1).getValue()).isEqualTo("three");
}
@Test
@@ -465,7 +474,9 @@ class CollectionBinderTests {
source.put("foo.values[0]", "foo-bar,bar-baz");
this.sources.add(source);
BeanWithEnumSetCollection result = this.binder.bind("foo", Bindable.of(BeanWithEnumSetCollection.class)).get();
assertThat(result.getValues().get(0)).containsExactly(ExampleEnum.FOO_BAR, ExampleEnum.BAR_BAZ);
List<EnumSet<ExampleEnum>> values = result.getValues();
assertThat(values).isNotNull();
assertThat(values.get(0)).containsExactly(ExampleEnum.FOO_BAR, ExampleEnum.BAR_BAZ);
}
@Test
@@ -504,7 +515,7 @@ class CollectionBinderTests {
private Set<String> itemsSet = new LinkedHashSet<>();
private String string;
private @Nullable String string;
List<String> getItems() {
return this.items;
@@ -522,11 +533,11 @@ class CollectionBinderTests {
this.itemsSet = itemsSet;
}
String getString() {
@Nullable String getString() {
return this.string;
}
void setString(String string) {
void setString(@Nullable String string) {
this.string = string;
}
@@ -576,23 +587,23 @@ class CollectionBinderTests {
static class BeanWithNestedCollection {
private String value;
private @Nullable String value;
private List<BeanWithNestedCollection> foos;
private @Nullable List<BeanWithNestedCollection> foos;
List<BeanWithNestedCollection> getFoos() {
@Nullable List<BeanWithNestedCollection> getFoos() {
return this.foos;
}
void setFoos(List<BeanWithNestedCollection> foos) {
void setFoos(@Nullable List<BeanWithNestedCollection> foos) {
this.foos = foos;
}
String getValue() {
@Nullable String getValue() {
return this.value;
}
void setValue(String value) {
void setValue(@Nullable String value) {
this.value = value;
}
@@ -600,13 +611,13 @@ class CollectionBinderTests {
static class ClonedArrayBean {
private String[] bar;
private String @Nullable [] bar;
String[] getBar() {
return this.bar.clone();
String @Nullable [] getBar() {
return (this.bar != null) ? this.bar.clone() : null;
}
void setBar(String[] bar) {
void setBar(String @Nullable [] bar) {
this.bar = bar;
}
@@ -614,13 +625,13 @@ class CollectionBinderTests {
static class BeanWithGetterException {
private List<String> values;
private @Nullable List<String> values;
void setValues(List<String> values) {
void setValues(@Nullable List<String> values) {
this.values = values;
}
List<String> getValues() {
@Nullable List<String> getValues() {
return Collections.unmodifiableList(this.values);
}
@@ -628,13 +639,13 @@ class CollectionBinderTests {
static class BeanWithEnumSetCollection {
private List<EnumSet<ExampleEnum>> values;
private @Nullable List<EnumSet<ExampleEnum>> values;
void setValues(List<EnumSet<ExampleEnum>> values) {
void setValues(@Nullable List<EnumSet<ExampleEnum>> values) {
this.values = values;
}
List<EnumSet<ExampleEnum>> getValues() {
@Nullable List<EnumSet<ExampleEnum>> getValues() {
return this.values;
}
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.properties.bind.JavaBeanBinder.Bean;
@@ -271,8 +272,10 @@ class JavaBeanBinderTests {
source.put("foo.value-bean.string-value", "foo");
this.sources.add(source);
ExampleNestedBean bean = this.binder.bind("foo", Bindable.of(ExampleNestedBean.class)).get();
assertThat(bean.getValueBean().getIntValue()).isEqualTo(123);
assertThat(bean.getValueBean().getStringValue()).isEqualTo("foo");
ExampleValueBean valueBean = bean.getValueBean();
assertThat(valueBean).isNotNull();
assertThat(valueBean.getIntValue()).isEqualTo(123);
assertThat(valueBean.getStringValue()).isEqualTo("foo");
}
@Test
@@ -505,8 +508,12 @@ class JavaBeanBinderTests {
source.put("foo.booleans[b].value", "true");
this.sources.add(source);
ExampleWithGenericMap bean = this.binder.bind("foo", Bindable.of(ExampleWithGenericMap.class)).get();
assertThat(bean.getIntegers().get("a").getValue()).isOne();
assertThat(bean.getBooleans().get("b").getValue()).isTrue();
GenericValue<Integer> a = bean.getIntegers().get("a");
assertThat(a).isNotNull();
assertThat(a.getValue()).isOne();
GenericValue<Boolean> b = bean.getBooleans().get("b");
assertThat(b).isNotNull();
assertThat(b.getValue()).isTrue();
}
@Test
@@ -524,7 +531,9 @@ class JavaBeanBinderTests {
void beanPropertiesPreferMatchingType() {
// gh-16206
ResolvableType type = ResolvableType.forClass(PropertyWithOverloadedSetter.class);
Bean<PropertyWithOverloadedSetter> bean = new Bean<>(type, type.resolve()) {
Class<?> resolvedType = type.resolve();
assertThat(resolvedType).isNotNull();
Bean<PropertyWithOverloadedSetter> bean = new Bean<>(type, resolvedType) {
@Override
protected void addProperties(Method[] declaredMethods, Field[] declaredFields) {
@@ -553,6 +562,7 @@ class JavaBeanBinderTests {
};
BeanProperty property = bean.getProperties().get("property");
assertThat(property).isNotNull();
PropertyWithOverloadedSetter target = new PropertyWithOverloadedSetter();
property.setValue(() -> target, "some string");
}
@@ -621,9 +631,9 @@ class JavaBeanBinderTests {
private long longValue;
private String stringValue;
private @Nullable String stringValue;
private ExampleEnum enumValue;
private @Nullable ExampleEnum enumValue;
int getIntValue() {
return this.intValue;
@@ -641,19 +651,19 @@ class JavaBeanBinderTests {
this.longValue = longValue;
}
String getStringValue() {
@Nullable String getStringValue() {
return this.stringValue;
}
void setStringValue(String stringValue) {
void setStringValue(@Nullable String stringValue) {
this.stringValue = stringValue;
}
ExampleEnum getEnumValue() {
@Nullable ExampleEnum getEnumValue() {
return this.enumValue;
}
void setEnumValue(ExampleEnum enumValue) {
void setEnumValue(@Nullable ExampleEnum enumValue) {
this.enumValue = enumValue;
}
@@ -662,13 +672,13 @@ class JavaBeanBinderTests {
static class ExampleRenamedPropertyBean {
@Name("public")
private String exampleProperty;
private @Nullable String exampleProperty;
String getExampleProperty() {
@Nullable String getExampleProperty() {
return this.exampleProperty;
}
void setExampleProperty(String exampleProperty) {
void setExampleProperty(@Nullable String exampleProperty) {
this.exampleProperty = exampleProperty;
}
@@ -700,13 +710,13 @@ class JavaBeanBinderTests {
static class ExampleMapBean {
private Map<ExampleEnum, Integer> map;
private @Nullable Map<ExampleEnum, Integer> map;
Map<ExampleEnum, Integer> getMap() {
@Nullable Map<ExampleEnum, Integer> getMap() {
return this.map;
}
void setMap(Map<ExampleEnum, Integer> map) {
void setMap(@Nullable Map<ExampleEnum, Integer> map) {
this.map = map;
}
@@ -714,13 +724,13 @@ class JavaBeanBinderTests {
static class ExampleListBean {
private List<ExampleEnum> list;
private @Nullable List<ExampleEnum> list;
List<ExampleEnum> getList() {
@Nullable List<ExampleEnum> getList() {
return this.list;
}
void setList(List<ExampleEnum> list) {
void setList(@Nullable List<ExampleEnum> list) {
this.list = list;
}
@@ -728,13 +738,13 @@ class JavaBeanBinderTests {
static class ExampleSetBean {
private Set<ExampleEnum> set;
private @Nullable Set<ExampleEnum> set;
Set<ExampleEnum> getSet() {
@Nullable Set<ExampleEnum> getSet() {
return this.set;
}
void setSet(Set<ExampleEnum> set) {
void setSet(@Nullable Set<ExampleEnum> set) {
this.set = set;
}
@@ -742,13 +752,13 @@ class JavaBeanBinderTests {
static class ExampleCollectionBean {
private Collection<ExampleEnum> collection;
private @Nullable Collection<ExampleEnum> collection;
Collection<ExampleEnum> getCollection() {
@Nullable Collection<ExampleEnum> getCollection() {
return this.collection;
}
void setCollection(Collection<ExampleEnum> collection) {
void setCollection(@Nullable Collection<ExampleEnum> collection) {
this.collection = collection;
}
@@ -797,13 +807,13 @@ class JavaBeanBinderTests {
static class ExampleCollectionBeanWithDelimiter {
@Delimiter("|")
private Collection<ExampleEnum> collection;
private @Nullable Collection<ExampleEnum> collection;
Collection<ExampleEnum> getCollection() {
@Nullable Collection<ExampleEnum> getCollection() {
return this.collection;
}
void setCollection(Collection<ExampleEnum> collection) {
void setCollection(@Nullable Collection<ExampleEnum> collection) {
this.collection = collection;
}
@@ -811,13 +821,13 @@ class JavaBeanBinderTests {
static class ExampleNestedBean {
private ExampleValueBean valueBean;
private @Nullable ExampleValueBean valueBean;
ExampleValueBean getValueBean() {
@Nullable ExampleValueBean getValueBean() {
return this.valueBean;
}
void setValueBean(ExampleValueBean valueBean) {
void setValueBean(@Nullable ExampleValueBean valueBean) {
this.valueBean = valueBean;
}
@@ -863,14 +873,14 @@ class JavaBeanBinderTests {
static class ExampleNestedSubclassBean extends ExampleNestedBean {
private ExampleValueSubclassBean valueBean;
private @Nullable ExampleValueSubclassBean valueBean;
@Override
ExampleValueSubclassBean getValueBean() {
@Nullable ExampleValueSubclassBean getValueBean() {
return this.valueBean;
}
void setValueBean(ExampleValueSubclassBean valueBean) {
void setValueBean(@Nullable ExampleValueSubclassBean valueBean) {
this.valueBean = valueBean;
}
@@ -892,17 +902,17 @@ class JavaBeanBinderTests {
static class ExampleWithNonDefaultConstructor {
private String value;
private @Nullable String value;
ExampleWithNonDefaultConstructor(String value) {
ExampleWithNonDefaultConstructor(@Nullable String value) {
this.value = value;
}
String getValue() {
@Nullable String getValue() {
return this.value;
}
void setValue(String value) {
void setValue(@Nullable String value) {
this.value = value;
}
@@ -976,7 +986,7 @@ class JavaBeanBinderTests {
private int value;
private ExampleWithSelfReference self;
private @Nullable ExampleWithSelfReference self;
int getValue() {
return this.value;
@@ -986,11 +996,11 @@ class JavaBeanBinderTests {
this.value = value;
}
ExampleWithSelfReference getSelf() {
@Nullable ExampleWithSelfReference getSelf() {
return this.self;
}
void setSelf(ExampleWithSelfReference self) {
void setSelf(@Nullable ExampleWithSelfReference self) {
this.self = self;
}
@@ -998,13 +1008,13 @@ class JavaBeanBinderTests {
static class ExampleWithInvalidAccessors {
private String name;
private @Nullable String name;
String getName() {
@Nullable String getName() {
return this.name;
}
void setName(String name) {
void setName(@Nullable String name) {
this.name = name;
}
@@ -1020,15 +1030,15 @@ class JavaBeanBinderTests {
static class ExampleWithStaticAccessors {
private static String name;
private static @Nullable String name;
private int counter;
static String getName() {
static @Nullable String getName() {
return name;
}
static void setName(String name) {
static void setName(@Nullable String name) {
ExampleWithStaticAccessors.name = name;
}
@@ -1053,13 +1063,13 @@ class JavaBeanBinderTests {
static class ConverterAnnotatedExampleBean {
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate date;
private @Nullable LocalDate date;
LocalDate getDate() {
@Nullable LocalDate getDate() {
return this.date;
}
void setDate(LocalDate date) {
void setDate(@Nullable LocalDate date) {
this.date = date;
}
@@ -1067,13 +1077,13 @@ class JavaBeanBinderTests {
static class ExampleWithPropertyEditorType {
private Class<? extends Throwable> value;
private @Nullable Class<? extends Throwable> value;
Class<? extends Throwable> getValue() {
@Nullable Class<? extends Throwable> getValue() {
return this.value;
}
void setValue(Class<? extends Throwable> value) {
void setValue(@Nullable Class<? extends Throwable> value) {
this.value = value;
}
@@ -1097,13 +1107,13 @@ class JavaBeanBinderTests {
static class GenericValue<T> {
private T value;
private @Nullable T value;
T getValue() {
@Nullable T getValue() {
return this.value;
}
void setValue(T value) {
void setValue(@Nullable T value) {
this.value = value;
}
@@ -1111,17 +1121,17 @@ class JavaBeanBinderTests {
static class PropertyWithOverloadedSetter {
private String property;
private @Nullable String property;
void setProperty(int property) {
this.property = String.valueOf(property);
}
void setProperty(String property) {
void setProperty(@Nullable String property) {
this.property = property;
}
String getProperty() {
@Nullable String getProperty() {
return this.property;
}
@@ -1143,13 +1153,13 @@ class JavaBeanBinderTests {
static class PackagePrivateSetterBean {
private String property;
private @Nullable String property;
String getProperty() {
@Nullable String getProperty() {
return this.property;
}
void setProperty(String property) {
void setProperty(@Nullable String property) {
this.property = property;
}
@@ -1225,13 +1235,13 @@ class JavaBeanBinderTests {
static class BridgeMethodsBase<T extends BridgeBaseType> {
private T value;
private @Nullable T value;
T getValue() {
@Nullable T getValue() {
return this.value;
}
void setValue(T value) {
void setValue(@Nullable T value) {
this.value = value;
}
@@ -1240,7 +1250,7 @@ class JavaBeanBinderTests {
static class BridgeMethods extends BridgeMethodsBase<BridgeType> {
@Override
BridgeType getValue() {
@Nullable BridgeType getValue() {
return super.getValue();
}
@@ -16,6 +16,8 @@
package org.springframework.boot.context.properties.bind;
import org.jspecify.annotations.Nullable;
/**
* Java bean with an additional public single-arg constructor.
*
@@ -23,7 +25,7 @@ package org.springframework.boot.context.properties.bind;
*/
public class JavaBeanWithPublicConstructor {
private String value;
private @Nullable String value;
public JavaBeanWithPublicConstructor() {
}
@@ -32,11 +34,11 @@ public class JavaBeanWithPublicConstructor {
setValue(value);
}
public String getValue() {
public @Nullable String getValue() {
return this.value;
}
public void setValue(String value) {
public void setValue(@Nullable String value) {
this.value = value;
}
@@ -29,6 +29,7 @@ import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
@@ -369,7 +370,9 @@ class MapBinderTests {
source.put("foo.bar[2].value", "c");
this.sources.add(source);
Map<String, List<JavaBean>> map = this.binder.bind("foo", target).get();
List<String> values = map.get("bar").stream().map(JavaBean::getValue).toList();
List<JavaBean> bar = map.get("bar");
assertThat(bar).isNotNull();
List<String> values = bar.stream().map(JavaBean::getValue).toList();
assertThat(values).containsExactly("a", "b", "c");
}
@@ -387,7 +390,9 @@ class MapBinderTests {
this.sources.add(new MockConfigurationPropertySource("foo.bar.pattern", "1", "line1"));
Bindable<Map<String, Foo>> target = Bindable.mapOf(String.class, Foo.class);
Map<String, Foo> map = this.binder.bind("foo", target).get();
assertThat(map.get("bar").getPattern()).isEqualTo("1");
Foo bar = map.get("bar");
assertThat(bar).isNotNull();
assertThat(bar.getPattern()).isEqualTo("1");
}
@Test
@@ -434,7 +439,9 @@ class MapBinderTests {
mockSource.put("foo.bar.baz[2].value", "c");
this.sources.add(mockSource);
Map<String, List<JavaBean>> map = this.binder.bind("foo", target).get();
List<String> values = map.get("bar.baz").stream().map(JavaBean::getValue).toList();
List<JavaBean> barBaz = map.get("bar.baz");
assertThat(barBaz).isNotNull();
List<String> values = barBaz.stream().map(JavaBean::getValue).toList();
assertThat(values).containsExactly("a", "b", "c");
}
@@ -495,8 +502,12 @@ class MapBinderTests {
this.sources.add(source);
BindResult<NestableFoo> foo = this.binder.bind("foo", NestableFoo.class);
assertThat(foo.get().getValue()).isNotNull();
assertThat(foo.get().getFoos().get("foo1").getValue()).isEqualTo("two");
assertThat(foo.get().getFoos().get("foo2").getValue()).isEqualTo("three");
NestableFoo foo1 = foo.get().getFoos().get("foo1");
assertThat(foo1).isNotNull();
assertThat(foo1.getValue()).isEqualTo("two");
NestableFoo foo2 = foo.get().getFoos().get("foo2");
assertThat(foo2).isNotNull();
assertThat(foo2.getValue()).isEqualTo("three");
}
@Test
@@ -611,8 +622,11 @@ class MapBinderTests {
source.put("foo.addresses.localhost[1]", "127.0.0.2");
this.sources.add(source);
MapWithWildcardProperties result = this.binder.bind("foo", Bindable.of(MapWithWildcardProperties.class)).get();
assertThat(result.getAddresses().get("localhost").stream().map(InetAddress::getHostAddress))
.containsExactly("127.0.0.1", "127.0.0.2");
Map<String, ? extends List<? extends InetAddress>> addresses = result.getAddresses();
assertThat(addresses).isNotNull();
List<? extends InetAddress> localhost = addresses.get("localhost");
assertThat(localhost).isNotNull();
assertThat(localhost.stream().map(InetAddress::getHostAddress)).containsExactly("127.0.0.1", "127.0.0.2");
}
@Test
@@ -670,20 +684,20 @@ class MapBinderTests {
static class Foo {
private String pattern;
private @Nullable String pattern;
Foo() {
}
Foo(String pattern) {
Foo(@Nullable String pattern) {
this.pattern = pattern;
}
String getPattern() {
@Nullable String getPattern() {
return this.pattern;
}
void setPattern(String pattern) {
void setPattern(@Nullable String pattern) {
this.pattern = pattern;
}
@@ -693,17 +707,17 @@ class MapBinderTests {
private final Map<String, NestableFoo> foos = new LinkedHashMap<>();
private String value;
private @Nullable String value;
Map<String, NestableFoo> getFoos() {
return this.foos;
}
String getValue() {
@Nullable String getValue() {
return this.value;
}
void setValue(String value) {
void setValue(@Nullable String value) {
this.value = value;
}
@@ -762,13 +776,13 @@ class MapBinderTests {
static class BeanWithGetterException {
private Map<String, String> values;
private @Nullable Map<String, String> values;
void setValues(Map<String, String> values) {
void setValues(@Nullable Map<String, String> values) {
this.values = values;
}
Map<String, String> getValues() {
@Nullable Map<String, String> getValues() {
return Collections.unmodifiableMap(this.values);
}
@@ -776,13 +790,13 @@ class MapBinderTests {
static class MapWithWildcardProperties {
private Map<String, ? extends List<? extends InetAddress>> addresses;
private @Nullable Map<String, ? extends List<? extends InetAddress>> addresses;
Map<String, ? extends List<? extends InetAddress>> getAddresses() {
@Nullable Map<String, ? extends List<? extends InetAddress>> getAddresses() {
return this.addresses;
}
void setAddresses(Map<String, ? extends List<? extends InetAddress>> addresses) {
void setAddresses(@Nullable Map<String, ? extends List<? extends InetAddress>> addresses) {
this.addresses = addresses;
}
@@ -19,6 +19,7 @@ package org.springframework.boot.context.properties.bind;
import java.util.HashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.core.env.Environment;
@@ -38,9 +39,10 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
*/
class PropertySourcesPlaceholdersResolverTests {
private PropertySourcesPlaceholdersResolver resolver;
private @Nullable PropertySourcesPlaceholdersResolver resolver;
@Test
@SuppressWarnings("NullAway") // Test null check
void placeholderResolverIfEnvironmentNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new PropertySourcesPlaceholdersResolver((Environment) null))
@@ -28,6 +28,7 @@ import java.util.Optional;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.internal.CharacterIndex;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
@@ -733,9 +734,9 @@ class ValueObjectBinderTests {
static class NestedJavaBean {
private String value;
private @Nullable String value;
String getValue() {
@Nullable String getValue() {
return this.value;
}
@@ -903,23 +904,23 @@ class ValueObjectBinderTests {
static class NonExtractableParameterName {
private String value;
private @Nullable String value;
private JsonPath jsonPath;
private @Nullable JsonPath jsonPath;
String getValue() {
@Nullable String getValue() {
return this.value;
}
void setValue(String value) {
void setValue(@Nullable String value) {
this.value = value;
}
JsonPath getJsonPath() {
@Nullable JsonPath getJsonPath() {
return this.jsonPath;
}
void setJsonPath(JsonPath jsonPath) {
void setJsonPath(@Nullable JsonPath jsonPath) {
this.jsonPath = jsonPath;
}
@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -89,7 +90,7 @@ class IgnoreTopLevelConverterNotFoundBindHandlerTests {
private int foo;
private Map<String, String> map;
private @Nullable Map<String, String> map;
int getFoo() {
return this.foo;
@@ -99,11 +100,11 @@ class IgnoreTopLevelConverterNotFoundBindHandlerTests {
throw new IllegalStateException();
}
Map<String, String> getMap() {
@Nullable Map<String, String> getMap() {
return this.map;
}
void setMap(Map<String, String> map) {
void setMap(@Nullable Map<String, String> map) {
this.map = map;
}
@@ -19,6 +19,7 @@ package org.springframework.boot.context.properties.bind.handler;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.properties.bind.BindException;
@@ -42,7 +43,7 @@ class NoUnboundElementsBindHandlerTests {
private final List<ConfigurationPropertySource> sources = new ArrayList<>();
private Binder binder;
private @Nullable Binder binder;
@Test
void bindWhenNotUsingNoUnboundElementsHandlerShouldBind() {
@@ -73,11 +74,14 @@ class NoUnboundElementsBindHandlerTests {
source.put("example.baz", "bar");
this.sources.add(source);
this.binder = new Binder(this.sources);
assertThatExceptionOfType(BindException.class)
.isThrownBy(
() -> this.binder.bind("example", Bindable.of(Example.class), new NoUnboundElementsBindHandler()))
.satisfies((ex) -> assertThat(ex.getCause().getMessage())
.contains("The elements [example.baz] were left unbound"));
assertThatExceptionOfType(BindException.class).isThrownBy(() -> {
assertThat(this.binder).isNotNull();
this.binder.bind("example", Bindable.of(Example.class), new NoUnboundElementsBindHandler());
}).satisfies((ex) -> {
Throwable cause = ex.getCause();
assertThat(cause).isNotNull();
assertThat(cause.getMessage()).contains("The elements [example.baz] were left unbound");
});
}
@Test
@@ -126,11 +130,14 @@ class NoUnboundElementsBindHandlerTests {
source.put("example.foo[0]", "bar");
this.sources.add(source);
this.binder = new Binder(this.sources);
assertThatExceptionOfType(BindException.class)
.isThrownBy(
() -> this.binder.bind("example", Bindable.of(Example.class), new NoUnboundElementsBindHandler()))
.satisfies((ex) -> assertThat(ex.getCause().getMessage())
.contains("The elements [example.foo[0]] were left unbound"));
assertThatExceptionOfType(BindException.class).isThrownBy(() -> {
assertThat(this.binder).isNotNull();
this.binder.bind("example", Bindable.of(Example.class), new NoUnboundElementsBindHandler());
}).satisfies((ex) -> {
Throwable cause = ex.getCause();
assertThat(cause).isNotNull();
assertThat(cause.getMessage()).contains("The elements [example.foo[0]] were left unbound");
});
}
@Test
@@ -148,7 +155,9 @@ class NoUnboundElementsBindHandlerTests {
NoUnboundElementsBindHandler handler = new NoUnboundElementsBindHandler();
ExampleWithNestedList bound = this.binder.bind("example", Bindable.of(ExampleWithNestedList.class), handler)
.get();
assertThat(bound.getNested().get(0).getStringValue()).isEqualTo("bar");
List<Nested> nested = bound.getNested();
assertThat(nested).isNotNull();
assertThat(nested.get(0).getStringValue()).isEqualTo("bar");
}
@Test
@@ -162,22 +171,25 @@ class NoUnboundElementsBindHandlerTests {
this.sources.add(source1);
this.sources.add(source2);
this.binder = new Binder(this.sources);
assertThatExceptionOfType(BindException.class)
.isThrownBy(() -> this.binder.bind("example", Bindable.of(ExampleWithNestedList.class),
new NoUnboundElementsBindHandler()))
.satisfies((ex) -> assertThat(ex.getCause().getMessage())
.contains("The elements [example.nested[1].invalid] were left unbound"));
assertThatExceptionOfType(BindException.class).isThrownBy(() -> {
assertThat(this.binder).isNotNull();
this.binder.bind("example", Bindable.of(ExampleWithNestedList.class), new NoUnboundElementsBindHandler());
}).satisfies((ex) -> {
Throwable cause = ex.getCause();
assertThat(cause).isNotNull();
assertThat(cause.getMessage()).contains("The elements [example.nested[1].invalid] were left unbound");
});
}
static class Example {
private String foo;
private @Nullable String foo;
String getFoo() {
@Nullable String getFoo() {
return this.foo;
}
void setFoo(String foo) {
void setFoo(@Nullable String foo) {
this.foo = foo;
}
@@ -185,13 +197,13 @@ class NoUnboundElementsBindHandlerTests {
static class ExampleWithList {
private List<String> foo;
private @Nullable List<String> foo;
List<String> getFoo() {
@Nullable List<String> getFoo() {
return this.foo;
}
void setFoo(List<String> foo) {
void setFoo(@Nullable List<String> foo) {
this.foo = foo;
}
@@ -199,13 +211,13 @@ class NoUnboundElementsBindHandlerTests {
static class ExampleWithNestedList {
private List<Nested> nested;
private @Nullable List<Nested> nested;
List<Nested> getNested() {
@Nullable List<Nested> getNested() {
return this.nested;
}
void setNested(List<Nested> nested) {
void setNested(@Nullable List<Nested> nested) {
this.nested = nested;
}
@@ -213,33 +225,33 @@ class NoUnboundElementsBindHandlerTests {
static class Nested {
private String stringValue;
private @Nullable String stringValue;
private Integer intValue;
private @Nullable Integer intValue;
private OtherNested otherNested;
private @Nullable OtherNested otherNested;
String getStringValue() {
@Nullable String getStringValue() {
return this.stringValue;
}
void setStringValue(String value) {
void setStringValue(@Nullable String value) {
this.stringValue = value;
}
Integer getIntValue() {
@Nullable Integer getIntValue() {
return this.intValue;
}
void setIntValue(Integer intValue) {
void setIntValue(@Nullable Integer intValue) {
this.intValue = intValue;
}
OtherNested getOtherNested() {
@Nullable OtherNested getOtherNested() {
return this.otherNested;
}
void setOtherNested(OtherNested otherNested) {
void setOtherNested(@Nullable OtherNested otherNested) {
this.otherNested = otherNested;
}
@@ -247,13 +259,13 @@ class NoUnboundElementsBindHandlerTests {
static class OtherNested {
private String baz;
private @Nullable String baz;
String getBaz() {
@Nullable String getBaz() {
return this.baz;
}
void setBaz(String baz) {
void setBaz(@Nullable String baz) {
this.baz = baz;
}
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.mock;
class BindValidationExceptionTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenValidationErrorsIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new BindValidationException(null))
.withMessageContaining("'validationErrors' must not be null");
@@ -25,6 +25,7 @@ import java.util.Set;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -268,7 +269,9 @@ class ValidationBindHandlerTests {
action.run();
}
catch (BindException ex) {
return (BindValidationException) ex.getCause();
Throwable cause = ex.getCause();
assertThat(cause).isNotNull();
return (BindValidationException) cause;
}
throw new IllegalStateException("Did not throw");
}
@@ -341,19 +344,20 @@ class ValidationBindHandlerTests {
static class ExampleNested {
private String name;
private @Nullable String name;
@Min(5)
private int age;
@NotNull
@SuppressWarnings("NullAway.Init")
private String address;
String getName() {
@Nullable String getName() {
return this.name;
}
void setName(String name) {
void setName(@Nullable String name) {
this.name = name;
}
@@ -423,13 +427,13 @@ class ValidationBindHandlerTests {
static class ExampleMapValue {
private String number;
private @Nullable String number;
String getNumber() {
@Nullable String getNumber() {
return this.number;
}
void setNumber(String number) {
void setNumber(@Nullable String number) {
this.number = number;
}
@@ -437,14 +441,14 @@ class ValidationBindHandlerTests {
static class TestHandler extends AbstractBindHandler {
private final Object result;
private final @Nullable Object result;
TestHandler(Object result) {
TestHandler(@Nullable Object result) {
this.result = result;
}
@Override
public Object onFailure(ConfigurationPropertyName name, Bindable<?> target, BindContext context,
public @Nullable Object onFailure(ConfigurationPropertyName name, Bindable<?> target, BindContext context,
Exception error) throws Exception {
return this.result;
}
@@ -45,6 +45,7 @@ class ValidationErrorsTests {
private static final ConfigurationPropertyName NAME = ConfigurationPropertyName.of("foo");
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenNameIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new ValidationErrors(null, Collections.emptySet(), Collections.emptyList()))
@@ -52,12 +53,14 @@ class ValidationErrorsTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenBoundPropertiesIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ValidationErrors(NAME, null, Collections.emptyList()))
.withMessageContaining("'boundProperties' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenErrorsIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ValidationErrors(NAME, Collections.emptySet(), null))
.withMessageContaining("'errors' must not be null");
@@ -18,6 +18,7 @@ package org.springframework.boot.context.properties.source;
import java.util.Collections;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -98,7 +99,7 @@ class AliasedConfigurationPropertySourceTests {
.isEqualTo(ConfigurationPropertyState.PRESENT);
}
private Object getValue(ConfigurationPropertySource source, String name) {
private @Nullable Object getValue(ConfigurationPropertySource source, String name) {
ConfigurationProperty property = source.getConfigurationProperty(ConfigurationPropertyName.of(name));
return (property != null) ? property.getValue() : null;
}
@@ -61,6 +61,7 @@ class ConfigurationPropertyCachingTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void getFromSourcesWhenSourcesIsNullThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> ConfigurationPropertyCaching.get((Iterable<ConfigurationPropertySource>) null))
@@ -30,6 +30,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class ConfigurationPropertyNameAliasesTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void createWithStringWhenNullNameShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ConfigurationPropertyNameAliases((String) null))
.withMessageContaining("'name' must not be null");
@@ -40,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class ConfigurationPropertyNameTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void ofNameShouldNotBeNull() {
assertThatIllegalArgumentException().isThrownBy(() -> ConfigurationPropertyName.of(null))
.withMessageContaining("'name' must not be null");
@@ -231,6 +232,7 @@ class ConfigurationPropertyNameTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void adaptWhenNameIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> ConfigurationPropertyName.adapt(null, '.'))
.withMessageContaining("Name must not be null");
@@ -35,8 +35,10 @@ class ConfigurationPropertySourceTests {
MockPropertySource source = new MockPropertySource();
source.setProperty("spring", "boot");
ConfigurationPropertySource adapted = ConfigurationPropertySource.from(source);
assertThat(adapted.getConfigurationProperty(ConfigurationPropertyName.of("spring")).getValue())
.isEqualTo("boot");
assertThat(adapted).isNotNull();
ConfigurationProperty spring = adapted.getConfigurationProperty(ConfigurationPropertyName.of("spring"));
assertThat(spring).isNotNull();
assertThat(spring.getValue()).isEqualTo("boot");
}
@Test
@@ -20,6 +20,7 @@ import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -108,7 +109,7 @@ class ConfigurationPropertySourcesCachingTests {
new ConfigurationPropertySourcesCaching(null).enable();
}
private ConfigurationPropertyCaching getCaching(int index) {
private @Nullable ConfigurationPropertyCaching getCaching(int index) {
return CachingConfigurationPropertySource.find(this.sources.get(index));
}
@@ -20,6 +20,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.core.convert.ConversionFailedException;
@@ -165,7 +166,7 @@ class ConfigurationPropertySourcesPropertyResolverTests {
private final Map<String, AtomicInteger> counts = new HashMap<>();
@Override
public Object getProperty(String name) {
public @Nullable Object getProperty(String name) {
incrementCount(name);
return super.getProperty(name);
}
@@ -22,6 +22,7 @@ import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@@ -129,7 +130,7 @@ class ConfigurationPropertySourcesTests {
sources.addFirst(new PropertySource<Environment>("env", environment) {
@Override
public String getProperty(String key) {
public @Nullable String getProperty(String key) {
return this.source.getProperty(key);
}
@@ -33,12 +33,14 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class ConfigurationPropertyStateTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void searchWhenIterableIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> ConfigurationPropertyState.search(null, (e) -> true))
.withMessageContaining("'source' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void searchWhenPredicateIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> ConfigurationPropertyState.search(Collections.emptyList(), null))
@@ -16,6 +16,8 @@
package org.springframework.boot.context.properties.source;
import java.util.Objects;
import org.junit.jupiter.api.Test;
import org.springframework.boot.origin.Origin;
@@ -36,15 +38,18 @@ class ConfigurationPropertyTests {
private static final ConfigurationPropertyName NAME = ConfigurationPropertyName.of("foo");
private final ConfigurationPropertySource source = ConfigurationPropertySource.from(mock(PropertySource.class));
private final ConfigurationPropertySource source = Objects
.requireNonNull(ConfigurationPropertySource.from(mock(PropertySource.class)));
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenNameIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ConfigurationProperty(null, "bar", null))
.withMessageContaining("'name' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenValueIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ConfigurationProperty(NAME, null, null))
.withMessageContaining("'value' must not be null");
@@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class FilteredConfigurationPropertiesSourceTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenSourceIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new FilteredConfigurationPropertiesSource(null, Objects::nonNull))
@@ -39,6 +40,7 @@ class FilteredConfigurationPropertiesSourceTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenFilterIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new FilteredConfigurationPropertiesSource(new MockConfigurationPropertySource(), null))
@@ -50,10 +52,16 @@ class FilteredConfigurationPropertiesSourceTests {
ConfigurationPropertySource source = createTestSource();
ConfigurationPropertySource filtered = source.filter(this::noBrackets);
ConfigurationPropertyName name = ConfigurationPropertyName.of("a");
assertThat(source.getConfigurationProperty(name).getValue()).isEqualTo("1");
assertThat(filtered.getConfigurationProperty(name).getValue()).isEqualTo("1");
ConfigurationProperty configurationProperty = source.getConfigurationProperty(name);
assertThat(configurationProperty).isNotNull();
assertThat(configurationProperty.getValue()).isEqualTo("1");
ConfigurationProperty configurationProperty2 = filtered.getConfigurationProperty(name);
assertThat(configurationProperty2).isNotNull();
assertThat(configurationProperty2.getValue()).isEqualTo("1");
ConfigurationPropertyName bracketName = ConfigurationPropertyName.of("a[1]");
assertThat(source.getConfigurationProperty(bracketName).getValue()).isEqualTo("2");
ConfigurationProperty configurationProperty3 = source.getConfigurationProperty(bracketName);
assertThat(configurationProperty3).isNotNull();
assertThat(configurationProperty3.getValue()).isEqualTo("2");
assertThat(filtered.getConfigurationProperty(bracketName)).isNull();
}
@@ -62,7 +62,9 @@ class FilteredIterableConfigurationPropertiesSourceTests extends FilteredConfigu
IterableConfigurationPropertySource testSource = (IterableConfigurationPropertySource) createTestSource();
Map<String, Object> map = new LinkedHashMap<>();
for (ConfigurationPropertyName name : testSource) {
map.put(name.toString(), testSource.getConfigurationProperty(name).getValue());
ConfigurationProperty configurationProperty = testSource.getConfigurationProperty(name);
assertThat(configurationProperty).isNotNull();
map.put(name.toString(), configurationProperty.getValue());
}
PropertySource<?> propertySource = new OriginTrackedMapPropertySource("test", map, true);
SpringConfigurationPropertySource source = SpringConfigurationPropertySource.from(propertySource);
@@ -79,7 +81,9 @@ class FilteredIterableConfigurationPropertiesSourceTests extends FilteredConfigu
IterableConfigurationPropertySource testSource = (IterableConfigurationPropertySource) createTestSource();
Map<String, Object> map = new LinkedHashMap<>();
for (ConfigurationPropertyName name : testSource) {
map.put(name.toString(), testSource.getConfigurationProperty(name).getValue());
ConfigurationProperty configurationProperty = testSource.getConfigurationProperty(name);
assertThat(configurationProperty).isNotNull();
map.put(name.toString(), configurationProperty.getValue());
}
PropertySource<?> propertySource = new OriginTrackedMapPropertySource("test", map, true);
SpringConfigurationPropertySource source = SpringConfigurationPropertySource.from(propertySource);
@@ -19,6 +19,8 @@ package org.springframework.boot.context.properties.source;
import java.util.HashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import static org.assertj.core.api.Assertions.assertThat;
class KnownAncestorsConfigurationPropertySource implements ConfigurationPropertySource {
@@ -26,7 +28,7 @@ class KnownAncestorsConfigurationPropertySource implements ConfigurationProperty
private final Map<ConfigurationPropertyName, ConfigurationPropertyState> ancestors = new HashMap<>();
@Override
public ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
public @Nullable ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
return null;
}
@@ -19,6 +19,7 @@ package org.springframework.boot.context.properties.source;
import java.util.LinkedHashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -33,6 +34,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class MapConfigurationPropertySourceTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenMapIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new MapConfigurationPropertySource(null))
.withMessageContaining("'map' must not be null");
@@ -49,6 +51,7 @@ class MapConfigurationPropertySourceTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void putAllWhenMapIsNullShouldThrowException() {
MapConfigurationPropertySource source = new MapConfigurationPropertySource();
assertThatIllegalArgumentException().isThrownBy(() -> source.putAll(null))
@@ -101,7 +104,7 @@ class MapConfigurationPropertySourceTests {
}
private Object getValue(ConfigurationPropertySource source, String name) {
private @Nullable Object getValue(ConfigurationPropertySource source, String name) {
ConfigurationProperty property = source.getConfigurationProperty(ConfigurationPropertyName.of(name));
return (property != null) ? property.getValue() : null;
}
@@ -21,6 +21,8 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.origin.MockOrigin;
import org.springframework.boot.origin.OriginTrackedValue;
@@ -41,7 +43,7 @@ public class MockConfigurationPropertySource implements IterableConfigurationPro
this(configurationPropertyName, value, null);
}
public MockConfigurationPropertySource(String configurationPropertyName, Object value, String origin) {
public MockConfigurationPropertySource(String configurationPropertyName, Object value, @Nullable String origin) {
put(ConfigurationPropertyName.of(configurationPropertyName),
OriginTrackedValue.of(value, MockOrigin.of(origin)));
}
@@ -82,7 +84,7 @@ public class MockConfigurationPropertySource implements IterableConfigurationPro
}
@Override
public ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
public @Nullable ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
OriginTrackedValue result = this.map.get(name);
if (result == null) {
result = findValue(name);
@@ -90,7 +92,7 @@ public class MockConfigurationPropertySource implements IterableConfigurationPro
return ConfigurationProperty.of(name, result);
}
private OriginTrackedValue findValue(ConfigurationPropertyName name) {
private @Nullable OriginTrackedValue findValue(ConfigurationPropertyName name) {
return this.map.get(name);
}
@@ -102,7 +104,7 @@ public class MockConfigurationPropertySource implements IterableConfigurationPro
}
@Override
public ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
public @Nullable ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
return MockConfigurationPropertySource.this.getConfigurationProperty(name);
}
@@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThatNoException;
class MutuallyExclusiveConfigurationPropertiesExceptionTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenConfiguredNamesIsNullThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new MutuallyExclusiveConfigurationPropertiesException(null, Arrays.asList("a", "b")))
@@ -50,6 +51,7 @@ class MutuallyExclusiveConfigurationPropertiesExceptionTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenMutuallyExclusiveNamesIsNullThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new MutuallyExclusiveConfigurationPropertiesException(Arrays.asList("a", "b"), null))
@@ -16,6 +16,7 @@
package org.springframework.boot.context.properties.source;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -82,12 +83,12 @@ class PrefixedConfigurationPropertySourceTests {
assertThat(prefixed).isSameAs(source);
}
private ConfigurationPropertyName getName(ConfigurationPropertySource source, String name) {
private @Nullable ConfigurationPropertyName getName(ConfigurationPropertySource source, String name) {
ConfigurationProperty property = source.getConfigurationProperty(ConfigurationPropertyName.of(name));
return (property != null) ? property.getName() : null;
}
private Object getValue(ConfigurationPropertySource source, String name) {
private @Nullable Object getValue(ConfigurationPropertySource source, String name) {
ConfigurationProperty property = source.getConfigurationProperty(ConfigurationPropertyName.of(name));
return (property != null) ? property.getValue() : null;
}
@@ -22,6 +22,7 @@ import java.time.Instant;
import java.time.ZoneOffset;
import java.util.concurrent.atomic.AtomicInteger;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.properties.source.ConfigurationPropertyCaching.CacheOverride;
@@ -186,14 +187,14 @@ class SoftReferenceConfigurationPropertyCacheTests {
*/
class TestSoftReferenceConfigurationPropertyCache extends SoftReferenceConfigurationPropertyCache<Value> {
private Value value;
private @Nullable Value value;
TestSoftReferenceConfigurationPropertyCache(boolean neverExpire) {
super(neverExpire);
}
@Override
protected Value getValue() {
protected @Nullable Value getValue() {
return this.value;
}
@@ -20,6 +20,7 @@ import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.env.RandomValuePropertySource;
@@ -41,6 +42,7 @@ import static org.mockito.Mockito.mock;
class SpringConfigurationPropertySourceTests {
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenPropertySourceIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new SpringConfigurationPropertySource(null, false, mock(PropertyMapper.class)))
@@ -59,7 +61,9 @@ class SpringConfigurationPropertySourceTests {
mapper.addFromConfigurationProperty(name, "key2");
SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource(propertySource, false,
mapper);
assertThat(adapter.getConfigurationProperty(name).getValue()).isEqualTo("value2");
ConfigurationProperty configurationProperty = adapter.getConfigurationProperty(name);
assertThat(configurationProperty).isNotNull();
assertThat(configurationProperty.getValue()).isEqualTo("value2");
}
@Test
@@ -73,6 +77,7 @@ class SpringConfigurationPropertySourceTests {
SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource(propertySource, false,
mapper);
ConfigurationProperty configurationProperty = adapter.getConfigurationProperty(name);
assertThat(configurationProperty).isNotNull();
assertThat(configurationProperty.getOrigin()).hasToString("\"key\" from property source \"test\"");
assertThat(configurationProperty.getSource()).isEqualTo(adapter);
}
@@ -87,7 +92,9 @@ class SpringConfigurationPropertySourceTests {
mapper.addFromConfigurationProperty(name, "key");
SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource(propertySource, false,
mapper);
assertThat(adapter.getConfigurationProperty(name).getOrigin()).hasToString("TestOrigin key");
ConfigurationProperty configurationProperty = adapter.getConfigurationProperty(name);
assertThat(configurationProperty).isNotNull();
assertThat(configurationProperty.getOrigin()).hasToString("TestOrigin key");
}
@Test
@@ -102,6 +109,7 @@ class SpringConfigurationPropertySourceTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void fromWhenPropertySourceIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> SpringConfigurationPropertySource.from(null))
.withMessageContaining("'source' must not be null");
@@ -112,7 +120,7 @@ class SpringConfigurationPropertySourceTests {
PropertySource<?> propertySource = new PropertySource<>("test", new Object()) {
@Override
public Object getProperty(String name) {
public @Nullable Object getProperty(String name) {
return null;
}
@@ -242,7 +250,7 @@ class SpringConfigurationPropertySourceTests {
}
@Override
public Object getProperty(String name) {
public @Nullable Object getProperty(String name) {
name = name.toLowerCase(Locale.ROOT);
if (!name.startsWith(this.prefix)) {
return null;
@@ -267,7 +275,7 @@ class SpringConfigurationPropertySourceTests {
}
@Override
public Object getProperty(String name) {
public @Nullable Object getProperty(String name) {
return this.propertySource.getProperty(name);
}

Some files were not shown because too many files have changed in this diff Show More