Optionally disable HATEOAS format in Spring Data Rest

14,359

The short answer is, you can't use spring-data-rest without hateoas. If you want to build your web service without hateoas, you'll have to write your own controllers (which can still use spring-data repositories).

Quoting Oliver Gierke in this SO post:

Actually my whole point is: the server is just doing decent REST. If that breaks the client, it's the client that needs to be fixed (tweaked). So the hypermedia aspect is a fundamental one to Spring Data REST and we're not going to back out of that. That's probably not satisfying in your concrete situation but should answer the question at least :). – Oliver Gierke

Share:
14,359

Related videos on Youtube

Ben M
Author by

Ben M

I like to build things. Especially in the cloud, using the jvm.

Updated on October 26, 2021

Comments

  • Ben M
    Ben M over 2 years

    So let's say I have an existing application that has two endpoints /people and /pants. Calling GET /people returns:

    [
        {
            "name":"john",
            "age":37,
            "pants":[
                {
                    "color":"green",
                    "brand":"levis",
                    "size":"medium"
                },
                {
                    "color":"indigo",
                    "brand":"jncos",
                    "size":"medium-with-huge-legs"
                }
            ]
        },
        {
            "name":"june",
            "age":23,
            "pants":[
                {
                    "color":"pink",
                    "brand":"gap",
                    "size":"small"
                }
            ]
        }
    ]
    

    If i were to use Spring Data Rest and call GET /person i'd receive something like:

    {
        "_links":{
            "next":{
                "href":"http://myapp.com/people?page=1&size=20"
            },
            "self":{
                "href":"http://myapp.com/people{&page,size,sort}",
                "templated":true
            },
            "search":{
                "href":"http://myapp.com/people/search"
            }
        },
        "_embedded":{
            "people":[
                {
                    "name":"john",
                    "age":37,
                    "_links":{
                        "self":{
                            "href":"http://myapp.com/people/john"
                        },
                        "pants":{
                            "href":"http://myapp.com/people/john/pants"
                        }
                    }
                },
                {
                    "name":"june",
                    "age":23,
                    "_links":{
                        "self":{
                            "href":"http://myapp.com/people/june"
                        },
                        "pants":{
                            "href":"http://myapp.com/people/june/pants"
                        }
                    }
                }
            ]
        }
    }
    

    Let's say I have a bunch of existing clients that I don't want to have to change - is there any way to disable the hypermedia portions of the response in some cases (say Accept="application/json") but enable it them for others (Accept="hal+json")?

    Thanks!

    Updated

    Okay - so it appears that much to my chagrin, what I'm looking to do is not supported. I understand why Spring Data Rest is strongly leaning toward Hypermedia... but I don't buy that providing the capability to "disable" hypermedia based on a header thus providing more options is a bad thing.

    That aside, I'm a bit unsure of how to actually achieve this via my own Controllers. If I create a Controller and attempt to override the /people RequestMapping with produces = "application/json" I am able to get the "raw" json back with Accept="application/json" but if I pass Accept="application/hal+json"` I get a 406 with "Could not find acceptable representation". It looks like the SDR resource mappings aren't mapped with a content type ... any suggestions?

    • Jonathan W
      Jonathan W over 9 years
      Yes, you would do it with a different Accept header.
    • Ben M
      Ben M over 9 years
      Jonathan, the question isn't really around how to know when to return the non-hateoas response but instead how would I enable Spring Data Rest to not generate the Hypermedia elements in the response.
    • Jonathan W
      Jonathan W over 9 years
      I believe that Spring Data REST uses two different HttpMessageConverters for this, and that they are in a chain. If the Accept header indicates application/hal+json, the TypeConstrainedMappingJackson2HttpMessageConverter will handle it and produce HAL. If, however, the header is only 'application/json', the regular MappingJackson2HttpMessageConverter kicks in and will not serialize to HAL. Not sure if that helps, but I would look at trying to tweak this latter converter to not return hypermedia links.
  • Chris DaMour
    Chris DaMour over 9 years
    i'm surprised you cannot override the serializer/message converter to just not output the links...seems like it should be possible
  • Ben M
    Ben M almost 3 years
    I accepted this answer, but 7 years later, i still fundamentally disagree with Drotbohm's insistence on HATEOAS. I think time has continued to show us that in practical terms, very very very few consumers are actually interested or able to make use of the affordances.
  • gyoder
    gyoder almost 3 years
    7 years later, I agree with you. :)