使用 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>>>() {}
);
我们正在开发一个公开 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>>>() {}
);