【问题标题】:Why Spring HATEOAS returns duplicate links causing JSON deserialization exception?为什么 Spring HATEOAS 返回导致 JSON 反序列化异常的重复链接?
【发布时间】:2016-01-19 23:48:48
【问题描述】:

原版实体用户 -

public class User implements Serializable {
    private static final long serialVersionUID = 262950482349139355L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "FIRST_NAME", nullable = false, unique = false)
    @Convert(converter = NameConverter.class)
    private String firstName;

    @Column(name = "LAST_NAME", nullable = false, unique = false)
    @Convert(converter = NameConverter.class)
    private String lastName;

    @Column(name = "PHONE_NUM", nullable = false, unique = false)
    @Convert(converter = PhoneNumberConverter.class)
    private String phoneNum;

    @Column(name = "EMAIL", nullable = true, unique = false)
    @Convert(converter = OptionalStringConverter.class)
    private Optional<String> email;
}

在 URL 中更改了主机名的搜索结果 - 存在 2 个 _links

{
  "_links" : {
    "self" : {
      "href" : "http://hostname/users/search/findByLastName?lastName=doe{&page,size,sort}",
      "templated" : true
    }
  },
  "_embedded" : {
    "users" : [ {
      "firstName" : "John",
      "lastName" : "Doe",
      "phoneNum" : "111-111-1111",
      "email" : null,
      "_links" : { },
      "_embedded" : { },
      "_links" : {
        "self" : {
          "href" : "http://hostname/users/1",
          "templated" : false
        }
      }
    } ]
  },
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  }
}

编辑

单独访问资源时不存在重复链接。但是,当客户端(在我的例子中是微服务)使用 RestTemplate 发出请求时,响应会返回 2 _links,如上所示。

@Override
public Collection<Long> getUserIdsByFirstName(String firstName) {
    String findByFirstNameUri = UriComponentsBuilder.fromUriString(userServiceUrl)
        .path("/users/search/findByFirstName").queryParam("firstName", firstName).toUriString();

// This is where ResponseEntity.body would have the 2 _links, if ResponseEntity<String> were used. I used a custom object to weed that out.
ResponseEntity<UserSearchResult> userSearchResult = restTemplate.exchange(findByFirstNameUri, GET, dummyEntity,
        UserSearchResult.class);
     ...
}

我正在使用 Spring Data JPA、Spring Data Rest、Spring HATEOAS 和 Spring Cloud。这是我的 Github 上的 link to the project

完全披露:我在 Spring HATEOAS Github 上提交了一个问题。

【问题讨论】:

  • 请向我们展示您在哪里组装资源的代码。实体和预期结果是不够的。我们在自己的软件中做了一个非常相似的事情,而且效果很好。
  • @ThomasUhrig 我不收集资源。我正在使用 Spring JPA 为我做这件事。我更新了我的帖子,澄清了这一点,并提供了代码链接。
  • 我不想浏览您的 GitHub 存储库来修复您的问题。请贴出相关代码。在这种情况下,实体和结果不相关。如果我浏览您的存储库 - 只是理论上 - 我会说您使用 PersistentEntityResourceAssembler 在控制器中组装您的资源。但在您这样做之前,您手动将链接放置到UserSearchResult 。所以是的,你组装了资源,但你做错了。所以显示该代码。
  • 假设,如果我正在组装User 资源,我会很乐意展示代码。您是否要查看链接,这取决于您。需要明确的是,我从未要求您为我“修复”任何事情,但仅仅在开放论坛上做出回应就意味着愿意提供帮助。还是谢谢。
  • 论坛规则说“发布代码,而不仅仅是链接”! (见stackoverflow.com/help/on-topic)。我要求您这样做并解释您显示的代码是不够的,但您仍然不这样做。如果您没有在我的评论中得到讽刺(这很强烈!):我查看了您的 GitHub 存储库并命名了您的问题所在的确切类。你检查过这个吗?

标签: json spring spring-data-jpa spring-hateoas hal


【解决方案1】:

首先,您使用的是 spring-data-rest 而不仅仅是 spring-hateoas。所以你没有资源也没有控制器。我认为这是这里的主要误解。

我认为您的自定义存储库有问题。

我会改变两件事:

  • 从 UserRepositoryCustomImpl 中删除 @Repository
  • 使 UserRepository 扩展 UserRepositoryCustom

所以

public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom

public class UserRepositoryCustomImpl implements UserRepositoryCustom

这是实现自定义存储库方法所需的:

另见http://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/#repositories.custom-implementations

【讨论】:

  • 我不使用UserRepositoryCustom,我最初玩弄了这个想法,但最终没有使用它。 UserRepository 只是扩展 JpaRepository public interface UserRepository extends JpaRepository&lt;User, Long&gt; {...}
  • 我确认UserRepositoryCustom 与此问题无关(通过删除UserRepositoryCustom)。我在帖子中添加了更多信息。
猜你喜欢
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-16
相关资源
最近更新 更多