Ignore type-constrained converter when auto-configuring Jackson converter
Previously, JacksonHttpMessageConvertersConfiguration would configure a general-purpose MappingJackson2HttpMessageConverter only if there was no existing MappingJackson2HttpMessageConverter in the application context. This was problematic when a TypeConstrainedMappingJackson2HttpMessageConverter bean was present. Such a bean is only capable of performing conversion for a specific type, and therefore is no substitute for a general purpose converter, yet its presence was causing the auto-configuration of a general purpose converters to be turned off. This would leave Spring MVC’s default converter being used for application/json requests which would not honour the user’s Jackson configuration. This commit enhances @ConditionalOnMissingBean so that the annotation can be used to specify one or more types that should be ignored when searching for beans. This allows the TypeConstrainedMappingJackson2HttpMessageConverter beans that are published by Spring Data REST to be ignored such that the general-purpose MappingJackson2HttpMessageConverter is still auto-configured. Fixes gh-2914
This commit is contained in:
@@ -32,6 +32,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
@@ -187,6 +188,28 @@ public class ConditionalOnMissingBeanTests {
|
||||
equalTo("fromFactory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnMissingBeanConditionWithIgnoredSubclass() {
|
||||
this.context.register(CustomExampleBeanConfiguration.class,
|
||||
ConditionalOnIgnoredSubclass.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBeansOfType(ExampleBean.class).size(), is(equalTo(2)));
|
||||
assertThat(this.context.getBeansOfType(CustomExampleBean.class).size(),
|
||||
is(equalTo(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnMissingBeanConditionWithIgnoredSubclassByName() {
|
||||
this.context.register(CustomExampleBeanConfiguration.class,
|
||||
ConditionalOnIgnoredSubclassByName.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBeansOfType(ExampleBean.class).size(), is(equalTo(2)));
|
||||
assertThat(this.context.getBeansOfType(CustomExampleBean.class).size(),
|
||||
is(equalTo(1)));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(name = "foo")
|
||||
protected static class OnBeanNameConfiguration {
|
||||
@@ -299,6 +322,38 @@ public class ConditionalOnMissingBeanTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class ConditionalOnIgnoredSubclass {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = ExampleBean.class, ignored = CustomExampleBean.class)
|
||||
public ExampleBean exampleBean() {
|
||||
return new ExampleBean("test");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class ConditionalOnIgnoredSubclassByName {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = ExampleBean.class, ignoredType = "org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBeanTests.CustomExampleBean")
|
||||
public ExampleBean exampleBean() {
|
||||
return new ExampleBean("test");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class CustomExampleBeanConfiguration {
|
||||
|
||||
@Bean
|
||||
public CustomExampleBean customExampleBean() {
|
||||
return new CustomExampleBean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(annotation = EnableScheduling.class)
|
||||
protected static class OnAnnotationConfiguration {
|
||||
@@ -369,6 +424,14 @@ public class ConditionalOnMissingBeanTests {
|
||||
|
||||
}
|
||||
|
||||
public static class CustomExampleBean extends ExampleBean {
|
||||
|
||||
public CustomExampleBean() {
|
||||
super("custom subclass");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ExampleFactoryBean implements FactoryBean<ExampleBean> {
|
||||
|
||||
public ExampleFactoryBean(String value) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* Copyright 2012-2015 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.
|
||||
@@ -22,12 +22,17 @@ import java.util.List;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration;
|
||||
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
@@ -37,8 +42,11 @@ import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConve
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
@@ -212,6 +220,36 @@ public class HttpMessageConvertersAutoConfigurationTests {
|
||||
.getPropertyValue("prettyPrint"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeConstrainedConverterDoesNotPreventAutoConfigurationOfJacksonConverter()
|
||||
throws Exception {
|
||||
this.context.register(JacksonObjectMapperBuilderConfig.class,
|
||||
TypeConstrainedConverterConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
BeanDefinition beanDefinition = this.context
|
||||
.getBeanDefinition("mappingJackson2HttpMessageConverter");
|
||||
assertThat(beanDefinition.getFactoryBeanName(),
|
||||
is(equalTo(MappingJackson2HttpMessageConverterConfiguration.class
|
||||
.getName())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeConstrainedConverterFromSpringDataDoesNotPreventAutoConfigurationOfJacksonConverter()
|
||||
throws Exception {
|
||||
this.context.register(JacksonObjectMapperBuilderConfig.class,
|
||||
RepositoryRestMvcConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
BeanDefinition beanDefinition = this.context
|
||||
.getBeanDefinition("mappingJackson2HttpMessageConverter");
|
||||
assertThat(beanDefinition.getFactoryBeanName(),
|
||||
is(equalTo(MappingJackson2HttpMessageConverterConfiguration.class
|
||||
.getName())));
|
||||
}
|
||||
|
||||
private void assertConverterBeanExists(Class<?> type, String beanName) {
|
||||
assertEquals(1, this.context.getBeansOfType(type).size());
|
||||
List<String> beanNames = Arrays.asList(this.context.getBeanDefinitionNames());
|
||||
@@ -279,4 +317,14 @@ public class HttpMessageConvertersAutoConfigurationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class TypeConstrainedConverterConfiguration {
|
||||
|
||||
@Bean
|
||||
public TypeConstrainedMappingJackson2HttpMessageConverter typeConstrainedConverter() {
|
||||
return new TypeConstrainedMappingJackson2HttpMessageConverter(
|
||||
ResourceSupport.class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user