Upgrade to Jackson 2.7.2

Closes gh-5081
This commit is contained in:
Andy Wilkinson 2016-03-01 16:37:51 +00:00
parent 355860fd09
commit ef5087c5ee
8 changed files with 83 additions and 29 deletions

View File

@ -310,7 +310,7 @@ public class ConfigurationPropertiesReportEndpoint
private boolean isReadable(BeanDescription beanDesc, BeanPropertyWriter writer) { private boolean isReadable(BeanDescription beanDesc, BeanPropertyWriter writer) {
String parentType = beanDesc.getType().getRawClass().getName(); String parentType = beanDesc.getType().getRawClass().getName();
String type = writer.getPropertyType().getName(); String type = writer.getType().getTypeName();
AnnotatedMethod setter = findSetter(beanDesc, writer); AnnotatedMethod setter = findSetter(beanDesc, writer);
// If there's a setter, we assume it's OK to report on the value, // If there's a setter, we assume it's OK to report on the value,
// similarly, if there's no setter but the package names match, we assume // similarly, if there's no setter but the package names match, we assume
@ -324,7 +324,7 @@ public class ConfigurationPropertiesReportEndpoint
private AnnotatedMethod findSetter(BeanDescription beanDesc, private AnnotatedMethod findSetter(BeanDescription beanDesc,
BeanPropertyWriter writer) { BeanPropertyWriter writer) {
String name = "set" + StringUtils.capitalize(writer.getName()); String name = "set" + StringUtils.capitalize(writer.getName());
Class<?> type = writer.getPropertyType(); Class<?> type = writer.getType().getRawClass();
AnnotatedMethod setter = beanDesc.findMethod(name, new Class<?>[] { type }); AnnotatedMethod setter = beanDesc.findMethod(name, new Class<?>[] { type });
// The enabled property of endpoints returns a boolean primitive but is set // The enabled property of endpoints returns a boolean primitive but is set
// using a Boolean class // using a Boolean class

View File

@ -19,6 +19,7 @@ package org.springframework.boot.actuate.endpoint.jmx;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.boot.actuate.endpoint.Endpoint;
@ -40,6 +41,10 @@ public class EndpointMBean {
private final ObjectMapper mapper; private final ObjectMapper mapper;
private final JavaType listObject;
private final JavaType mapStringObject;
/** /**
* Create a new {@link EndpointMBean} instance. * Create a new {@link EndpointMBean} instance.
* @param beanName the bean name * @param beanName the bean name
@ -53,6 +58,10 @@ public class EndpointMBean {
Assert.notNull(objectMapper, "ObjectMapper must not be null"); Assert.notNull(objectMapper, "ObjectMapper must not be null");
this.endpoint = endpoint; this.endpoint = endpoint;
this.mapper = objectMapper; this.mapper = objectMapper;
this.listObject = objectMapper.getTypeFactory()
.constructParametricType(List.class, Object.class);
this.mapStringObject = objectMapper.getTypeFactory()
.constructParametricType(Map.class, String.class, Object.class);
} }
@ManagedAttribute(description = "Returns the class of the underlying endpoint") @ManagedAttribute(description = "Returns the class of the underlying endpoint")
@ -77,9 +86,9 @@ public class EndpointMBean {
return result; return result;
} }
if (result.getClass().isArray() || result instanceof List) { if (result.getClass().isArray() || result instanceof List) {
return this.mapper.convertValue(result, List.class); return this.mapper.convertValue(result, this.listObject);
} }
return this.mapper.convertValue(result, Map.class); return this.mapper.convertValue(result, this.mapStringObject);
} }
} }

View File

@ -17,10 +17,12 @@
package org.springframework.boot.actuate.endpoint.jmx; package org.springframework.boot.actuate.endpoint.jmx;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
@ -199,12 +201,12 @@ public class EndpointMBeanExporterTests {
} }
@Test @Test
public void jsonConversionWithDefaultObjectMapper() throws Exception { public void jsonMapConversionWithDefaultObjectMapper() throws Exception {
this.context = new GenericApplicationContext(); this.context = new GenericApplicationContext();
this.context.registerBeanDefinition("endpointMbeanExporter", this.context.registerBeanDefinition("endpointMbeanExporter",
new RootBeanDefinition(EndpointMBeanExporter.class)); new RootBeanDefinition(EndpointMBeanExporter.class));
this.context.registerBeanDefinition("endpoint1", this.context.registerBeanDefinition("endpoint1",
new RootBeanDefinition(JsonConversionEndpoint.class)); new RootBeanDefinition(JsonMapConversionEndpoint.class));
this.context.refresh(); this.context.refresh();
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class); MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
Object response = mbeanExporter.getServer().invoke( Object response = mbeanExporter.getServer().invoke(
@ -215,7 +217,7 @@ public class EndpointMBeanExporterTests {
} }
@Test @Test
public void jsonConversionWithCustomObjectMapper() throws Exception { public void jsonMapConversionWithCustomObjectMapper() throws Exception {
this.context = new GenericApplicationContext(); this.context = new GenericApplicationContext();
ConstructorArgumentValues constructorArgs = new ConstructorArgumentValues(); ConstructorArgumentValues constructorArgs = new ConstructorArgumentValues();
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
@ -225,7 +227,7 @@ public class EndpointMBeanExporterTests {
new RootBeanDefinition(EndpointMBeanExporter.class, constructorArgs, new RootBeanDefinition(EndpointMBeanExporter.class, constructorArgs,
null)); null));
this.context.registerBeanDefinition("endpoint1", this.context.registerBeanDefinition("endpoint1",
new RootBeanDefinition(JsonConversionEndpoint.class)); new RootBeanDefinition(JsonMapConversionEndpoint.class));
this.context.refresh(); this.context.refresh();
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class); MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
Object response = mbeanExporter.getServer().invoke( Object response = mbeanExporter.getServer().invoke(
@ -235,6 +237,22 @@ public class EndpointMBeanExporterTests {
assertThat(((Map<?, ?>) response).get("date")).isInstanceOf(String.class); assertThat(((Map<?, ?>) response).get("date")).isInstanceOf(String.class);
} }
@Test
public void jsonListConversion() throws Exception {
this.context = new GenericApplicationContext();
this.context.registerBeanDefinition("endpointMbeanExporter",
new RootBeanDefinition(EndpointMBeanExporter.class));
this.context.registerBeanDefinition("endpoint1",
new RootBeanDefinition(JsonListConversionEndpoint.class));
this.context.refresh();
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
Object response = mbeanExporter.getServer().invoke(
getObjectName("endpoint1", this.context), "getData", new Object[0],
new String[0]);
assertThat(response).isInstanceOf(List.class);
assertThat(((List<?>) response).get(0)).isInstanceOf(Long.class);
}
private ObjectName getObjectName(String beanKey, GenericApplicationContext context) private ObjectName getObjectName(String beanKey, GenericApplicationContext context)
throws MalformedObjectNameException { throws MalformedObjectNameException {
return getObjectName("org.springframework.boot", beanKey, false, context); return getObjectName("org.springframework.boot", beanKey, false, context);
@ -265,11 +283,11 @@ public class EndpointMBeanExporterTests {
} }
public static class JsonConversionEndpoint public static class JsonMapConversionEndpoint
extends AbstractEndpoint<Map<String, Object>> { extends AbstractEndpoint<Map<String, Object>> {
public JsonConversionEndpoint() { public JsonMapConversionEndpoint() {
super("json-conversion"); super("json-map-conversion");
} }
@Override @Override
@ -281,4 +299,18 @@ public class EndpointMBeanExporterTests {
} }
public static class JsonListConversionEndpoint
extends AbstractEndpoint<List<Object>> {
public JsonListConversionEndpoint() {
super("json-list-conversion");
}
@Override
public List<Object> invoke() {
return Arrays.<Object>asList(new Date());
}
}
} }

View File

@ -166,9 +166,9 @@ public class JacksonAutoConfiguration {
public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder() { public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.applicationContext(this.applicationContext); builder.applicationContext(this.applicationContext);
if (this.jacksonProperties.getSerializationInclusion() != null) { if (this.jacksonProperties.getDefaultPropertyInclusion() != null) {
builder.serializationInclusion( builder.serializationInclusion(
this.jacksonProperties.getSerializationInclusion()); this.jacksonProperties.getDefaultPropertyInclusion());
} }
if (this.jacksonProperties.getTimeZone() != null) { if (this.jacksonProperties.getTimeZone() != null) {
builder.timeZone(this.jacksonProperties.getTimeZone()); builder.timeZone(this.jacksonProperties.getTimeZone());

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,6 +29,7 @@ import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
/** /**
* Configuration properties to configure Jackson. * Configuration properties to configure Jackson.
@ -89,7 +90,7 @@ public class JacksonProperties {
* Controls the inclusion of properties during serialization. Configured with one of * Controls the inclusion of properties during serialization. Configured with one of
* the values in Jackson's JsonInclude.Include enumeration. * the values in Jackson's JsonInclude.Include enumeration.
*/ */
private JsonInclude.Include serializationInclusion; private JsonInclude.Include defaultPropertyInclusion;
/** /**
* Time zone used when formatting dates. Configured using any recognized time zone * Time zone used when formatting dates. Configured using any recognized time zone
@ -146,12 +147,24 @@ public class JacksonProperties {
return this.generator; return this.generator;
} }
@Deprecated
@DeprecatedConfigurationProperty(reason = "ObjectMapper.setSerializationInclusion was deprecated in Jackson 2.7", replacement = "spring.jackson.default-property-inclusion")
public JsonInclude.Include getSerializationInclusion() { public JsonInclude.Include getSerializationInclusion() {
return this.serializationInclusion; return getDefaultPropertyInclusion();
} }
@Deprecated
public void setSerializationInclusion(JsonInclude.Include serializationInclusion) { public void setSerializationInclusion(JsonInclude.Include serializationInclusion) {
this.serializationInclusion = serializationInclusion; setDefaultPropertyInclusion(serializationInclusion);
}
public JsonInclude.Include getDefaultPropertyInclusion() {
return this.defaultPropertyInclusion;
}
public void setDefaultPropertyInclusion(
JsonInclude.Include defaultPropertyInclusion) {
this.defaultPropertyInclusion = defaultPropertyInclusion;
} }
public TimeZone getTimeZone() { public TimeZone getTimeZone() {

View File

@ -35,7 +35,7 @@ import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy; import com.fasterxml.jackson.databind.PropertyNamingStrategy.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.Annotated;
@ -167,22 +167,22 @@ public class JacksonAutoConfigurationTests {
public void customPropertyNamingStrategyField() throws Exception { public void customPropertyNamingStrategyField() throws Exception {
this.context.register(JacksonAutoConfiguration.class); this.context.register(JacksonAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(this.context, EnvironmentTestUtils.addEnvironment(this.context,
"spring.jackson.property-naming-strategy:CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES"); "spring.jackson.property-naming-strategy:SNAKE_CASE");
this.context.refresh(); this.context.refresh();
ObjectMapper mapper = this.context.getBean(ObjectMapper.class); ObjectMapper mapper = this.context.getBean(ObjectMapper.class);
assertThat(mapper.getPropertyNamingStrategy()) assertThat(mapper.getPropertyNamingStrategy())
.isInstanceOf(LowerCaseWithUnderscoresStrategy.class); .isInstanceOf(SnakeCaseStrategy.class);
} }
@Test @Test
public void customPropertyNamingStrategyClass() throws Exception { public void customPropertyNamingStrategyClass() throws Exception {
this.context.register(JacksonAutoConfiguration.class); this.context.register(JacksonAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(this.context, EnvironmentTestUtils.addEnvironment(this.context,
"spring.jackson.property-naming-strategy:com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy"); "spring.jackson.property-naming-strategy:com.fasterxml.jackson.databind.PropertyNamingStrategy.SnakeCaseStrategy");
this.context.refresh(); this.context.refresh();
ObjectMapper mapper = this.context.getBean(ObjectMapper.class); ObjectMapper mapper = this.context.getBean(ObjectMapper.class);
assertThat(mapper.getPropertyNamingStrategy()) assertThat(mapper.getPropertyNamingStrategy())
.isInstanceOf(LowerCaseWithUnderscoresStrategy.class); .isInstanceOf(SnakeCaseStrategy.class);
} }
@Test @Test
@ -355,8 +355,8 @@ public class JacksonAutoConfigurationTests {
this.context.refresh(); this.context.refresh();
ObjectMapper objectMapper = this.context ObjectMapper objectMapper = this.context
.getBean(Jackson2ObjectMapperBuilder.class).build(); .getBean(Jackson2ObjectMapperBuilder.class).build();
assertThat(objectMapper.getSerializationConfig().getSerializationInclusion()) assertThat(objectMapper.getSerializationConfig().getDefaultPropertyInclusion()
.isEqualTo(JsonInclude.Include.ALWAYS); .getValueInclusion()).isEqualTo(JsonInclude.Include.USE_DEFAULTS);
} }
@Test @Test
@ -367,8 +367,8 @@ public class JacksonAutoConfigurationTests {
this.context.refresh(); this.context.refresh();
ObjectMapper objectMapper = this.context ObjectMapper objectMapper = this.context
.getBean(Jackson2ObjectMapperBuilder.class).build(); .getBean(Jackson2ObjectMapperBuilder.class).build();
assertThat(objectMapper.getSerializationConfig().getSerializationInclusion()) assertThat(objectMapper.getSerializationConfig().getDefaultPropertyInclusion()
.isEqualTo(JsonInclude.Include.NON_NULL); .getValueInclusion()).isEqualTo(JsonInclude.Include.NON_NULL);
} }
@Test @Test

View File

@ -112,9 +112,9 @@ public class DataSourceJsonSerializationTests {
for (BeanPropertyWriter writer : beanProperties) { for (BeanPropertyWriter writer : beanProperties) {
AnnotatedMethod setter = beanDesc.findMethod( AnnotatedMethod setter = beanDesc.findMethod(
"set" + StringUtils.capitalize(writer.getName()), "set" + StringUtils.capitalize(writer.getName()),
new Class<?>[] { writer.getPropertyType() }); new Class<?>[] { writer.getType().getRawClass() });
if (setter != null && this.conversionService.canConvert(String.class, if (setter != null && this.conversionService.canConvert(String.class,
writer.getPropertyType())) { writer.getType().getRawClass())) {
result.add(writer); result.add(writer);
} }
} }

View File

@ -86,7 +86,7 @@
<httpclient.version>4.5.1</httpclient.version> <httpclient.version>4.5.1</httpclient.version>
<httpcore.version>4.4.4</httpcore.version> <httpcore.version>4.4.4</httpcore.version>
<infinispan.version>8.1.2.Final</infinispan.version> <infinispan.version>8.1.2.Final</infinispan.version>
<jackson.version>2.6.5</jackson.version> <jackson.version>2.7.2</jackson.version>
<janino.version>2.7.8</janino.version> <janino.version>2.7.8</janino.version>
<javassist.version>3.18.1-GA</javassist.version> <!-- Same as Hibernate --> <javassist.version>3.18.1-GA</javassist.version> <!-- Same as Hibernate -->
<javax-cache.version>1.0.0</javax-cache.version> <javax-cache.version>1.0.0</javax-cache.version>