From 4c2c6d5a4a0c256ea8d1275e62ad18386cf5b346 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Sun, 17 May 2015 17:26:33 +0200 Subject: [PATCH] #341 - Default ObjectMapper for HAL now ignores unknown properties. We now explicitly disable the "fail on unknown properties" deserialization feature for the ObjectMapper instance used with our default HAL setup to be able to use it with a RestTemplate out of the box. --- ...ermediaSupportBeanDefinitionRegistrar.java | 42 ++++++++++++++++++- ...nableHypermediaSupportIntegrationTest.java | 14 +++++++ 2 files changed, 55 insertions(+), 1 deletion(-) 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);