From f43d6925c59c5572b0849a9c2a7766b1858bd2c7 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 18 Nov 2014 15:51:30 +0000 Subject: [PATCH] =?UTF-8?q?Apply=20spring.jackson.*=20config=20to=20Hyperm?= =?UTF-8?q?ediaAutoConfiguration=E2=80=99s=20ObjectMapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, HypermediaAutoConfiguration would trigger the creation of an ObjectMapper bean named _halObjectMapper. This bean did not have the spring.jackson.* configuration applied to it, however its presence would revent JacksonAutoConfiguration from creating its ObjectMapper. This left the user with an ObjectMapper that did not honour the spring.jackson.* configuration. This commit updates HypermediaAutoConfiguration to use the Jackson2ObjectMapperBuilder that may have been created by JacksonAutoConfiguration. If the builder exists it is used to configure the _halObjectMapper bean. Fixes gh-1949 --- .../hateoas/HypermediaAutoConfiguration.java | 43 ++++++++++++++++++- .../HypermediaAutoConfigurationTests.java | 19 ++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hateoas/HypermediaAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hateoas/HypermediaAutoConfiguration.java index 86fdc55a2a..bf3c9eb241 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hateoas/HypermediaAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hateoas/HypermediaAutoConfiguration.java @@ -16,12 +16,17 @@ package org.springframework.boot.autoconfigure.hateoas; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.hateoas.EntityLinks; import org.springframework.hateoas.LinkDiscoverers; @@ -29,27 +34,63 @@ import org.springframework.hateoas.Resource; import org.springframework.hateoas.config.EnableEntityLinks; import org.springframework.hateoas.config.EnableHypermediaSupport; import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.plugin.core.Plugin; import org.springframework.web.bind.annotation.RequestMapping; +import com.fasterxml.jackson.databind.ObjectMapper; + /** * {@link EnableAutoConfiguration Auto-configuration} for Spring HATEOAS's * {@link EnableHypermediaSupport}. * * @author Roy Clarkson * @author Oliver Gierke + * @author Andy Wilkinson * @since 1.1.0 */ @Configuration @ConditionalOnClass({ Resource.class, RequestMapping.class, Plugin.class }) @ConditionalOnWebApplication -@AutoConfigureAfter(WebMvcAutoConfiguration.class) +@AutoConfigureAfter({ WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class }) public class HypermediaAutoConfiguration { @Configuration @ConditionalOnMissingBean(LinkDiscoverers.class) @EnableHypermediaSupport(type = HypermediaType.HAL) protected static class HypermediaConfiguration { + + @ConditionalOnClass({ Jackson2ObjectMapperBuilder.class, ObjectMapper.class }) + protected static class HalObjectMapperConfiguration { + + @Autowired(required = false) + private Jackson2ObjectMapperBuilder objectMapperBuilder; + + @Bean + public BeanPostProcessor halObjectMapperConfigurer() { + return new BeanPostProcessor() { + + @Override + public Object postProcessAfterInitialization(Object bean, + String beanName) throws BeansException { + if (HalObjectMapperConfiguration.this.objectMapperBuilder != null + && bean instanceof ObjectMapper + && "_halObjectMapper".equals(beanName)) { + HalObjectMapperConfiguration.this.objectMapperBuilder + .configure((ObjectMapper) bean); + } + return bean; + } + + @Override + public Object postProcessBeforeInitialization(Object bean, + String beanName) throws BeansException { + return bean; + } + + }; + } + } } @Configuration diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hateoas/HypermediaAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hateoas/HypermediaAutoConfigurationTests.java index 27e4f93202..961449fcc2 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hateoas/HypermediaAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hateoas/HypermediaAutoConfigurationTests.java @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.hateoas; import org.junit.After; import org.junit.Test; +import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.Configuration; import org.springframework.hateoas.EntityLinks; import org.springframework.hateoas.LinkDiscoverer; @@ -28,6 +30,9 @@ import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType import org.springframework.hateoas.hal.HalLinkDiscoverer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -78,6 +83,20 @@ public class HypermediaAutoConfigurationTests { this.context.getBean(LinkDiscoverers.class); } + @Test + public void jacksonConfigurationIsAppliedToTheHalObjectMapper() { + this.context = new AnnotationConfigWebApplicationContext(); + this.context.register(HypermediaAutoConfiguration.class, + JacksonAutoConfiguration.class); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.jackson.serialization.INDENT_OUTPUT:true"); + this.context.refresh(); + ObjectMapper objectMapper = this.context.getBean("_halObjectMapper", + ObjectMapper.class); + assertTrue(objectMapper.getSerializationConfig().isEnabled( + SerializationFeature.INDENT_OUTPUT)); + } + @Configuration @EnableHypermediaSupport(type = HypermediaType.HAL) static class SampleConfig {