Spring boot rest service, как заставить его маршалировать ссылки как свойства?

Первый вопрос вот так будь нежнее:)

У меня есть проект JPA, который я хочу представить как REST. Я сделал это до сих пор:

Моя сущность:

@Entity
public class SignUpSheet {
    @Id
    @GeneratedValue
    private Long id;

    @Column
    private String name;

    @Column
    private String description;

    @Column
    @Temporal(TemporalType.TIMESTAMP)
    private Date dateTime;

    @ManyToOne
    private User parent;

    @OneToMany
    private List<Volunteer> volunteers;

    //getter and setters
}

Все хорошо, я звоню добавил spring-boot-starter-data-rest к моему pom, и теперь я получаю услугу. Вот JSON, я вернусь.

http://localhost:8080/api-0.1.0/signUpSheets/1

{
  "name": "Auction",
  "description": "My First Sign Up Sheet",
  "dateTime": "2015-04-22T03:47:12.000+0000",
  "volunteers": [
   {
    "role": "Bringing stuff",
    "comments": "I have comments!"
   }
   ], 
  "endpoint": "/signUpSheets",
  "_links": {
    "self": {
      "href": "http://localhost:8080/api-0.1.0/signUpSheets/1"
    },
    "parent": {
      "href": "http://localhost:8080/api-0.1.0/signUpSheets/1/parent"
    },
    "user": {
      "href": "http://localhost:8080/api-0.1.0/signUpSheets/1/user"
    } 
  }
}

Супер! Почти то, что я ожидал. Теперь я вызываю свой сервис, используя Spring RestTemplate, и вот где я застрял. Когда он маршалирует обратно в объект SignUpSheet, он вытягивает большую часть объекта, но поле идентификатора является нулевым (что имеет смысл, поскольку в Json нет поля идентификатора, только собственная ссылка), и все объекты OneToMany и ManyToOne являются нуль (я полагаю, по той же причине).

У меня вопрос: как мне сказать Spring Hateoas добавить идентификатор в json или указать Джексону, как добавить его в поле идентификатора? Кроме того, как я могу получить ссылки? Если бы мне не пришлось маршалировать обратно в сущность JPA, а вместо этого создать еще один POJO для SignUpSheet (что-то, чего я хотел бы избежать в целях дублирования, но о котором можно поговорить, если это необходимо / желательно по какой-то причине, по которой я скучаю). Я добавил Jackson2HalModule в мой ObjectMapper, но это, кажется, не имеет значения, есть ли он там или нет.

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper o = new ObjectMapper();
    o.registerModule(new Jackson2HalModule());
    return o;
}

Заранее спасибо за помощь!

================================================== =====

Решение:

Первый шаг, прочитайте инструкцию:)

Итак, я узнал, что мне нужно расширить ResourceSupport для моих недавно созданных DTO. Сделано и сделано. Но я не получал никаких ссылок назад! Похоже, мне нужно было добавить Jackson2HalModule к объекту отображения на RestTemplate следующим образом:

    ObjectMapper o = new ObjectMapper();
    o.registerModule(new Jackson2HalModule());
    MappingJackson2HttpMessageConverter c = new MappingJackson2HttpMessageConverter();
    c.setObjectMapper(o);
    restTemplate.getMessageConverters().add(0, c);

Поэтому я полагаю, что буду расширять RestTemplate и @Component, и я подхожу для любого ресурса HATEOAS.

2 ответа

Решение

Я не думаю, что вы должны пытаться десериализовать JSON обратно в вашу сущность JPA. Сущность JPA очень тесно связана с базой данных вашего приложения и должна рассматриваться как деталь реализации сервера. Вместо этого я бы порекомендовал сопоставить типу, который специально смоделирован по REST API, а не по структуре вашей базы данных и использованию вами JPA.

Вы используете Spring Data REST, который сильно охватывает гипермедиа. Это означает, что клиенты должны использовать URI для идентификации ресурсов и ссылок для навигации между ними. Например, на стороне клиента лист регистрации уже имеет идентификатор; это href из self ссылка в ответе. Следовательно, нет необходимости предоставлять идентификатор из вашей сущности JPA. В самом деле, при этом будут раскрыты детали реализации вашего приложения, о которых клиенты не должны знать.

Вместо того, чтобы пытаться заполнить все свойства в ответе, вместо этого Spring Data REST предоставляет ссылки. Например, чтобы получить доступ к родителю регистрационного листа, вы должны извлечь href из parent ссылку из ответа и выполнить GET запрос на URI.

Вам нужно продлить RepositoryRestConfigurerAdapter чтобы сказать вам нужен Id для экспорта, например:

public class RepositoryConfig extends RepositoryRestConfigurerAdapter {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(SignUpSheet.class);
 }
}
Другие вопросы по тегам