HAL ссылки с существительным в единственном числе вместо существительного во множественном числе при переходе по rel-links - PullRequest
0 голосов
/ 31 января 2019

Я использую Spring Boot (2.1.1) для автоматического создания HAL REST API моих JpaRepository интерфейсов.

В большинстве случаев эти интерфейсы пусты, например:

public interface ProjectRepository extends JpaRepository<Project, Long> {}

public interface ProtocolRepository extends JpaRepository<Protocol, Long> {}

A Project сущность содержит много Protocol сущностей.И у Protocol объекта есть обратная ссылка на Project объект.

Когда я посещаю http://localhost:8080/admin/protocols/4711, я получаю ссылку на его проект:

...
"project": {
  "href": "http://localhost:8080/admin/protocols/4711/project"
}
...

Нокогда я перехожу по этой ссылке, все дальнейшие ссылки генерируются с ошибками:

  ...
  "_links": {
    "self": {
      "href": "http://localhost:8080/admin/project/1"
    },
    "project": {
      "href": "http://localhost:8080/admin/project/1"
    }
  ...
  }
  ...

Ошибка в ссылке заключается в том, что вместо единственного числа projects.

* используется единственное существительное project.1023 * Поскольку эти ссылки генерируются автоматически, неясно, как можно изменить это поведение.

1 Ответ

0 голосов
/ 31 января 2019

При отладке внутренних компонентов Spring я выяснил, что PersistentEntityResourceAssembler использует экземпляр DefaultSelfLinkProvider для создания собственных ссылок.Когда я отладил этот класс, я понял, что он не работает правильно, когда для объекта, который проксируется Hibernate, генерируется собственная ссылка.

Поэтому я попытался заменить DefaultSelfLinkProvider моей собственной реализацией SelfLinkProvider -интерфейс.

Это можно сделать с помощью BeanPostProcessor:

  @Bean
  public BeanPostProcessor entityManagerBeanPostProcessor()
  {
    return new BeanPostProcessor()
    {
      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
      {
        return bean;
      }

      @Override
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
      {
        if (bean instanceof SelfLinkProvider)
        { return new HibernateSelfLinkProvider((SelfLinkProvider) bean); }
        return bean;
      }
    };
  }

А HibernateSelfLinkProvider - это простая обертка вокруг SelfLinkProvider:

public class HibernateSelfLinkProvider implements SelfLinkProvider
{
  private final SelfLinkProvider selfLinkProvider;

  public HibernateSelfLinkProvider(SelfLinkProvider selfLinkProvider)
  {
    this.selfLinkProvider = selfLinkProvider;
  }

  @Override
  public Link createSelfLinkFor(Object instance)
  {
    instance = Hibernate.unproxy(instance);
    return selfLinkProvider.createSelfLinkFor(instance);
  }
}

Приятной особенностью Hibernate.unproxy() является то, что он оставляет данный объект неизменным, если он не является прокси-объектом.

С этим дополнением я получаю правильную ссылку: "http://localhost:8080/admin/projects/1".Но я не уверен, что это лучшее место для изменения поведения.

...