Почему RestTemplate не привязывает представление ответа к PagedResources?

Я использую spring-data-rest для предоставления объектов в качестве (выгружаемых) ресурсов отдыха. Все работает нормально, но когда я запрашиваю данные через RestTemplate, я получаю бесполезный HATEOAS JSON (который я не просил). JSON выглядит как PagedResources. Я мог бы с этим смириться, но JSON неправильно преобразуется в объект. Внутри нет content.

Репозиторий:

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

Клиент:

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
}

Системный выход:

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

завиток:

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
  }
}

Кажется, что _embedded неправильно сопоставляется с контентом?!


person user3563584    schedule 23.04.2014    source источник
comment
В будущем вы, возможно, захотите переосмыслить то, как вы задаете вопросы здесь. Если что-то бесполезно для вас, не используйте его. Пожалуйста, не заявляйте, что вы ничего не просили, если вы явно отправляете GET запрос. Как обычно с компьютерами, вы в точности получаете то, что просите. Если вы не укажете заголовок Accept, вы получите значение по умолчанию, то есть application/hal+json. Вообще говоря, такой негативный тон не создает стимула к ответу. Тем не менее, я потратил время. Добро пожаловать. PS: Кстати, что такое HATEOAS JSON?   -  person Oliver Drotbohm    schedule 24.04.2014
comment
@Oliver: я признаю, мой тон несколько негативен. но эти маленькие препятствия раздражают. конечно, я пробовал другие заголовки accept, но результат всегда один и тот же. и я не единственный, у кого есть проблемы с этим: stackoverflow.com/q/23264044/3563584. также я не хотел использовать вещи, я должен.   -  person user3563584    schedule 24.04.2014
comment
Аааа, так вот как вы анализируете список _embedded на клиенте, говоря RestTemplate ожидать один из классов ресурсов ненависти. Очень полезно, документация spring-data-rest довольно скудна на стороне клиента.   -  person dan carter    schedule 21.11.2014


Ответы (1)


Как вы правильно заметили, PagedResources не имеет свойства _embedded, поэтому свойство content не заполняется.

Эту дилемму можно решить двумя способами:

  1. Предоставление типа, который соответствует представлению в первую очередь. Таким образом, создайте собственный класс и либо придерживайтесь имен свойств представления, либо настройте его, используя аннотации Джексона и т. д.

  2. Настройте собственный MappingJackson2HttpMessageConverter и настройте ObjectMapper, чтобы настроить Jackson2HalModule, который Spring HATEOAS поставляет из коробки.

    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));
    
person Oliver Drotbohm    schedule 24.04.2014
comment
большое спасибо за вашу помощь. вариант 2 выглядит красиво. но я получаю нераспознанное шаблонное поле (класс org.springframework.hateoas.Link), не помеченное как игнорируемое (одно известное свойство: href]). я думаю, я должен копать глубже. если я не могу заставить его работать, я думаю, что буду придерживаться варианта 1. - person user3563584; 25.04.2014
comment
Я думаю, вы можете просто избавиться от этого, установив objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);. Джексон довольно строг по умолчанию. Обновил ответ соответственно. - person Oliver Drotbohm; 25.04.2014
comment
Хм, если я сделаю это для меня все сломается - есть идеи? - person Stefan Falk; 02.04.2018
comment
@OliverDrotbohm У меня та же проблема, разница в том, что я не использую RestTemplate, а использую FeignClient. Что я могу сделать? - person Soumitri Pattnaik; 19.12.2018