处理@RepositoryRestResource

时间:2017-11-19 13:35:32

标签: spring jackson spring-data-jpa spring-data-rest

前言

我想在一个调用中创建另一个资源的子资源。这些资源具有@ManyToMany关系:用户和组。

想要首先创建一个用户,然后是该组,然后在Working with Relationships in Spring Data REST中显示该关系 - 仅仅是因为我认为它上面不存在的资源只有当一个用户也与该资源相关联时,才应创建自己(例如组)。为此,我需要一个端点like this one(这对我不起作用,否则我不会在这里)创建一个组,并设置相关的"播种"用户在一次交易中。

目前,让这项工作成功的唯一方法是"同步"手动关系如下:

public void setUsers(Set<AppUser> users) {
    users.forEach(u -> u.getGroups().add(this));
    this.users = users;
}

这将允许我

POST http://localhost:8080/groups

{
  "name": "Group X",
  "users": ["http://localhost:8080/users/1"]
}

但我的问题是,这对我来说感觉不对 - 它似乎是一种解决方法,而不是实际的Spring方式使这个要求工作。所以..

我目前正在努力使用Spring @RepositoryRestResource创建关系资源。我想创建一个新组并将其与调用用户关联,如下所示:

POST http://localhost:8080/users/1/groups

{
  "name": "Group X"
}

但唯一的结果是回复204 No Content。我不知道为什么。这可能与我的另一个问题有关或可能没有关系(参见here),我试图通过在JSON有效载荷中设置相关资源来实现同样的目标 - 这也不起作用。

服务器端我收到以下错误:

tion$ResourceSupportHttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class org.springframework.hateoas.Resources<java.lang.Object>]]: java.lang.NullPointerException

如果您需要任何特定代码,请与我们联系。

试过

我将exported = false添加到@RepositoryRestResource的{​​{1}}:

UserGroupRepository

我正在发送:

@RepositoryRestResource(collectionResourceRel = "groups", path = "groups", exported = false)
public interface UserGroupRepository extends JpaRepository<UserGroup, Long> {
    List<UserGroup> findByName(@Param("name") String name);
}

但是,服务器端的结果仍为PATCH http://localhost:8080/users/1 { "groups": [ { "name": "Group X" } ] } 204 No Content

单元测试

基本上,以下单元测试应该可以工作,但我也可以回答为什么这不能正常工作,这也说明了如何正确完成。

ResourceNotFoundException

然而,行

@Autowired
private TestRestTemplate template;

private static String USERS_ENDPOINT = "http://localhost:8080/users/";
private static String GROUPS_ENDPOINT = "http://localhost:8080/groups/";

// ..

@Test
@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
public void whenCreateUserGroup() {

    // Creates a user
    whenCreateAppUser();

    ResponseEntity<AppUser> appUserResponse = template.getForEntity(USERS_ENDPOINT + "1/", AppUser.class);
    AppUser appUser = appUserResponse.getBody();

    UserGroup userGroup = new UserGroup();
    userGroup.setName("Test Group");
    userGroup.setUsers(Collections.singleton(appUser));

    template.postForEntity(GROUPS_ENDPOINT, userGroup, UserGroup.class);

    ResponseEntity<UserGroup> userGroupResponse = template.getForEntity(GROUPS_ENDPOINT + "2/", UserGroup.class);

    Predicate<String> username = other -> appUser.getUsername().equals(other);

    assertNotNull("Response must not be null.", userGroupResponse.getBody());

    assertTrue("User was not associated with the group he created.",
            userGroupResponse.getBody().getUsers().stream()
                    .map(AppUser::getUsername).anyMatch(username));
}

将破坏此测试并返回userGroup.setUsers(Collections.singleton(appUser));

1 个答案:

答案 0 :(得分:0)

根据SDR reference

  

POST

     

仅支持集合关联。向集合添加新元素。支持的媒体类型:

     

#include <stdio.h> extern FILE *stderr, *stdin, *stdout; - 指向要添加到关联的资源的URI。

所以要将text/uri-list添加到group,请尝试执行此操作:

user

其他info