Spring HATEOAS неправильная ссылка на связанные ресурсы

Я использую Spring Boot 2.0.3, Spring Data REST, Spring HATEOAS. Моя модель предметной области достаточно структурирована, но в последнее время я обнаружил странное поведение собственных ссылок.

Я собираюсь показать часть модели, чтобы указать на проблему, удалив бесполезную часть:

Проверка зрения:

@EntityListeners(value = EyeExamListener.class)
public class EyeExam extends AbstractEntity {

    @NotNull
    @JoinColumn(name = "contact_id", updatable = false)
    @JsonDeserialize(using = ContactUriDeserializer.class)
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private Contact contact;

    @NotNull
    @Column(nullable = false, columnDefinition = "DATE")
    private Instant date;

Контакт:

@EntityListeners({ContactListener.class})
public class Contact extends AbstractEntity {

    @NotNull
    @Enumerated(EnumType.STRING)
    @Column(nullable = false, columnDefinition = "VARCHAR(30) DEFAULT 'CUSTOMER'")
    private ContactType type = ContactType.CUSTOMER;

    @NotNull
    @Enumerated(EnumType.STRING)
    @Column(nullable = false, columnDefinition = "VARCHAR(30) DEFAULT 'NATURAL_PERSON'")
    private PersonType personType = PersonType.NATURAL_PERSON;

    private String firstName;

    private String lastName;

    private String companyName;

Это КонтактРепозиторий:

@Transactional
@PreAuthorize("isAuthenticated()")
public interface ContactRepository extends JpaRepository<Contact, Long> {
 ....
 ....
}

Когда я получаю определенный ресурс EyeExam (https://myserver.com/api/v1/eyeExams/13), Spring возвращает:

  {
  "sid" : "f16d6e45-477f-11e9-898e-9d6f4f2f5990",
  "createdBy" : "system",
  "createdDate" : "2017-05-31T17:38:00Z",
  "lastModifiedDate" : null,
  "lastModifiedBy" : null,
  "createdByName" : "System",
  "lastModifiedByName" : null,
  "date" : "2017-05-31T00:00:00Z",

  "_links" : {
    "self" : {
      "href" : "https://myserver.com/api/v1/eyeExams/13"
    },
    "eyeExam" : {
      "href" : "https://myserver.com/api/v1/eyeExams/13{?projection}",
      "templated" : true
    },
    "supplyTypes" : {
      "href" : "https://myserver.com/api/v1/eyeExams/13/supplyTypes"
    },
    "changeStatus" : {
      "href" : "https://myserver.com/api/v1/eyeExams/13/changeStatus?status=%7Bstatus%7D"
    },
    "contact" : {
      "href" : "https://myserver.com/api/v1/eyeExams/13/contact{?projection}",
      "templated" : true
    },
    "store" : {
      "href" : "https://myserver.com/api/v1/eyeExams/13/store{?projection}",
      "templated" : true
    }
  }
}

Как видите, я получаю ссылку на связанный ресурс Контакт. Все в порядке. Теперь я получаю ресурс https://myserver.com/api/v1/eyeExams/13/контакт, и Spring отвечает:

{
  "sid" : "4c2ba300-477e-11e9-898e-9d6f4f2f5990",
  "createdBy" : "system",
  "createdDate" : "2018-11-01T09:00:00Z",
  "lastModifiedDate" : null,
  "lastModifiedBy" : null,
  "createdByName" : "System",
  "lastModifiedByName" : null,
  "type" : "CUSTOMER",
  "personType" : "NATURAL_PERSON",
  "firstName" : "John",
  "lastName" : "Smith",
  "companyName" : null,  
  "_links" : {
    "self" : {
      "href" : "https://myserver.com/api/v1/contact/22352"
    },
    "contact" : {
      "href" : "https://myserver.com/api/v1/contact/22352{?projection}",
      "templated" : true
    },
    "notes" : {
      "href" : "https://myserver.com/api/v1/contacts/22352/notes"
    },
    "auditLogs" : {
      "href" : "https://myserver.com/api/v1/contacts/22352/auditLogs"
    },
    "media" : {
      "href" : "https://myserver.com/api/v1/contacts/22352/media"
    },
    "privacyAgreements" : {
      "href" : "https://myserver.com/api/v1/contacts/22352/privacyAgreements"
    },
    "eyeExams" : {
      "href" : "https://myserver.com/api/v1/contacts/22352/eyeExams"
    },
    "eyeExamsCount" : {
      "href" : "https://myserver.com/api/v1/contacts/22352/eyeExams/count"
    },
    "documents" : {
      "href" : "https://myserver.com/api/v1/contacts/22352/documents"
    },
    "pendingSalesOrders" : {
      "href" : "https://myserver.com/api/v1/contacts/22352/pendingSalesOrders"
    },
    "lastPurchasedFrames" : {
      "href" : "https://myserver.com/api/v1/contacts/22352/lastPurchasedFrames"
    },
    "store" : {
      "href" : "https://myserver.com/api/v1/contact/22352/store{?projection}",
      "templated" : true
    }
  }
}

Я хочу указать ссылку на себя. Это неправильно, на самом деле должно быть https://myserver.com/api/v1/contacts/22352 с окончанием -s.

Я использовал какой-то пользовательский ResourceProcessor, но даже без них у меня та же проблема.

Прямо сейчас я создал обходной путь в ContactResourceProcessor, переписав собственную ссылку на правильную, но я хотел бы понять, делаю ли я что-то неправильно, если это ошибка или я просто что-то пропустил.

Какие аннотации уровня класса у вас есть в интерфейсе ContactRepository?

Selindek 16.03.2019 16:17

@Selindek Я добавил репозиторий в вопрос.

drenda 16.03.2019 18:22
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
365
1

Ответы 1

Вероятно, это ошибка, но попробуйте этот обходной путь:

@RepositoryRestResource(path = "contacts")
@Transactional
@PreAuthorize("isAuthenticated()")
public interface ContactRepository extends JpaRepository<Contact, Long> {
 ....
 ....
}

Я пробовал, но у меня не работает. Мне пришлось переписать ссылку на себя в ResourceProcessor

drenda 18.03.2019 18:44

Другие вопросы по теме