Spring-hateoas: Cannot retrieve embedded collection of resources

Created on 28 Jan 2015  路  8Comments  路  Source: spring-projects/spring-hateoas

I have a Spring-Data-Rest project that exposes Question objects. I would like to retrieve this list using Spring-Hateoas, but when I make my request, the embedded Questions appear as links in the Resource object rather than as full Question objects. This means I would need to re-fetch each question to get the actual content, even though the content was already provided in the actual response. Is this intentional behavior?

My client code looks like this:

        ResponseEntity<Resources<Question>> responseEntity =
                restTemplate.exchange("https://example.com/data/questions",
                                HttpMethod.GET, null, 
                        new ParameterizedTypeReference<Resources<Question>>() {}, 
                        Collections.emptyMap());

        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            Resources<Question> questionsResource = responseEntity.getBody();
            Collection<Question> questions = questionsResource.getContent();
        }

This code executes, but the questions Collection is empty. When I call getLinks(), I see that all of my Question objects are listed there (as Link objects), despite not being returned as links in the HTTP response.

I have the same experience when I use Resource<Question> instead of Resources<Question>.

Here is an example of the response from .../data/questions:

{
    "_links": {
        "self": {
            "href": "https://example.com/data/questions{?page,size,sort}",
            "templated": true
        },
        "next": {
            "href": "https://example.com/data/questions?page=1&size=20{&sort}",
            "templated": true
        },
        "search": {
            "href": "https://example.com/data/questions/search"
        }
    },
    "_embedded": {
        "questions": [
            {
                "questionText": "What is your favorite color?",
                "_links": {
                    "self": {
                        "href": "https://example.com/data/questions/1"
                    }
                }
            }
    }
}
question

Most helpful comment

A) how is your RestTemplate getting configured?
B) show the RestTemplare call used to retrieve the collection resource
C) the type to extract from the collection should be Resources<Resource<Question>>. The collection has links as does each each entry of the collection.

All 8 comments

For general questions, please use StackOverflow. Also, if you think you think the issue is related to Spring Data REST, please use the corresponding bug tracker.

That said, the scenario you describe is a bit inconsistent. You show a request to a collection resource but state to find "links in the Resource object". What you show then is the simple default representation of a collection resource containing the full question object you complain about missing in the first place. So as far I can see the server behaves as expected.

Your client not being able to bind the result correctly is probably be caused by the RestTemplate not set up correctly. Suspiciously looks like this question on StackOverflow.

@olivergierke - thanks for the response. I don't think this is an issue with Spring-Data-Rest. It is possible i am misunderstanding something about using Spring-Data-Rest in the server, or Spring Hateoas in a client, so SO would make sense, but I've read all the documentation I could find and everything seems to be working smoothly, so I thought this seemed like either a bug or a lack of documentation issue which should be addressed more directly.

Let me clarify my question a bit:

I believe I've implemented the server in Spring Data REST correctly, but if something looks inconsistent, please let me know. I have a Question class annotated with @Entity and a QuestionRepository that seems to work fine.

When I make a GET request to .../data/questions, I see the JSON response posted above, which seems to have the expected format. (It seems odd to me that the returned questions are _embedded, but that's the way SDR has always worked for me).

When I use RestTemplate to make this call, and then try and access the data, questions is empty:

            Resources<Question> questionsResource = responseEntity.getBody();
            Collection<Question> questions = questionsResource.getContent();

However, when I inspect the questionsResource, the Resources.links field has a list of all my Question objects. This seems to tell me the Spring-Hateoas recognizes there are embedded Question objects, but doesn't provide a way to retrieve them.

So I have two questions:

1) Why can't I get embedded entities out of the Resources (or Resource) class? Is this a feature missing from Spring-Hateoas, or am I doing it wrong? You mentioned in the StackOverflow question:

PagedResources does not have an _embedded property, that's why you don't get the content property populated.

Is that by design? Shouldn't PagedResources have an _embedded property, especially since this is the format Spring-Data-Rest to returns results in? And especially because it is the _embedded data that is being paginated?

2) As a corollary, (and this really is a question for Spring-Data-Rest), does it make sense for the QuestionRepository to return the list of Questions as _embedded? Shouldn't the Questions just be returned directly in the JSON? Am I doing something wrong or is that an intentional descision in Spring-Data-Rest?

As to your linked StackOverflow question, that does seem to be the same or similar issue. I don't understand what you mean by the first solution "Providing a type that matches the representation in the first place." - a type to match what representation? There is already a Person (or in my case Question) class, aren't all the other classes represented by Spring-Hateoas provided classes?

I hope this explains my concern.

I am having the same issue...

A) how is your RestTemplate getting configured?
B) show the RestTemplare call used to retrieve the collection resource
C) the type to extract from the collection should be Resources<Resource<Question>>. The collection has links as does each each entry of the collection.

Thanks for the quick Response. Your comment C helped me resolving issue.

It is such a difficult task to debug this. Your answer helped.

I am facing problem when i am using failover or Hystrix. As it is failover how do i recreate Resources> so that i can send some static data during failure. To reiterate how do i create instances of Resources Object and make it behave like HETEOAS by manual forging. Any example ?

I'm documenting this here for historical reasons:

If you are using Spring HATEOAS 1.1, see https://docs.spring.io/spring-hateoas/docs/1.1.0.M3/reference/html/#client.rest-template for official documentation on how to use our client configuration API for RestTemplate.

If you are using 1.0.x or earlier, then I recommend registering a RestTemplate as a bean somewhere in your application, and retrieve it from the application context. It will have the message converters registered to handle hypermedia.

With a RestTemplate configured to consume hypermedia, you can then invoke it per traditional means.

Was this page helpful?
0 / 5 - 0 ratings