1
votes

Using Java8 in eclipse AWS SDK, I've created and uploaded a lambda function that is hooked in upon fulfillment of my lex intent. Lambda has not problem receiving JSON request and parsing. Then, I format a simple "Close" dialogAction response and send back to lex and receive the following error from the Test Bot page in the lex console:

    An error has occurred: Received invalid response from Lambda: 
    Can not construct instance of IntentResponse: 
    no String-argument constructor/factory method to deserialize 
    from String value
    ('{"dialogAction
    {"type":"Close","fulfillmentState":"Fulfilled","message":
    {"contentType":"PlainText","content":"Thanks I got your info"}}}') 
    at [Source: "{\"dialogAction\":
    {\"type\":\"Close\",\"fulfillmentState\":\"Fulfilled\",\"message\":
   {\"contentType\":\"PlainText\",\"content\":\"Thanks I got your 
   info\"}}}";line: 1, column: 1]

It seems to have a problem right away with the format (line 1, column 1), but my JSON string looks ok to me. Before returning the output string in the handleRequest java function, I am writing the it to the Cloudwatch log and it writes as follows:

{
   "dialogAction": {
        "type": "Close",
        "fulfillmentState": "Fulfilled",
        "message": {
            "contentType": "PlainText",
            "content": "Thanks I got your info"
        }
    }
}

Things I've tried:

  • Removing the message element as it's not required
  • Adding in non-required properties like sessionAttributes, responseCard, etc
  • removing the double quotes
  • replacing double quotes with single quotes
  • hardcoding json from sample response format message in documentation

Is there something hidden at the http headers level or is java8 doing something to the JSON that is not visible?

4
This thread seems like it's addressing the same problem: stackoverflow.com/questions/44756575/…Mark
It is similar yes, but my issue is with Lex processing the response from Lambda, not Lambda processing the request from Lex (which I am able to do).Mattbob

4 Answers

2
votes

Not sure if this is because I'm using Java8 or not, but a return value of "String" from the RequestHandler class handleRequest method will not work. Yes, String is an object, but the constructors on the Lex side are expecting an "Object". I was converting my lex response POJO to a String before returning it in the handleRequest method. That was my mistake.

I fixed it by changing the return type of the handleRequest method to be "Object" instead of "String".

public Object handleRequest(Object input, Context context)

instead of

public String handleRequest(Object input, Context context) 

You also have to implement the

 public class LambdaFunctionHandler implements RequestHandler<Object, Object>

not

public class LambdaFunctionHandler implements RequestHandler<Object, String>

This solved my issue.

2
votes

In my case I was facing exactly the same issue and was able to fix it by creating specific response POJO type and using this POJO as the return type for 'handleRequest' method. E.g. BotResponse.java as follow:

public class BotResponse implements Serializable{
    private static final long serialVersionUID = 1L;

    public DialogAction dialogAction = new DialogAction();

    public DialogAction getDialogAction() {
        return dialogAction;
    }

    public void setDialogAction(DialogAction dialogAction) {
        this.dialogAction = dialogAction;
    }
}

Note, I have also added the 'implements Serializable' just to be on safer side. Probably it is an overkill. Not sure why but for me returning a well formatted JSON String object did not worked even after changing the return type of 'handleRequest' method to 'Object'.

0
votes

I know this is an old question however thought this might help some else

@Mattbob Solution dint fix my issue, However he is in the right path. Best approach is to use a Response object, a custom response object and make the lambda return the custom response object. So i went to the Documentation and created a custom object that looks Response format here

http://docs.aws.amazon.com/lex/latest/dg/lambda-input-response-format.html

At the time of answering question i couldnt find an object in SDK that matched the response Object so i had to recreate but if some one knows please comment below

 Class xxxxx implements RequestHandler<Object, AccountResponse> {

@Override
public AccountResponse handleRequest(Object input, Context context) {

} }

Lambda will look somewhat like this and just populate and return the object to match response structure and error goes away. Hope this helps.

0
votes

Whenever we are returning the object to the bot from the backend make sure we need to pass content type along with content. But here we are passing wrong. So wE need to pass as like below. It is in Node.js

 let message = {
        contentType: "PlainText",
        content: 'Testing bot'
      };