How to enable HAL rendering without using @EnableHypermediaSupport with spring hateoas?
Asked Answered
G

2

6

With @EnableHypermediaSupport(type = HypermediaType.HAL) Spring hateoas provides a simple and convenient way to enable HAL rendering.

The annotations triggers some configuration magic which is explained here: https://github.com/spring-projects/spring-hateoas#enablehypermediasupport

However if you are working on a given xml-config based spring application, it is not easy to integrate @EnableHypermediaSupport. I tried a lot of different ways to enable HAL rendering but no single solution was working correctly:

  • Including a configuration class in existing mvc servlet xml configuration.
  • Using different versions of spring hateos (0.70.0, 0.80.0, 0.9.0.BUILD-SNAPSHOT), hoping that 0.90.0 will produce HAL out of the box, since, according to a jira issue, it should become the default rendering (at least for spring data rest).
  • Using a custom MappingJackson2HttpMessageConverter to register a new Jackson2HalModule() also did not work. Although the converter was used for rendering (for example to render Dates), the output was not rendered in HAL.

Therefore my question: How can I enable HAL rendering without using EnableHypermediaSupport?

I intentionally left out any code snippets, because I don't think that it would help much.

Glue answered 10/1, 2014 at 9:48 Comment(7)
And what's the problem with adding a class annotated with @EnableHypermediaSupport?Sadiras
It works as far as this is the only mvc setting. But there is an <mvc:annotation-driven> element in the mvc-servlet.xml. Depending on the hateoas version using, we either got an Exception, that context cannot be refreshed, or the links are not rendered HAL anymore. They are rendered the default spring way.Glue
It works for me. I use version 0.8.0.RELEASESadiras
At a first glance it looks ok. But in detail, it behaves different. For example: The solution using ONLY java configuration returns HAL if you omit the accept header, if you use applicatim/json or if you use application/hal+json. The solution with including the config class does not work for application/json. Another problem is that with 0.80.0 RELEASE we results of pagable resources contain a wrong number of embedded resources. For example we have a resource users and although pagesize is set to 4 and there are 10 users existing, only two users are returned.Glue
Surprisingly, the number of rendered embedded resources is correct if I use @EnableHypermediaSupport without HAL.Glue
Any Update on this since Version 0.9.0 is released?Martsen
I can tell you that @EnableHypermediaSupport doesn't even work in .9 see andreitsibets.blogspot.com/2014/04/… for a work aroundLavadalavage
F
3

Based on @WaldemarSchneider answer, here is a concrete how-to:

Create an HTTP message converter:

public class HalHttpMessageConverter extends AbstractJackson2HttpMessageConverter {

  public HalHttpMessageConverter() {
    super(new ObjectMapper(), new MediaType("application", "hal+json", DEFAULT_CHARSET));
    objectMapper.registerModule(new Jackson2HalModule());
    objectMapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(new DefaultRelProvider(), null));
    // customize your mapper if needed
    objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
  }

  @Override
  protected boolean supports(Class<?> clazz) {
    return ResourceSupport.class.isAssignableFrom(clazz);
  }

}

Register it in your servlet context:

<mvc:annotation-driven>
  <mvc:message-converters>
    <bean class="package.to.HalHttpMessageConverter" />
  </mvc:message-converters>
</mvc:annotation-driven>

And don't forget to make your rest controllers produce application/hal+json:

@RestController
@RequestMapping(value = "/articles", produces = "application/hal+json")
public class ArticleRestController {
  ...
}
Freed answered 3/7, 2015 at 12:51 Comment(0)
C
2

Maybe this question is a little bit old but i want to provide my solution for the following users.

I had similiar circumstances (Spring MVC 3.2.10.RELEASE, Spring HATEAOS 0.16.0.RELEASE) to configure spring hateoas to use hypermedia without java configuration.

My solution was the following:

Create a custom HalJacksonHttpMessageConverter (which acts similiar as the Spring MVC standard MappingJacksonHttpMessageConverter, it also have to have a method which exposes the ObjectMapper) but register application/hal+json as the supported hypermediatypes. The supports method should return true if the given class is assignable from ResourceSupport.

Create a RelProvider (the DefaultRelProvider fulfilled my needs in this case) in your xml configuration.

I created a BeanPostProcessorBean (implemented interfaces: BeanPostProcessor and BeanFactoryAware). Enrich the existing ObjectMapper from my HalJachsonHttpMessageConverter with the following settings:

// retrieve the object mapper from the messageConverter
RelProvider provider = beanFactory.getBean("relProvider", RelProvider.class);
ObjectMapper mapper = (ObjectMapper) objectMapper;
mapper.registerModule(new Jackson2HalModule());
mapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(provider, null));
mapper.enable(SerializationFeature.INDENT_OUTPUT);

Register these beans in your spring bean xml. I hope this helps. If someone has a better configuration approach, please let me know.

Caparison answered 26/8, 2014 at 12:26 Comment(1)
thanks for adding here , got an idea to do for my media typeBushman

© 2022 - 2024 — McMap. All rights reserved.