Fix setter detection in `configprops` endpoint

Previously, the setter of a property whose second letter is upper-case (
such as `oAuth2Uri`) was not detected properly. The JavaBean spec states
that, in such a case, the first letter should not be capitalized (i.e.
the setter should be `setoAuth2Uri` rather than `setOAuth2Uri`).

This commit makes sure that Jackson uses standard bean names and fixes
the setter detection algorithm to take this case into account.

Closes gh-13878
pull/14019/merge
Stephane Nicoll 6 years ago
parent 9e4ccbd1e6
commit fbf3c48bf8

@ -26,6 +26,7 @@ import java.util.Map;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
@ -172,6 +173,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
*/
protected void configureObjectMapper(ObjectMapper mapper) {
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.configure(MapperFeature.USE_STD_BEAN_NAMING, true);
mapper.setSerializationInclusion(Include.NON_NULL);
applyConfigurationPropertiesFilter(mapper);
applySerializationModifier(mapper);
@ -375,7 +377,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
private AnnotatedMethod findSetter(BeanDescription beanDesc,
BeanPropertyWriter writer) {
String name = "set" + StringUtils.capitalize(writer.getName());
String name = "set" + determineAccessorSuffix(writer.getName());
Class<?> type = writer.getType().getRawClass();
AnnotatedMethod setter = beanDesc.findMethod(name, new Class<?>[] { type });
// The enabled property of endpoints returns a boolean primitive but is set
@ -386,6 +388,23 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
return setter;
}
/**
* Determine the accessor suffix of the specified {@code propertyName}, see
* section 8.8 "Capitalization of inferred names" of the JavaBean specs for more
* details.
* @param propertyName the property name to turn into an accessor suffix
* @return the accessor suffix for {@code propertyName}
*/
private String determineAccessorSuffix(String propertyName) {
if (propertyName.length() > 1
&& Character.isUpperCase(propertyName.charAt(1))) {
return propertyName;
}
else {
return StringUtils.capitalize(propertyName);
}
}
}
/**

@ -44,6 +44,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Stephane Nicoll
*/
public class ConfigurationPropertiesReportEndpointTests {
@ -120,6 +121,24 @@ public class ConfigurationPropertiesReportEndpointTests {
});
}
@Test
public void nonCamelCaseProperty() {
load((context, properties) -> {
Map<String, Object> nestedProperties = properties.getBeans()
.get("testProperties").getProperties();
assertThat(nestedProperties.get("myURL")).isEqualTo("https://example.com");
});
}
@Test
public void simpleBoolean() {
load((context, properties) -> {
Map<String, Object> nestedProperties = properties.getBeans()
.get("testProperties").getProperties();
assertThat(nestedProperties.get("simpleBoolean")).isEqualTo(true);
});
}
@Test
public void mixedBoolean() {
load((context, properties) -> {
@ -129,6 +148,24 @@ public class ConfigurationPropertiesReportEndpointTests {
});
}
@Test
public void mixedCase() {
load((context, properties) -> {
Map<String, Object> nestedProperties = properties.getBeans()
.get("testProperties").getProperties();
assertThat(nestedProperties.get("mIxedCase")).isEqualTo("mixed");
});
}
@Test
public void singleLetterProperty() {
load((context, properties) -> {
Map<String, Object> nestedProperties = properties.getBeans()
.get("testProperties").getProperties();
assertThat(nestedProperties.get("z")).isEqualTo("zzz");
});
}
@Test
@SuppressWarnings("unchecked")
public void listsAreSanitized() {
@ -219,8 +256,16 @@ public class ConfigurationPropertiesReportEndpointTests {
private String myTestProperty = "654321";
private String myURL = "https://example.com";
private boolean simpleBoolean = true;
private Boolean mixedBoolean = true;
private String mIxedCase = "mixed";
private String z = "zzz";
private Map<String, Object> secrets = new HashMap<>();
private Hidden hidden = new Hidden();
@ -254,14 +299,46 @@ public class ConfigurationPropertiesReportEndpointTests {
this.myTestProperty = myTestProperty;
}
public boolean isMixedBoolean() {
return (this.mixedBoolean != null) ? this.mixedBoolean : false;
public String getMyURL() {
return this.myURL;
}
public void setMyURL(String myURL) {
this.myURL = myURL;
}
public boolean isSimpleBoolean() {
return this.simpleBoolean;
}
public void setSimpleBoolean(boolean simpleBoolean) {
this.simpleBoolean = simpleBoolean;
}
public void setMixedBoolean(Boolean mixedBoolean) {
this.mixedBoolean = mixedBoolean;
}
public boolean isMixedBoolean() {
return (this.mixedBoolean != null) ? this.mixedBoolean : false;
}
public String getmIxedCase() {
return this.mIxedCase;
}
public void setmIxedCase(String mIxedCase) {
this.mIxedCase = mIxedCase;
}
public String getZ() {
return this.z;
}
public void setZ(String z) {
this.z = z;
}
public Map<String, Object> getSecrets() {
return this.secrets;
}

Loading…
Cancel
Save