Search code examples
spring-integrationspring-hateoasspring-integration-http

How to get Spring Integration Http.inboundGateway to return HAL Json?


I set the following property to true "spring.hateoas.use-hal-as-default-json-media-type' & added org.springframework.boot:spring-boot-starter-hateoas as a dependency.

Code

@Bean
public IntegrationFlow myUserFlow() {
    return IntegrationFlows
            .from(Http.inboundGateway("/user")
                    .requestMapping(r -> r.methods(HttpMethod.GET))
                    .get()
            )
            .handle((payload, headers) -> new MyUser("Joe Blogs")
                    .add(Link.of("http://localhost:8080/account", LinkRelation.of("account"))))
            .get();
}

Response

GET http://localhost:8080/user
HTTP/1.1 200 
connection: Keep-Alive, keep-alive
Content-Type: application/hal+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 11 Jan 2021 18:31:13 GMT
Keep-Alive: timeout=60

{
  "name": "Joe Blogs",
  "links": [
    {
      "rel": "account",
      "href": "http://localhost:8080/account"
    }
  ]
}

Response code: 200; Time: 19ms; Content length: 87 bytes

I expected the reponse to be returned in a HAL format e.g.

{
  "name": "Joe Blogs",
  "_links": [
    {
      "account":{
          "href": "http://localhost:8080/account"
       }
    }
  ]
}

Why is this not the case? And how can I make it so?

Sample application: https://github.com/kevvvvyp/si-hateoas-demo


Solution

  • The solution is like this:

    public IntegrationFlow myUserFlow(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
        return IntegrationFlows
                .from(Http.inboundGateway("/user")
                        .messageConverters(requestMappingHandlerAdapter.getMessageConverters().toArray(HttpMessageConverter[]::new))
    

    The problem is because Spring Integration HTTP channel adapters are not auto-configured by Spring Boot and they are definitely not aware of your HAL customization.

    So, we need to wait until the RequestMappingHandlerAdapter is processed by Spring Boot and hateoas customization. Then we take its converters and inject them into our Http.inboundGateway().

    I wanted to say that we may think about something automatic in Spring Boot to pick that customization up, but since we really don't talk about some infrastructure like MVC's @RequestMapping but rather some concrete beans, it is really probably better to stick with an explicit configuration.

    I'm not sure though why can't we use HttpMessageConverters instead, but looks like RequestMappingHandlerAdapter is configured later on, when this kind of beans (IntegrtionFlow) have already parsed and created.