Search code examples
jsonspringresttemplatehateoas

Auto-populate _link-ed member objects when consuming HAL based APIs with RestTemplate


Using Spring RestTemplate, I'd like to consume a HAL based REST service with a simplified configuration like this:

GET http://my.rest.service/items/123 returns

{
    "_links": {
        "category": {
            "href": "/categories/321"
        },
        "self": {
            "href": "/items/123"
        }
    },
    "name": "my wonderful item"
}

A GET on http://my.rest.service/categories/321 will then accordingly return the category my item is assigned to (which looks quite similar to the JSON above).

What I can do up to now (and what is working :)) is some "manual" link-following:

public Item getItemById(Integer itemId) {
    RestTemplate restTemplate = getRestTemplateWithHalMessageConverter();

    ResponseEntity<Resource<Budget>> response =
        restTemplate.exchange("http://my.rest.service/items/"+itemId,
            HttpMethod.GET, getHttpEntity(), 
            new ParameterizedTypeReference<Resource<Item>>() {}
        );

    ResponseEntity<Resource<Category>> catResponse =
        restTemplate.exchange("http://my.rest.service/" + 
            response.getBody().getLink("category").getHref(),
            HttpMethod.GET, getHttpEntity(), 
            new ParameterizedTypeReference<Resource<Category>>() {}
        );

    Item result = response.getBody().getContent();
    //^^ Now this is an item with NULL in category field

    result.setCategory(catResponse.getBody().getContent());
    //And voila, now the category is assigned

    return result;
}

(I didn't post the "helper" functions like getRestTemplateWithHalMessageConverter() here as IMHO they are not relevant for this question, especially as they work as expected.)

What I would like to achieve is "auto-following" the links in the HAL response and populate my Java objects respectively.

So, my question is, is there any way to get "automatic" _link following, such that my Item will be fully populated without the second exchange etc.? This is a simple example, but I have more complex objects with many links. Of course, one can assume, that the matching fields exist in the particular classes.

And on bonus question ;) : Can this be used alongside with some kind of caching? If I have 30 items with category 8, I wouldn't like having 30 calls to the category endpoint...

If there is no out-of-the-box solution for both questions (at least I didn't find one...) and I'll have to write my own, I'm fine with that! Just want to make sure I'm not reinventing the wheel just because I missed something...

Thanks a lot!!


Solution

  • You can use Bowman to consume JSON+HAL resources in JAVA. This library greatly simplifies the consumption of resources comparing to RestTemplate as shown in this article.

    This library answers the "automatic link following" part :

    Our client is a wrapper around Spring HATEOAS and Jackson with a heavy JPA influence. Retrieving an object from the remote returns a proxy of the returned object, instrumented using Javassist, whose accessors can transparently conduct further remote service invocations in accordance with its HAL links. This allows linked and inline associations to both be defined in the same way in the client model and greatly simplifies client code.