Why does RestTemplate not bind response representation to PagedResources?

11,075

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

This dilemma can be solved in two different ways:

  1. Providing a type that matches the representation in the first place. Thus, craft a custom class and either stick to the property names of the representation or customize it using Jackson annotations etc.

  2. Set up a custom MappingJackson2HttpMessageConverter and customize the ObjectMapperto get the Jackson2HalModule configured that Spring HATEOAS ships out of the box.

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.registerModule(new Jackson2HalModule());
    
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
    converter.setObjectMapper(mapper);
    
    RestTemplate template = new RestTemplate(Collections.<HttpMessageConverter<?>> singletonList(converter));
    
Share:
11,075
user3563584
Author by

user3563584

Updated on June 07, 2022

Comments

  • user3563584
    user3563584 almost 2 years

    I am using spring-data-rest to expose entities as (paged) rest resources. Everything works fine, but when I request data via RestTemplate, I get an useless HATEOAS JSON (which I didn't ask for). The JSON seems to be a PagedResources. I could live with that, but the JSON isn't converted into an object correctly. There is no content inside.

    Repository:

    @RepositoryRestResource(collectionResourceRel = "people", path = "people")
    public interface PersonRepository extends PagingAndSortingRepository<Person, Long>
    {
        List<Person> findByLastName(@Param("name") String name);
    }
    

    Client:

    public List<Person> getPersons()
    {
        RestTemplate rt = new RestTemplate();
        System.out.println(rt.getForObject(URL, PagedResources.class).getContent().size());
        System.out.println(rt.getForObject(URL, PagedResources.class).getLinks().size());
        System.out.println(rt.getForObject(URL, PagedResources.class).getMetadata().getTotalElements());
        return new ArrayList<Person>(rt.getForObject(URL, PagedResources.class).getContent()); // <-- empty
    }
    

    System.out:

    0 // getContent().size()
    4 // getLinks().size()
    2 // getTotalElements()
    

    curl:

    C:\...>curl http://localhost:8080/spring-jsf-rest/rest/people
    {
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/spring-jsf-rest/rest/people{?page,size,sort}",
          "templated" : true
        },
        "search" : {
          "href" : "http://localhost:8080/spring-jsf-rest/rest/people/search"
        }
      },
      "_embedded" : {
        "people" : [ {
          "firstName" : "John",
          "lastName" : "Rambo",
          "_links" : {
            "self" : {
              "href" : "http://localhost:8080/spring-jsf-rest/rest/people/1"
            }
          }
        }, {
          "firstName" : "Chuck",
          "lastName" : "Norris",
          "_links" : {
            "self" : {
              "href" : "http://localhost:8080/spring-jsf-rest/rest/people/2"
            }
          }
        } ]
      },
      "page" : {
        "size" : 20,
        "totalElements" : 2,
        "totalPages" : 1,
        "number" : 0
      }
    }
    

    It seems like _embedded is not mapped correctly to content?!

  • user3563584
    user3563584 about 10 years
    big thanks for your help. option 2 looks nice. but i get "Unrecognized field "templated" (class org.springframework.hateoas.Link), not marked as ignorable (one known property: "href"])". i guess i have to dig deeper. if i cant get it to work, i guess ill stick to option 1.
  • norgence
    norgence about 10 years
    I think you can simply get rid off this by setting objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOW‌​N_PROPERTIES, false);. Jackson is quite strict by default. Updated the answer accordingly.
  • Stefan Falk
    Stefan Falk about 6 years
    Hm, if I do that things break for me - any idea?
  • Soumitri Pattnaik
    Soumitri Pattnaik over 5 years
    @OliverDrotbohm I am having the same issue, the difference is I am not using RestTemplate instead I am using FeignClient. What can I do?