From a1fe05f40b02cc79dc3777ff6f90a04ac4de6eac Mon Sep 17 00:00:00 2001 From: qxo <49526356@qq.com> Date: Fri, 4 Mar 2022 22:55:31 +0800 Subject: [PATCH 1/2] Fix NPE in configprops endpoint This works around spring-projects/spring-framework#28298. The bug means that when a @Configuration class is annotated with @ConfigurationProperties any bean defined by a static @Bean method is considered to be annotated with @ConfigurationProperties. See gh-30068 --- .../ConfigurationPropertiesReportEndpoint.java | 2 +- .../properties/ConfigurationPropertiesBean.java | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java index c79c58a060..23b8d8d12e 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java @@ -121,7 +121,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @ReadOperation public ApplicationConfigurationProperties configurationProperties() { - return extract(this.context, (bean) -> true); + return extract(this.context, (bean) -> bean != null); } @ReadOperation diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java index b5628a5f68..b95fee1918 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java @@ -144,7 +144,13 @@ public final class ConfigurationPropertiesBean { } Map propertiesBeans = new LinkedHashMap<>(); applicationContext.getBeansWithAnnotation(ConfigurationProperties.class) - .forEach((beanName, bean) -> propertiesBeans.put(beanName, get(applicationContext, bean, beanName))); + .forEach((beanName, bean) -> { + ConfigurationPropertiesBean propertiesBean = get(applicationContext, bean, beanName); + if (propertiesBean == null) { //ignore for null + return; + } + propertiesBeans.put(beanName,propertiesBean); + }); return propertiesBeans; } @@ -158,6 +164,9 @@ public final class ConfigurationPropertiesBean { try { Object bean = beanFactory.getBean(beanName); ConfigurationPropertiesBean propertiesBean = get(applicationContext, bean, beanName); + if (propertiesBean == null) { //ignore for null + continue; + } propertiesBeans.put(beanName, propertiesBean); } catch (Exception ex) { From 35154a96f32897456a6c7c77ecb3f5247343e197 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 7 Apr 2022 19:42:19 +0100 Subject: [PATCH 2/2] Polish "Fix NPE in configprops endpoint" See gh-30068 --- ...ConfigurationPropertiesReportEndpoint.java | 2 +- .../ConfigurationPropertiesBean.java | 21 ++++++++----------- .../ConfigurationPropertiesBeanTests.java | 20 ++++++++++++++++++ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java index 23b8d8d12e..c79c58a060 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java @@ -121,7 +121,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @ReadOperation public ApplicationConfigurationProperties configurationProperties() { - return extract(this.context, (bean) -> bean != null); + return extract(this.context, (bean) -> true); } @ReadOperation diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java index b95fee1918..a3c86d8b30 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -143,14 +143,12 @@ public final class ConfigurationPropertiesBean { return getAll((ConfigurableApplicationContext) applicationContext); } Map propertiesBeans = new LinkedHashMap<>(); - applicationContext.getBeansWithAnnotation(ConfigurationProperties.class) - .forEach((beanName, bean) -> { - ConfigurationPropertiesBean propertiesBean = get(applicationContext, bean, beanName); - if (propertiesBean == null) { //ignore for null - return; - } - propertiesBeans.put(beanName,propertiesBean); - }); + applicationContext.getBeansWithAnnotation(ConfigurationProperties.class).forEach((beanName, bean) -> { + ConfigurationPropertiesBean propertiesBean = get(applicationContext, bean, beanName); + if (propertiesBean != null) { + propertiesBeans.put(beanName, propertiesBean); + } + }); return propertiesBeans; } @@ -164,10 +162,9 @@ public final class ConfigurationPropertiesBean { try { Object bean = beanFactory.getBean(beanName); ConfigurationPropertiesBean propertiesBean = get(applicationContext, bean, beanName); - if (propertiesBean == null) { //ignore for null - continue; + if (propertiesBean != null) { + propertiesBeans.put(beanName, propertiesBean); } - propertiesBeans.put(beanName, propertiesBean); } catch (Exception ex) { } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanTests.java index ccd9bc6df0..256f2b1729 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanTests.java @@ -78,6 +78,15 @@ class ConfigurationPropertiesBeanTests { } } + @Test + void getAllDoesNotFindABeanDeclaredInAStaticBeanMethodOnAConfigurationAndConfigurationPropertiesAnnotatedClass() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + StaticBeanMethodConfiguration.class)) { + Map all = ConfigurationPropertiesBean.getAll(context); + assertThat(all).containsOnlyKeys("configurationPropertiesBeanTests.StaticBeanMethodConfiguration"); + } + } + @Test void getAllWhenHasBadBeanDoesNotFail() { try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( @@ -521,4 +530,15 @@ class ConfigurationPropertiesBeanTests { } + @Configuration(proxyBeanMethods = false) + @ConfigurationProperties + static class StaticBeanMethodConfiguration { + + @Bean + static String stringBean() { + return "example"; + } + + } + }