diff --git a/src/main/java/org/springframework/hateoas/config/HypermediaSupportBeanDefinitionRegistrar.java b/src/main/java/org/springframework/hateoas/config/HypermediaSupportBeanDefinitionRegistrar.java index b4f85a8b..0a307518 100644 --- a/src/main/java/org/springframework/hateoas/config/HypermediaSupportBeanDefinitionRegistrar.java +++ b/src/main/java/org/springframework/hateoas/config/HypermediaSupportBeanDefinitionRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-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. @@ -55,6 +55,7 @@ import org.springframework.hateoas.hal.HalLinkDiscoverer; import org.springframework.hateoas.hal.Jackson2HalModule; import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.plugin.core.PluginRegistry; import org.springframework.plugin.core.support.PluginRegistryFactoryBean; @@ -63,6 +64,7 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -116,6 +118,9 @@ class HypermediaSupportBeanDefinitionRegistrar implements ImportBeanDefinitionRe BeanDefinitionBuilder halQueryMapperBuilder = rootBeanDefinition(ObjectMapper.class); registerSourcedBeanDefinition(halQueryMapperBuilder, metadata, registry, HAL_OBJECT_MAPPER_BEAN_NAME); + BeanDefinitionBuilder customizerBeanDefinition = rootBeanDefinition(DefaultObjectMapperCustomizer.class); + registerSourcedBeanDefinition(customizerBeanDefinition, metadata, registry); + BeanDefinitionBuilder builder = rootBeanDefinition(Jackson2ModuleRegisteringBeanPostProcessor.class); registerSourcedBeanDefinition(builder, metadata, registry); } @@ -307,4 +312,39 @@ class HypermediaSupportBeanDefinitionRegistrar implements ImportBeanDefinitionRe } } } + + /** + * {@link BeanPostProcessor} to disable the default HAL {@link ObjectMapper} to fail on unknown properties. Needed as + * the methods to do that on {@link Jackson2ObjectMapperFactoryBean} were introduced in Spring 4.1 only. + * + * @author Oliver Gierke + */ + private static class DefaultObjectMapperCustomizer implements BeanPostProcessor { + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + + if (!HAL_OBJECT_MAPPER_BEAN_NAME.equals(beanName)) { + return bean; + } + + ObjectMapper mapper = (ObjectMapper) bean; + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + return mapper; + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + } } diff --git a/src/test/java/org/springframework/hateoas/config/EnableHypermediaSupportIntegrationTest.java b/src/test/java/org/springframework/hateoas/config/EnableHypermediaSupportIntegrationTest.java index a51983b9..22c56704 100644 --- a/src/test/java/org/springframework/hateoas/config/EnableHypermediaSupportIntegrationTest.java +++ b/src/test/java/org/springframework/hateoas/config/EnableHypermediaSupportIntegrationTest.java @@ -54,6 +54,7 @@ import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAda import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -135,6 +136,19 @@ public class EnableHypermediaSupportIntegrationTest { context.close(); } + /** + * @see #341 + */ + @Test + public void configuresDefaultObjectMapperForHalToIgnoreUnknownProperties() { + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HalConfig.class); + ObjectMapper mapper = context.getBean("_halObjectMapper", ObjectMapper.class); + + assertThat(mapper.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES), is(false)); + context.close(); + } + private static void assertEntityLinksSetUp(ApplicationContext context) { Map discoverers = context.getBeansOfType(EntityLinks.class);