From a2f8dc1676cb2ef1594b9e0620f52f8076c85617 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 6 Sep 2017 18:48:50 +0200 Subject: [PATCH] DATACMNS-1152 - Setup of ProjectingJackson2HttpMessageConverter now tries to use unique ObjectMapper from ApplicationContext. We're now trying to look up a uniquely available ObjectMapper instance from the application context falling back to a simple new instance in case none can be found. --- .../config/SpringDataWebConfiguration.java | 15 +++- ...gDataWebConfigurationIntegrationTests.java | 71 ++++++++++++++++--- 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java b/src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java index e739c0502..fcf249c47 100644 --- a/src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java +++ b/src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.data.web.config; import java.util.List; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -122,7 +123,10 @@ public class SpringDataWebConfiguration extends WebMvcConfigurerAdapter { if (ClassUtils.isPresent("com.jayway.jsonpath.DocumentContext", context.getClassLoader()) && ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", context.getClassLoader())) { - ProjectingJackson2HttpMessageConverter converter = new ProjectingJackson2HttpMessageConverter(new ObjectMapper()); + ObjectMapper mapper = getUniqueBean(ObjectMapper.class, context); + mapper = mapper == null ? new ObjectMapper() : mapper; + + ProjectingJackson2HttpMessageConverter converter = new ProjectingJackson2HttpMessageConverter(mapper); converter.setBeanClassLoader(context.getClassLoader()); converter.setBeanFactory(context); @@ -133,4 +137,13 @@ public class SpringDataWebConfiguration extends WebMvcConfigurerAdapter { converters.add(0, new XmlBeamHttpMessageConverter()); } } + + private static T getUniqueBean(Class type, ApplicationContext context) { + + try { + return context.getBean(type); + } catch (NoSuchBeanDefinitionException o_O) { + return null; + } + } } diff --git a/src/test/java/org/springframework/data/web/config/SpringDataWebConfigurationIntegrationTests.java b/src/test/java/org/springframework/data/web/config/SpringDataWebConfigurationIntegrationTests.java index 4023181a8..46aa2b66a 100644 --- a/src/test/java/org/springframework/data/web/config/SpringDataWebConfigurationIntegrationTests.java +++ b/src/test/java/org/springframework/data/web/config/SpringDataWebConfigurationIntegrationTests.java @@ -19,15 +19,20 @@ import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; import org.hamcrest.Matcher; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.data.classloadersupport.HidingClassLoader; import org.springframework.data.web.ProjectingJackson2HttpMessageConverter; import org.springframework.data.web.XmlBeamHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.test.util.ReflectionTestUtils; import org.xmlbeam.XBProjector; import com.fasterxml.jackson.databind.ObjectMapper; @@ -47,7 +52,7 @@ public class SpringDataWebConfigurationIntegrationTests { List> converters = new ArrayList>(); - createConfigWithClassLoader(HidingClassLoader.hide(ObjectMapper.class)).extendMessageConverters(converters); + createConfigWithClassLoader(HidingClassLoader.hide(ObjectMapper.class), triggerExtendConverters(converters)); assertThat(converters, not(hasItem(instanceWithClassName(ProjectingJackson2HttpMessageConverter.class)))); } @@ -57,7 +62,7 @@ public class SpringDataWebConfigurationIntegrationTests { List> converters = new ArrayList>(); - createConfigWithClassLoader(HidingClassLoader.hide(DocumentContext.class)).extendMessageConverters(converters); + createConfigWithClassLoader(HidingClassLoader.hide(DocumentContext.class), triggerExtendConverters(converters)); assertThat(converters, not(hasItem(instanceWithClassName(ProjectingJackson2HttpMessageConverter.class)))); } @@ -67,8 +72,7 @@ public class SpringDataWebConfigurationIntegrationTests { List> converters = new ArrayList>(); - ClassLoader classLoader = HidingClassLoader.hide(XBProjector.class); - createConfigWithClassLoader(classLoader).extendMessageConverters(converters); + createConfigWithClassLoader(HidingClassLoader.hide(XBProjector.class), triggerExtendConverters(converters)); assertThat(converters, not(hasItem(instanceWithClassName(XmlBeamHttpMessageConverter.class)))); } @@ -78,21 +82,49 @@ public class SpringDataWebConfigurationIntegrationTests { List> converters = new ArrayList>(); - createConfigWithClassLoader(getClass().getClassLoader()).extendMessageConverters(converters); + createConfigWithClassLoader(getClass().getClassLoader(), triggerExtendConverters(converters)); assertThat(converters, hasItem(instanceWithClassName(XmlBeamHttpMessageConverter.class))); assertThat(converters, hasItem(instanceWithClassName(ProjectingJackson2HttpMessageConverter.class))); } - private SpringDataWebConfiguration createConfigWithClassLoader(ClassLoader classLoader) { + @Test // DATACMNS-1152 + public void usesCustomObjectMapper() { + + List> converters = new ArrayList>(); + + createConfigWithClassLoader(getClass().getClassLoader(), triggerExtendConverters(converters), + SomeConfiguration.class); + + boolean found = false; + + for (HttpMessageConverter converter : converters) { + + if (converter instanceof ProjectingJackson2HttpMessageConverter) { + + found = true; + + assertThat(ReflectionTestUtils.getField(converter, "objectMapper"), + is(sameInstance((Object) SomeConfiguration.MAPPER))); + } + } + + assertThat(found, is(true)); + } + + private void createConfigWithClassLoader(ClassLoader classLoader, Consumer callback, + Class... additionalConfigurationClasses) { + + List> configClasses = new ArrayList>(Arrays.asList(additionalConfigurationClasses)); + configClasses.add(SpringDataWebConfiguration.class); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - SpringDataWebConfiguration.class); + configClasses.toArray(new Class[configClasses.size()])); context.setClassLoader(classLoader); try { - return context.getBean(SpringDataWebConfiguration.class); + callback.accept(context.getBean(SpringDataWebConfiguration.class)); } finally { context.close(); } @@ -108,4 +140,27 @@ public class SpringDataWebConfigurationIntegrationTests { private static Matcher instanceWithClassName(Class expectedClass) { return hasProperty("class", hasProperty("name", equalTo(expectedClass.getName()))); } + + private static Consumer triggerExtendConverters( + final List> converters) { + + return new Consumer() { + + @Override + public void accept(SpringDataWebConfiguration t) { + t.extendMessageConverters(converters); + } + }; + } + + @Configuration + static class SomeConfiguration { + + static ObjectMapper MAPPER = new ObjectMapper(); + + @Bean + ObjectMapper mapper() { + return MAPPER; + } + } }