Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optionally disable HATEOAS format in Spring Data Rest

Tags:

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?

like image 206
Ben M Avatar asked Nov 21 '14 21:11

Ben M


People also ask

Is HATEOAS RESTful?

HATEOAS stands for Hypermedia as the Engine of Application State and it is a component of RESTful API architecture and design.

Should I use spring HATEOAS?

Spring HATEOAS provides common abstractions (representational models, a Link class, API to build links pointing to Spring MVC controllers, etc.) to ease building hypermedia driven REST APIs with Spring MVC in general. Thus, you can use it alongside Spring MVC to manually build those services.

Is used for exposing spring data repositories over REST using Spring data REST?

Spring Data REST can be used to expose HATEOAS RESTful resources around Spring Data repositories. Without writing a lot of code, we can expose RESTful API around Spring Data Repositories.

Why is there HATEOAS in spring?

Spring HATEOAS provides some APIs to ease creating REST representations that follow the HATEOAS principle when working with Spring and especially Spring MVC. The core problem it tries to address is link creation and representation assembly.

How do I override spring HATEOAS default link relations?

Override Spring HATEOAS’s default by rendering ALL single-link relations as arrays. If you prefer to only override some particular link relations, you can create a HalConfiguration bean like this: Example 28. Link relation-based HAL single-link rendering policy Always render item link relations as an array.

How does spring HATEOAS render entity models?

It’s made up of properties. The item’s individual links. The previous fragment was lifted from the spec. When Spring HATEOAS renders an EntityModel, it will: Put the self link into both the document’s href attribute and the item-level href attribute. Put the rest of the model’s links into both the top-level links as well as the item-level links.

What are the basics of spring HATEOAS?

This section covers the basics of Spring HATEOAS and its fundamental domain abstractions. 2.1. Links The fundamental idea of hypermedia is to enrich the representation of a resource with hypermedia elements. The simplest form of that are links. They indicate a client that it can navigate to a certain resource.

What are the building blocks of a link in spring HATEOAS?

However, the fundamental building blocks of a link are its reference and relation. Spring HATEOAS lets you work with links through its immutable Link value type. Its constructor takes both a hypertext reference and a link relation, the latter being defaulted to the IANA link relation self . Read more on the latter in Link relations. Example 3.


1 Answers

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

like image 151
gyoder Avatar answered Sep 21 '22 09:09

gyoder