Amazon Lambda上适用于Amazon Echo/Alexa的Java handleRequest()方法签名?

Sea*_*eau 3 java amazon-web-services aws-lambda alexa-skill alexa-skills-kit

我正在尝试创建一个用Java实现的Amazon Lambda函数,以便与Amazon Echo/Alexa一起使用.我正在使用Eclipse Mars作为IDE.

以下是我LambdaFunctionHandler将收到Alexa请求的内容,如下所示:

public class LambdaFunctionHandler implements RequestHandler<SpeechletRequestEnvelope, SpeechletResponse> {

    @Override
    public SpeechletResponse handleRequest(SpeechletRequestEnvelope input, Context context) {
        context.getLogger().log("Input: " + input);

        // TODO: implement your handler
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当尝试使用Alexa的示例JSON输入进行测试时,我在Eclipse中收到错误:

{"errorMessage":"JSON解析期间发生错误","errorType":"java.lang.RuntimeException","stackTrace":[],"cause":{"errorMessage":"Lcom/fasterxml/jackson/databind /ObjectMapper;","errorType":"java.lang.NoClassDefFoundError","stackTrace":[java.lang.Class.getDeclaredFields0(Native Method)","java.lang.Class.privateGetDeclaredFields(Class.java:2583 ) " "java.lang.Class.getDeclaredFields(Class.java:1916)", "com.fasterxml.jackson.databind.introspect.AnnotatedClass._findFields(AnnotatedClass.java:689)"," com.fasterxml.jackson. databind.introspect.AnnotatedClass.resolveFields(AnnotatedClass.java:470) "" com.fasterxml.jackson.databind.introspect.AnnotatedClass.fields(AnnotatedClass.java:282)", "com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addFields(POJOPropertiesCollector.java:390)", "com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collect(POJOPropertiesCollector.java:243)", "com.fasterxml.jackson.databind.introspect.BasicClassIntrospector.collectProperties(BasicClassIntrospector.java:197)", "com.fasterxml.jackson.databind.introspect.BasicClassIntrospector.forDeserialization(BasicClassIntrospector.java:110)","com.fasterxml .jackson.databind.introspect.BasicClassIntrospector.forDeserialization(BasicClassIntrospector.java:15) " "com.fasterxml.jackson.databind.DeserializationConfig.introspect(DeserializationConfig.java:703)"," com.fasterxml.jackson.databind.deser .DeserializerCache._createDeserializer(DeserializerCache.java:330)", "com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:265)", "com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:245)", "com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:143)", "com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:439)","com.fasterxml.jackson .databind.ObjectReader._prefetchRootDeserializer(ObjectReader.java:1588) " "com.fasterxml.jackson.databind.ObjectReader.(ObjectReader.java:185)"," com.fasterxml.jackson.databind.ObjectMapper._newReader(ObjectMapper.的java:558)", "com.fasterxml.jackson.databind.ObjectMapper.reader(ObjectMapper.java:3098)"],"原因":{ "的errorMessage": "com.fasterxml.jackson.databind.ObjectMapper", "ERRORTYPE": "抛出java.lang.ClassNotFoundException", "堆栈跟踪":["java.net.URLClassLoader.findClass(URLClassLoader.java :381)","java.lang.ClassLoader.loadClass(ClassLoader.java:424)","java.lang.ClassLoader.loadClass(ClassLoader.java:357)","java.lang.Class.getDeclaredFields0(Native Method) ) " "java.lang.Class.privateGetDeclaredFields(Class.java:2583)", "java.lang.Class.getDeclaredFields(Class.java:1916)"," com.fasterxml.jackson.databind.introspect.AnnotatedClass. _findFields(AnnotatedClass.java:689) " "com.fasterxml.jackson.databind.introspect.AnnotatedClass.resolveFields(AnnotatedClass.java:470)"," com.fasterxml.jackson.databind.introspect.AnnotatedClass.fields(AnnotatedClass.java:282) " "com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addFields(POJOPropertiesCollector.java:390)"," com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collect( POJOPropertiesCollector.java:243)","com.fasterxml.jackson.databind.introspect.BasicClassIntrospector.collectProperties(BasicClassIntrospector.java:197)","com.fasterxml.jackson.databind.introspect.BasicClassIntrospector.forDeserialization(BasicClassIntrospector.java: 110) " "com.fasterxml.jackson.databind.introspect.BasicClassIntrospector.forDeserialization(BasicClassIntrospector.java:15)", "com.fasterxml.jackson.databind.DeserializationConfig.introspect(DeserializationConfig.java:703)"," COM .fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:330) " "com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:265)"," com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.的java:245)", "com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:143)", "com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:439)", "com.fasterxml.jackson.databind.ObjectReader._prefetchRootDeserializer(ObjectReader.java:1588)", "com.fasterxml.jackson.databind.ObjectReader.(ObjectReader.java:185)","com.fasterxml.jackson.databind. ObjectMapper._newReader(ObjectMapper.java:558) "" com.fasterxml.jackson.databind.ObjectMapper.reader(ObjectMapper.java:3098)"]}}}

这是我的JSON输入(取自在线的TestColors示例):

{
  "session": {
    "new": false,
    "sessionId": "session1234",
    "attributes": {},
    "user": {
      "userId": null
    },
    "application": {
      "applicationId": "amzn1.echo-sdk-ams.app.[unique-value-here]"
    }
  },
  "version": "1.0",
  "request": {
    "intent": {
      "slots": {
        "Color": {
          "name": "Color",
          "value": "red"
        }
      },
      "name": "MyColorIsIntent"
    },
    "type": "IntentRequest",
    "requestId": "request5678"
  }
}
Run Code Online (Sandbox Code Playgroud)

所以,显然亚马逊SpeechletRequestEnvelope不是正确的输入类handleRequest().

handleRequest()接收Alexa请求的正确方法签名是什么?

我找不到适用于Alexa/Echo的Amazon Lambda的Java示例.

Sea*_*eau 6

这是一个完整的工作示例:

public class LambdaFunctionHandler implements RequestStreamHandler {

    @Override
    public void handleRequest(InputStream inputStream, OutputStream output, Context context) throws IOException {
        byte serializedSpeechletRequest[] = IOUtils.toByteArray(inputStream);
        SpeechletRequestEnvelope requestEnvelope = SpeechletRequestEnvelope.fromJson(serializedSpeechletRequest);
        SpeechletRequest speechletRequest = requestEnvelope.getRequest();

        if (speechletRequest instanceof IntentRequest) {
            IntentRequest ir = (IntentRequest) speechletRequest;
            String outString = "IntentRequest name: " + ir.getIntent().getName();
            context.getLogger().log(outString);
            output.write(outString.getBytes());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,此类实现RequestStreamHandlerNOT RequestHandler.

使用问题中的输入JSON,output.write(outString.getBytes())将导致输出到Eclipse AWS Lambda控制台:

====================功能输出====================

IntentRequest名称:MyColorIsIntent

...同时context.getLogger().log(outString);在线将相同的行写入Amazon Lambda控制台.

您还需要确保/lib项目中有一个文件夹,并且需要包含以下JAR:

  • 公地编解码器1.6.jar
  • 公地lang3-3.x.jar
  • 杰克逊的注解 - 2.3.2.jar
  • 杰克逊核心2.3.2.jar
  • 杰克逊 - 数据绑定 - 2.3.2.jar
  • JakartaCommons-IO-2.4.jar
  • 乔达时间,2.3.jar
  • log4j.1.2.17.jar
  • servlet的API-3.0.jar
  • SLF4J-API-1.7.4.jar
  • SLF4J-log4j12-1.7.4.jar
  • Alexa的技能-KIT-1.0.jar

这些JAR可以从Maven Central下载,也可以从AlexaSkillsKit.zip中的"第三方"子文件夹下载.

在Eclipse中,您需要刷新项目以便它看到/lib目录中的JAR文件(只需按F5),然后将JAR添加到Java构建路径:

  1. 在Eclipse中右键单击Lambda项目的根目录
  2. 点击"属性"
  3. 选择"Java Build Path"
  4. 选择"库"选项卡
  5. 点击"添加JAR"
  6. 浏览到"lib"
  7. 选择"lib"文件夹中的所有JAR,然后单击"确定",直到返回主Eclipse屏幕

感谢@jephers指向Github上这个伟大教程的指针,我把它拼凑在一起:

https://github.com/jjaquinta/EchoProofOfConcepts/tree/master/jo.echo.lambda