在Spring Rest数据上创建具有RestTemplate的对象之间的关联(HATEOAS)

时间:2015-07-29 14:00:12

标签: spring resttemplate spring-data-rest spring-hateoas

我正在努力通过RestTemplate在Spring Data Rest API上操作对象(它们是JPA实体)。

我有一个树形结构,其中流派有父母和其他类型的孩子(这是itunes genre tree

创建一个对象很好:

URI selfLink = restTemplate.postForLocation(api+"/genre", genre, Collections.emptyMap());

与它建立关联并不是那么容易。如果我试图像这样建立一个父协会:

headers.setContentType(new MediaType("text", "uri-list"));
...
restTemplate.put(selfLink.toString()+"/parent", entity, parentGenreURI );

我在客户端遇到500内部服务器错误,但是在REST API端吞下了实际错误,并且日志中没有任何内容。

如果我尝试使用父亲的uri来修补URI本身:

headers.setContentType(MediaType.APPLICATION_JSON);
...
Map map = ImmutableMap.of("parent", parentGenreLink);
restTemplate.exchange(selfLink.toString()+"/parent", HttpMethod.PATCH, entity, String.class, map);

我在客户端上收到400 Bad Request错误,在服务器上收到错误

  

org.springframework.http.converter.HttpMessageNotReadableException:   无法读取类型类型的对象   从请求!嵌套异常是   org.springframework.http.converter.HttpMessageNotReadableException:   无法读取有效载荷!嵌套异常是   com.fasterxml.jackson.databind.JsonMappingException:没有要映射的内容   由于输入结束

这让我觉得这是正确的做法,但我只是做错了。

有人能为此提供一些指导吗?我见过的每个例子都使用curl,这对我没有多大帮助:)

在SO上有一些类似的回答问题,但是大多数问题都指向不再存在的文档,或者有这些简单的对象,所有内容都被转储到地图中。

2 个答案:

答案 0 :(得分:2)

查看您发布的少量代码以及您收到的错误,我认为您以错误的方式调用了您的服务。

我在这里以第二个电话为例,但由于我认为你在两个电话中都犯了同样的错误,所以第一个错误的解决方案应该是类似的。

如果我们查看您正在调用RestTemplate.exchange的文档,我们可以看到它需要以下参数:

  1. 要致电的网址
  2. 使用方法
  3. 要发送的 HttpEntity
  4. 回复的类别
  5. 要在网址
  6. 中替换的参数值

    在我认为你出错的地方是参数3和5.在我看来你是在试图发送JSON有效载荷

    {
      "parent": "someGenre"
    }
    

    但是你实际上在做的是告诉模板用 parentGenreLink的值替换URL中字符串 {parent} (URL参数占位符)的任何出现。

    您可能想要做的是将地图设置为 HttpEntity 上的正文,而不是传递任何网址参数:

    // Create the body
    Map map = ImmutableMap.of("parent", parentGenreLink);
    
    // Create the headers
    Headers headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    
    // Create the HTTP Entity
    HttpEntity<?> entity = new HttpEntity<>(map, headers);
    
    // Make the call without any URL parameters
    restTemplate.exchange(selfLink.toString()+"/parent", HttpMethod.PATCH, entity, String.class);
    

    请注意,要实现此功能,您必须拥有一个能够在模板上(de)序列化JSON设置的消息转换器:

    RestTemplate restTemplate = new RestTemplate();
    
    List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    messageConverters.add(new MappingJacksonHttpMessageConverter());
    restTemplate.setMessageConverters(messageConverters);
    

答案 1 :(得分:0)

除了@Raniz所建议的,另一种方法是:

HttpHeaders reqHeaders = new HttpHeaders();
reqHeaders.add(HttpHeaders.CONTENT_TYPE, new MediaType("text", "uri-list").toString());
HttpEntity<String> reqEntity = new HttpEntity<String>(category0link.getHref(), reqHeaders);
ResponseEntity<String> string = template.exchange(widget0link.getHref(),  HttpMethod.PUT, reqEntity, String.class, ImmutableMap.of());