I am using Java to create an app for Google Assistant that will call an external REST API and return certain responses based on trigger phrases. I currently can use the Default Welcome Intent to return simple text responses through the Actions on Google simulator. However, when I try to call an external REST API and send back a response, the simulator returns a message that says:
"MalformedResponse: Failed to parse Dialogflow response into AppResponse because of empty speech response."
I am using the org.springframework.web.client.RestTemplate
from Spring-framework to process the result from the REST Service (https://fitzroi-rest-api-0525.appspot.com/rest/Fitz) with the following call:
greeting = restTemplate.getForObject("https://fitzroi-rest-api-0525.appspot.com/rest/{name}", Greeting.class, givenName);
(This works well in a regular Spring project, but not within the Actions on Google Intent)
An example training phrase for my test app is "Tony is sending greetings." From here I am extracting "Tony" as a @sys.given-name
entity in Dialogflow. This name is then passed to the REST serivice for processing. The REST service is an MVC app that is running in a separate Google Cloud project from the Google Assistant App.
Please let me know if this is a good approach to consume a REST service using Dialogflow fullfillment webhook.
Below is a sample code from my webhook that is trying to consume the REST service.
@ForIntent("process-greeting")
public ActionResponse greetingProcessor(ActionRequest request) {
LOGGER.info("Trying to process greeting intent");
ResponseBuilder responseBuilder = getResponseBuilder(request);
String givenName = (String) request.getParameter("given-name");
if (givenName != null && !givenName.isEmpty()) {
RestTemplate restTemplate = new RestTemplate();
Greeting greeting = null;
greeting = restTemplate.getForObject("https://fitzroi-rest-api-0525.appspot.com/rest/{name}", Greeting.class, givenName);
// LOGGER.info("Attempting to send back " + greeting.getContent() + " to Google Assistant");
if (greeting == null)
responseBuilder.add("The rest service did not return a response.");
else
responseBuilder.add(greeting.getContent());
}
LOGGER.info("Welcome intent end.");
return responseBuilder.build();
}
It seems that since actions-on-google
requires thread-safe function calls, the RestTemplate
from spring-framework
does not work in an app-engine
app. I was able to find a walk-around by using a sample code provided by the actions-on-google
team on GitHub. This code requires that you parse the results from the URL from within the ActionsApp
instead of using a library. For example:
URL restURL = new URL("http://yourdomain.com/your/rest/call");
URLConnection conn = restURL.openConnection();
InputStreamReader reader = new InputStreamReader(
(InputStream) conn.getContent());
JsonParser parser = new JsonParser();
JsonElement root = parser.parse(reader);
MyObject = myParseFunction(root);
I also had a serious issue (UnKonwnHostException) parsing the results from a remote URL. This documentation was helpful.