I'm trying to consume a RESTful Web Service
with Spring
and my reference code is the one in this guide. The service that I'm interrogating returns JSON
like the following:
{ "id": 1,
"content": [
{ "dependencies": [
{ "parent": 0, "child": 1, "type": "PUNCT" },
{ "parent": 0, "child": 2, "type": "NPADVMOD" },
{ "parent": 0, "child": 3, "type": "PUNCT" } ],
"tokens": [
{ "ent": "", "index": 0, "lemma": "hello", "pos": "INTJ", "tag": "UH", "text": "Hello" },
{ "ent": "", "index": 1, "lemma": ",", "pos": "PUNCT", "tag": ",", "text": "," },
{ "ent": "PERSON", "index": 2, "lemma": "world", "pos": "PROPN", "tag": "NNP", "text": "World" },
{ "ent": "", "index": 3, "lemma": "!", "pos": "PUNCT", "tag": ".", "text": "!" } ]
} ]
}
I have created the following objects (all their methods are omitted for brevity):
@JsonIgnoreProperties(ignoreUnknown = true)
public class Token {
private String ent;
private int index;
private String lemma;
private String pos;
private String tag;
private String text;
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class Dependency {
private int parent;
private String type;
private int child;
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class Content {
private List<Token> tokens;
private List<Dependency> dependencies;
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class Message {
private long id;
private List<Content> content;
}
With the following code, I can successfully deserialise a Message
object:
@RequestMapping("/message")
public String message() {
return "{\"content\": [{\"dependencies\": [{\"child\": 1,\"type\": \"PUNCT\",\"parent\": 0},{\"child\": 2,\"type\": \"NPADVMOD\",\"parent\": 0},{\"child\": 3,\"type\": \"PUNCT\",\"parent\": 0}],\"tokens\": [{\"index\": 0,\"text\": \"Hello\",\"tag\": \"UH\",\"lemma\": \"hello\",\"pos\": \"INTJ\",\"ent\": \"\"},{\"index\": 1,\"text\": \",\",\"tag\": \",\",\"lemma\": \",\",\"pos\": \"PUNCT\",\"ent\": \"\"},{\"index\": 2,\"text\": \"World\",\"tag\": \"NNP\",\"lemma\": \"world\",\"pos\": \"PROPN\",\"ent\": \"PERSON\"},{\"index\": 3,\"text\": \"!\",\"tag\": \".\",\"lemma\": \"!\",\"pos\": \"PUNCT\",\"ent\": \"\"}]}],\"id\": 1}";
}
@RequestMapping("/decode")
public Boolean decode() {
RestTemplate restTemplate = new RestTemplate();
Message response = restTemplate.getForObject("http://localhost:8080/message", Message.class);
logger.info("I got: {}", response);
return Boolean.TRUE;
}
as I can see in the log:
17:26:34.609 [qtp990226843-17] INFO a.c.j.controllers.ExampleController - Message[content = [Content[dependencies = [Dependency[child = 1, parent = 0, type = PUNCT], Dependency[child = 2, parent = 0, type = NPADVMOD], Dependency[child = 3, parent = 0, type = PUNCT]], tokens = [Token[ent = , index = 0, lemma = hello, pos = INTJ, tag = UH, text = Hello], Token[ent = , index = 1, lemma = ,, pos = PUNCT, tag = ,, text = ,], Token[ent = PERSON, index = 2, lemma = world, pos = PROPN, tag = NNP, text = World], Token[ent = , index = 3, lemma = !, pos = PUNCT, tag = ., text = !]]]], id = 1]
If I try to connect directly to the RESTful Web Service
with the following code:
@RequestMapping("/remote")
public Boolean remote() {
RestTemplate restTemplate = new RestTemplate();
Map<String, String> env = System.getenv();
String host = env.getOrDefault("MY_HOST", "localhost");
String port = env.getOrDefault("MY_HOST", "7890");
String url = String.format("http://%s:%s", host, port);
String content = "Hello, World!";
URI uri = UriComponentsBuilder.fromHttpUrl(url).queryParam("content", content).build().encode().toUri();
Message response = REST_TEMPLATE.getForObject(uri, Message.class);
logger.info("I got: {}", response);
return Boolean.TRUE;
}
I observe the following error:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri Jun 02 16:53:42 BST 2017
There was an unexpected error (type=Internal Server Error, status=500).
org.springframework.web.util.NestedServletException: Request processing failed;
nested exception is org.springframework.web.client.RestClientException:
Could not extract response: no suitable HttpMessageConverter found for response
type [class ai.context_scout.joshi.model.Message] and content type
[text/plain;charset=utf-8]
I search online and in this site to find a solution, but I couldn't think of any keyword that led to meaningful results... any help?
Why I get this error? How to fix it?
Thanks!
PS: I just tried to implement a dumb service
that connects to the remote service
and returns the JSON received by that service as a String, and I modified the decode service
that was already able to deserialise the JSON to get the data from the dumb service
rather than the remote service
and it works! I'm flabbergasted! It doesn't make sense!
Anyway, for reference, the code is as follows (please let me know if it is possible to avoid to use the dumb service
):
@RequestMapping("/dumb")
public String dumb() {
Map<String, String> env = System.getenv();
String host = env.getOrDefault("SPACY_HOST", "localhost");
String port = env.getOrDefault("SPACY_HOST", "7890");
String url = String.format("http://%s:%s", host, port);
String content = "Hello, World!";
URI uri = UriComponentsBuilder.fromHttpUrl(url).queryParam("content", content).build().encode().toUri();
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(uri, String.class);
logger.info("I got: {}", response);
return response;
}
@RequestMapping("/decode")
public Boolean decode() {
RestTemplate restTemplate = new RestTemplate();
Message response = restTemplate.getForObject("http://localhost:8080/dumb", Message.class);
logger.info("I got: {}", response);
return Boolean.TRUE;
}