使用 RestTemplate 使用子资源 link 时出错

Error consuming subresources link with RestTemplate

我们正在开发一个公开 API 的服务器,以及一个使用它的网络应用程序。服务器使用 spring-boot (1.2.4.RELEASE) 和 spring-data-rest。 Web 应用程序使用 spring-hateoas 来消耗 API。我们在使用 PagedResources 时没有问题,但是当我们尝试访问关系列表时 link 抛出异常。

ResponseEntity<PagedResources<Resource<Project>>> projectsPaged = restTemplate().exchange(
    "http://localhost:8080/projects", 
    HttpMethod.GET, 
    null, 
    new ParameterizedTypeReference<PagedResources<Resource<Project>>>() {}
);
Collection<Resource<Project>> resourcesProjects = projectsPaged.getBody().getContent();
List<Project> projectsWithTranslations = new ArrayList<>();
for (Resource<Project> resourceProject : resourcesProjects) {
    ResponseEntity<Resources<Resource<ProjectT>>> resultTranslations = restTemplate().exchange(
        resourceProject.getLink("translations").getHref(), 
        HttpMethod.GET, 
        null, 
        new ParameterizedTypeReference<Resources<Resource<ProjectT>>>() {}
    ); // here is where the exception is thrown
    log.error("N. TRANSLATIONS: " + resultTranslations.getBody().getContent().size());
}

RestTemplate是这样创建的(resourceDetails()方法配置ClientCredentialsResourceDetails):

OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails(), new DefaultOAuth2ClientContext());

HttpClient httpClient = HttpClients.createDefault();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));

ObjectMapper o = new ObjectMapper();
o.registerModule(new Jackson2HalModule());
o.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
o.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false);
MappingJackson2HttpMessageConverter c = new MappingJackson2HttpMessageConverter();
c.setObjectMapper(o);
restTemplate.getMessageConverters().add(0, c);

项目 url 产生这个 JSON (http://localhost:8080/projects):

{
    "_links" : {
        "self" : {
            "href" : "http://localhost:8080/projects/actives{?page,size,sort}",
            "templated" : true
        }
    },
    "_embedded" : {
        "projects" : [ {
            "code" : "XK63489",
            ...
            "_links" : {
                "self" : {
                    "href" : "http://localhost:8080/projects/1"
                },
                "translations" : {
                    "href" : "http://localhost:8080/projects/1/translations"
                }
            }
        } ]
    },
    "page" : {
        "size" : 20,
        "totalElements" : 1,
        "totalPages" : 1,
        "number" : 0
    }
}

这是我们要消费的 JSON (http://localhost:8080/projects/1/translations):

{
  "_embedded" : {
    "projectTs" : [ {
      "locale" : "es",
      "name" : "Spanish name",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/projectTs/7"
        },
        "project" : {
          "href" : "http://localhost:8080/projectTs/7/project"
        }
      }
    },
    ...
    ]
  }
}

当我们尝试消耗第二个 JSON 时抛出此异常:

2015-06-12 14:22:10.212 ERROR 2968 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request] with root cause

org.springframework.web.client.HttpClientErrorException: 400 Bad Request
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
    at org.springframework.security.oauth2.client.http.OAuth2ErrorHandler.handleError(OAuth2ErrorHandler.java:165)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:614)
    ...

这是服务器抛出的异常:

2015-06-12 14:22:10.199 ERROR 1895 --- [nio-8080-exec-3] s.d.r.w.AbstractRepositoryRestController : Map has no value for 'repository'

java.lang.IllegalArgumentException: Map has no value for 'repository'
    at org.springframework.web.util.UriComponents$MapTemplateVariables.getValue(UriComponents.java:276)
    at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:221)

我们的代码有什么问题? 提前致谢。

我们找到了解决方案。

这是检索资源 link:

信息的正确代码
RequestEntity<Void> request = RequestEntity.get(URI.create(resourceProject.getLink("translations").getHref())).accept(MediaTypes.HAL_JSON).build();
ResponseEntity<Resources<Resource<ProjectT>>> resultTranslations = restTemplate().exchange(
    request,
    new ParameterizedTypeReference<Resources<Resource<ProjectT>>>() {}
);