Skip to content

Commit

Permalink
Support @name annotation on /actuator/configprops
Browse files Browse the repository at this point in the history
Update `ConfigurationPropertiesReportEndpoint` so that supports
constructor parameters annotated with `@Name`.

Fixes gh-24713
  • Loading branch information
philwebb committed Jan 13, 2021
1 parent 6c2ff56 commit 26f143b
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 13 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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.
Expand All @@ -17,6 +17,7 @@
package org.springframework.boot.actuate.context.properties;

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -58,12 +59,16 @@
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesBean;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.Name;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.origin.Origin;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.KotlinDetector;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.util.ClassUtils;
Expand Down Expand Up @@ -384,6 +389,8 @@ public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider
*/
protected static class GenericSerializerModifier extends BeanSerializerModifier {

private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();

@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc,
List<BeanPropertyWriter> beanProperties) {
Expand All @@ -398,11 +405,21 @@ public List<BeanPropertyWriter> changeProperties(SerializationConfig config, Bea
return result;
}

private boolean isCandidate(BeanDescription beanDesc, BeanPropertyWriter writer,
Constructor<?> bindConstructor) {
if (bindConstructor != null) {
return Arrays.stream(bindConstructor.getParameters())
.anyMatch((parameter) -> parameter.getName().equals(writer.getName()));
private boolean isCandidate(BeanDescription beanDesc, BeanPropertyWriter writer, Constructor<?> constructor) {
if (constructor != null) {
Parameter[] parameters = constructor.getParameters();
String[] names = PARAMETER_NAME_DISCOVERER.getParameterNames(constructor);
if (names == null) {
names = new String[parameters.length];
}
for (int i = 0; i < parameters.length; i++) {
String name = MergedAnnotations.from(parameters[i]).get(Name.class)
.getValue(MergedAnnotation.VALUE, String.class)
.orElse((names[i] != null) ? names[i] : parameters[i].getName());
if (name.equals(writer.getName())) {
return true;
}
}
}
return isReadable(beanDesc, writer);
}
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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.
Expand Down Expand Up @@ -34,6 +34,7 @@
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.context.properties.bind.Name;
import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginLookup;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
Expand Down Expand Up @@ -73,7 +74,7 @@ void descriptorWithJavaBeanBindMethodDetectsRelevantProperties() {
void descriptorWithValueObjectBindMethodDetectsRelevantProperties() {
this.contextRunner.withUserConfiguration(ImmutablePropertiesConfiguration.class).run(assertProperties(
"immutable",
(properties) -> assertThat(properties).containsOnlyKeys("dbPassword", "myTestProperty", "duration")));
(properties) -> assertThat(properties).containsOnlyKeys("dbPassword", "myTestProperty", "for")));
}

@Test
Expand Down Expand Up @@ -451,16 +452,16 @@ public static class ImmutableProperties {

private final String nullValue;

private final Duration duration;
private final Duration forDuration;

private final String ignored;

ImmutableProperties(@DefaultValue("123456") String dbPassword, @DefaultValue("654321") String myTestProperty,
String nullValue, @DefaultValue("10s") Duration duration) {
String nullValue, @DefaultValue("10s") @Name("for") Duration forDuration) {
this.dbPassword = dbPassword;
this.myTestProperty = myTestProperty;
this.nullValue = nullValue;
this.duration = duration;
this.forDuration = forDuration;
this.ignored = "dummy";
}

Expand All @@ -476,8 +477,8 @@ public String getNullValue() {
return this.nullValue;
}

public Duration getDuration() {
return this.duration;
public Duration getFor() {
return this.forDuration;
}

public String getIgnored() {
Expand Down

0 comments on commit 26f143b

Please sign in to comment.