I like to use spring-hateoas in my project and configured it with @EnableHypermediaSupport
.
The problem now is, that this magic config annotation registers its own MappingJackson2HttpMessageConverter
and my own customized converter will be ignored.
Background: I added some Jackson modules (like the JodaModule
) to my project and I want them to get registered using objectMapper.findAndRegisterModules();
. This is done by overriding configureMessageConverters(List<HttpMessageConverter<?>> converters)
in WebMvcConfigurationSupport
or WebMvcConfigurer
.
My current configuration looks like this:
@Configuration
@EnableHypermediaSupport(type = HAL)
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.getObjectMapper().findAndRegisterModules();
converters.add(converter);
}
}
Is there a way to customize the MappingJackson2HttpMessageConverter
or the ObjectMapper
that is used by spring-hateoas?
I had to do the same thing. With HATEOAS .16 i was able to ge this working..but really really ugly.
The key was that in the HypermediaSupportBeanDefinitionRegistrar the part that registers the HAL converter checks to see if there already is a HAL converter before it tries to add another one. So I just added a HAL Converter in my WebMVCConfig::configureMessageConverters myself.
Something like:
private static final String DELEGATING_REL_PROVIDER_BEAN_NAME = "_relProvider";
private static final String LINK_DISCOVERER_REGISTRY_BEAN_NAME = "_linkDiscovererRegistry";
private static final String HAL_OBJECT_MAPPER_BEAN_NAME = "_halObjectMapper";
@Autowired
private ListableBeanFactory beanFactory;
private static CurieProvider getCurieProvider(BeanFactory factory) {
try {
return factory.getBean(CurieProvider.class);
} catch (NoSuchBeanDefinitionException e) {
return null;
}
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
List<HttpMessageConverter<?>> baseConverters = new ArrayList<HttpMessageConverter<?>>();
super.configureMessageConverters(baseConverters);
//Need to override some behaviour in the HAL Serializer...so let's make our own
CurieProvider curieProvider = getCurieProvider(beanFactory);
RelProvider relProvider = beanFactory.getBean(DELEGATING_REL_PROVIDER_BEAN_NAME, RelProvider.class);
ObjectMapper halObjectMapper = beanFactory.getBean(HAL_OBJECT_MAPPER_BEAN_NAME, ObjectMapper.class);
halObjectMapper.registerModule(new Jackson2HalModule());
halObjectMapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider));
MappingJackson2HttpMessageConverter halConverter = new TypeConstrainedMappingJackson2HttpMessageConverter(
ResourceSupport.class);
halConverter.setSupportedMediaTypes(Arrays.asList(HAL_JSON));
halConverter.setObjectMapper(halObjectMapper);
converters.add(halConverter);
}
This is clearly implementation dependent, uses implementation details, and really doesn't let you modify the one that @EnableHyperMediaSupport build for you....but it works for now.