How to configure MappingJackson2HttpMessageConverter registered by spring-hateoas

java, json, spring, spring-hateoas, spring-mvc

Solution

I found an ugly solution for my problem:

I'm using a BeanPostProcessor and a lot of reflection magic, to replace Spring HATEOAS' internal ConversionService with my own one, that has been added to the Spring context before. This way I make sure, that Spring HATEOAS uses exactly the same ConversionService as Spring MVC.

/**
 * This is a HACK to work around a not yet implemented feature. At the moment Spring Hateoas uses a
 * {@link ConversionService}, which is hold in a private static final field and hence cannot be accessed to add more
 * Converters<br/>
 *
 * <ul>
 *   <li><a href="https://github.com/spring-projects/spring-hateoas/issues/118">Spring Hateoas Issue</a></li>
 *   <li><a
 *     href="http://stackoverflow.com/questions/22240155/converter-from-pathvariable-domainobject-to-string-using-controllerlinkbuilde">
 *     Solution on Stackoverflow</a></li>
 * </ul>
 */
public static class HateoasConversionServicePostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
        if (bean instanceof ConversionService) {
            try {
                Class<?> clazz = Class.forName(
                        "org.springframework.hateoas.mvc.AnnotatedParametersParameterAccessor$BoundMethodParameter");
                Field field = clazz.getDeclaredField("CONVERSION_SERVICE");
                field.setAccessible(true);

                Field modifiersField = Field.class.getDeclaredField("modifiers");
                modifiersField.setAccessible(true);
                modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

                field.set(null, bean);

                modifiersField.setInt(field, field.getModifiers() & Modifier.FINAL);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
        return bean;
    }
}

Problem

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?

Original source