DATAREST-424 - Registered HttpMessageConverters now implement Ordered.

To be able to control the order of the HttpMessageConverter beans registered by RepositoryRestMvcConfiguration we now use a dedicated subtype of TypeConstrainedMappingJackson2HttpMessageConverter which additionally implements Ordered.
This commit is contained in:
Oliver Gierke
2014-12-10 19:42:20 +01:00
parent 7c43512d1d
commit e2a35e7ce9
2 changed files with 100 additions and 7 deletions

View File

@@ -38,6 +38,7 @@ import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.core.io.ClassPathResource;
@@ -398,17 +399,20 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
public MappingJackson2HttpMessageConverter jacksonHttpMessageConverter() {
List<MediaType> mediaTypes = new ArrayList<MediaType>();
mediaTypes.addAll(Arrays.asList(RestMediaTypes.SCHEMA_JSON, //
RestMediaTypes.JSON_PATCH_JSON, RestMediaTypes.MERGE_PATCH_JSON, //
RestMediaTypes.SPRING_DATA_VERBOSE_JSON, RestMediaTypes.SPRING_DATA_COMPACT_JSON));
// Configure this mapper to be used if HAL is not the default media type
if (!config().useHalAsDefaultJsonMediaType()) {
mediaTypes.add(MediaType.APPLICATION_JSON);
}
MappingJackson2HttpMessageConverter jacksonConverter = new TypeConstrainedMappingJackson2HttpMessageConverter(
ResourceSupport.class);
int order = config().useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 1
: Ordered.LOWEST_PRECEDENCE - 10;
mediaTypes.addAll(Arrays.asList(RestMediaTypes.SCHEMA_JSON, //
RestMediaTypes.JSON_PATCH_JSON, RestMediaTypes.MERGE_PATCH_JSON, //
RestMediaTypes.SPRING_DATA_VERBOSE_JSON, RestMediaTypes.SPRING_DATA_COMPACT_JSON));
MappingJackson2HttpMessageConverter jacksonConverter = new ResourceSupportHttpMessageConverter(order);
jacksonConverter.setObjectMapper(objectMapper());
jacksonConverter.setSupportedMediaTypes(mediaTypes);
@@ -430,8 +434,10 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
mediaTypes.add(MediaType.APPLICATION_JSON);
}
MappingJackson2HttpMessageConverter converter = new TypeConstrainedMappingJackson2HttpMessageConverter(
ResourceSupport.class);
int order = config().useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 10
: Ordered.LOWEST_PRECEDENCE - 1;
MappingJackson2HttpMessageConverter converter = new ResourceSupportHttpMessageConverter(order);
converter.setObjectMapper(halObjectMapper());
converter.setSupportedMediaTypes(mediaTypes);
@@ -704,6 +710,31 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
return new AlpsResourceProcessor(config());
}
private static class ResourceSupportHttpMessageConverter extends TypeConstrainedMappingJackson2HttpMessageConverter
implements Ordered {
private final int order;
/**
* Creates a new {@link ResourceSupportHttpMessageConverter} with the given order.
*
* @param order the order for the {@link HttpMessageConverter}.
*/
public ResourceSupportHttpMessageConverter(int order) {
super(ResourceSupport.class);
this.order = order;
}
/*
* (non-Javadoc)
* @see org.springframework.core.Ordered#getOrder()
*/
@Override
public int getOrder() {
return order;
}
}
/**
* Override this method to add additional configuration.
*

View File

@@ -20,12 +20,14 @@ import static org.junit.Assert.*;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -34,12 +36,14 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.RepositoryLinksResource;
import org.springframework.data.rest.webmvc.RestMediaTypes;
import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module;
import org.springframework.data.web.HateoasPageableHandlerMethodArgumentResolver;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.hateoas.LinkDiscoverers;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.core.DefaultRelProvider;
import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
@@ -154,6 +158,35 @@ public class RepositoryRestMvConfigurationIntegrationTests {
}
}
/**
* @see DATAREST-424
*/
@Test
public void halHttpMethodConverterIsRegisteredBeforeTheGeneralOne() {
CollectingComponent component = context.getBean(CollectingComponent.class);
List<HttpMessageConverter<?>> converters = component.converters;
assertThat(converters.get(0).getSupportedMediaTypes(), hasItem(MediaTypes.HAL_JSON));
assertThat(converters.get(1).getSupportedMediaTypes(), hasItem(RestMediaTypes.SCHEMA_JSON));
}
/**
* @see DATAREST-424
*/
@Test
public void halHttpMethodConverterIsRegisteredAfterTheGeneralOneIfHalIsDisabledAsDefaultMediaType() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(NonHalConfiguration.class);
CollectingComponent component = context.getBean(CollectingComponent.class);
context.close();
List<HttpMessageConverter<?>> converters = component.converters;
assertThat(converters.get(0).getSupportedMediaTypes(), hasItem(RestMediaTypes.SCHEMA_JSON));
assertThat(converters.get(1).getSupportedMediaTypes(), hasItem(MediaTypes.HAL_JSON));
}
@Configuration
static class ExtendingConfiguration extends RepositoryRestMvcConfiguration {
@@ -162,6 +195,11 @@ public class RepositoryRestMvConfigurationIntegrationTests {
return new DefaultRelProvider();
}
@Bean
public CollectingComponent collectingComponent() {
return new CollectingComponent();
}
@Override
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
@@ -173,8 +211,32 @@ public class RepositoryRestMvConfigurationIntegrationTests {
}
}
@Configuration
static class NonHalConfiguration extends RepositoryRestMvcConfiguration {
@Bean
public CollectingComponent collectingComponent() {
return new CollectingComponent();
}
@Override
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.useHalAsDefaultJsonMediaType(false);
}
}
static class Sample {
public Date date;
}
static class CollectingComponent {
List<HttpMessageConverter<?>> converters;
@Autowired
public void setConverters(List<HttpMessageConverter<?>> converters) {
this.converters = converters;
}
}
}