Consuming Spring-hateoas Rest service using Spring RestTemplate and Super type t...
source link: http://www.java-allandsundry.com/2014/01/consuming-spring-hateoas-rest-service.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Consuming Spring-hateoas Rest service using Spring RestTemplate and Super type tokens
Spring-hateoas provides an excellent way for applications to create REST based services which follow the HATEOAS principle.
My objective here is not to show how to create the service itself, but to demonstrate how to write a client to the service.
The sample service that I am going to use is the "the-spring-rest-stack" written by Josh Long(@starbuxman). The specific subproject that I am going to use is the hateoas one here. If this subproject is run using "mvn jetty" command, a REST based endpoint to list the details of a user is available at http://localhost:8080/users/2 where "2" is the id of the user and gives a result of the following structure:
{
"links"
: [{
"rel"
:
"self"
,
}, {
"rel"
:
"customers"
,
}, {
"rel"
:
"photo"
,
}],
"id"
:
2
,
"firstName"
:
"Lois"
,
"profilePhotoMediaType"
:
null
,
"lastName"
:
"Lane"
,
"username"
:
"loislane"
,
"password"
:
null
,
"profilePhotoImported"
:
false
,
"enabled"
:
true
,
"signupDate"
:
1370201631000
}
{
"links"
: [{
"rel"
:
"self"
,
}, {
"rel"
:
"user"
,
}],
"id"
:
17
,
"signupDate"
:
1372461079000
,
"firstName"
:
"Scott"
,
"lastName"
:
"Andrews"
,
"databaseId"
:
17
}
public
class
Resource<T>
extends
ResourceSupport {
protected
Resource() {
this
.content =
null
;
}
public
Resource(T content, Link... links) {
this
(content, Arrays.asList(links));
}
...
Resource<User> user = ....
//call to the service
Resource<Customer> customer = ...
//call to the service
ObjectMapper objectMapper =
new
ObjectMapper();
Resource<Customer> customer = objectMapper.readValue(customerAsJson, Resource.
class
);
Resource<User> user = objectMapper.readValue(userAsJson, Resource.
class
);
The fix is to use a Super Type Token, which is essentially a way to provide the type information for libraries like Jackson and I have blogged about it before here. With this, a working code to map the json to the appropriate parameterized type would look like this:
ObjectMapper objectMapper =
new
ObjectMapper();
Resource<Customer> customer = objectMapper.readValue(customerAsJson,
new
TypeReference<Resource<Customer>>() {});
Resource<User> customer = objectMapper.readValue(userAsJson,
new
TypeReference<Resource<User>>() {});
Spring RestTemplate provides its own implementation of Super Type token to be able to bind different message formats to parameterized types, along the lines of Jackson's TypeReference, it is called the ParameterizedTypeReference.
ParameterizedTypeReference can be used to cleanly bind Rest responses for User and Customer to Java types this way:
RestTemplate restTemplate =
new
RestTemplate();
ResponseEntity<Resource<User>> responseEntity =
restTemplate.exchange(
"http://localhost:8080/users/2"
, HttpMethod.GET,
null
,
new
ParameterizedTypeReference<Resource<User>>() {}, Collections.emptyMap());
if
(responseEntity.getStatusCode() == HttpStatus.OK) {
Resource<User> userResource = responseEntity.getBody();
User user = userResource.getContent();
}
RestTemplate restTemplate =
new
RestTemplate();
ResponseEntity<Resource<Customer>> responseEntity =
restTemplate.exchange(
"http://localhost:8080/users/2/customers/17"
, HttpMethod.GET,
null
,
new
ParameterizedTypeReference<Resource<Customer>>() {}, Collections.emptyMap());
if
(responseEntity.getStatusCode() == HttpStatus.OK) {
Resource<Customer> customerResource = responseEntity.getBody();
Customer customer = customerResource.getContent();
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK