【问题标题】:Proper Java handleRequest() method signature for Amazon Echo/Alexa on Amazon Lambda?Amazon Lambda 上的 Amazon Echo/Alexa 的正确 Java handleRequest() 方法签名?
【发布时间】:2015-11-18 11:29:48
【问题描述】:

我正在尝试创建一个用 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;
    }
}

但是,当尝试使用来自 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 方法)","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","stackTrace":["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 方法)","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 example):

{
  "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"
  }
}

因此,显然 Amazon SpeechletRequestEnvelope 不是 handleRequest() 的正确输入类。

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

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

【问题讨论】:

    标签: java amazon-web-services aws-lambda alexa-skills-kit alexa-skill


    【解决方案1】:

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

    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());
            }
        }
    }
    

    请注意,这个类实现了RequestStreamHandler,而不是RequestHandler

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

    ====================函数输出====================

    IntentRequest 名称:MyColorIsIntent

    ...而 context.getLogger().log(outString); 导致同一行在线写入 Amazon Lambda 控制台。

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

    • commons-codec-1.6.jar
    • commons-lang3-3.x.jar
    • jackson-annotations-2.3.2.jar
    • jackson-core-2.3.2.jar
    • jackson-databind-2.3.2.jar
    • JakartaCommons-IO-2.4.jar
    • joda-time-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-skills-kit-1.0.jar

    可以从Maven CentralAlexaSkillsKit.zip 中的“第三方”子文件夹下载这些 JAR。

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

    1. 在 Eclipse 中右键单击 Lambda 项目的根目录
    2. 点击“属性”
    3. 选择“Java 构建路径”
    4. 选择“库”标签
    5. 点击“添加 JAR”
    6. 浏览到“lib”
    7. 选择“lib”文件夹中的所有 JAR,然后单击“确定”,直到您返回 Eclipse 主屏幕

    感谢 @jephers 指向 Github 上这个很棒的教程,我从那里拼凑了很多:

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

    【讨论】:

      【解决方案2】:

      我扩展了 jo.echo.lambda.utils.SpeechletLambda (https://github.com/jjaquinta/EchoProofOfConcepts/blob/master/jo.echo.lambda/jo/echo/lambda/utils/SpeechletLambda.java),这对我有用:

      @Override
      public void handleRequest(InputStream inputStream,
              OutputStream outputStream, Context context) throws IOException
      {
          super.handleRequest(inputStream, outputStream, context);
      }
      

      希望对你有帮助

      【讨论】:

      • SpeechletLambda.java 最初来自哪里?您能否提供指向亚马逊网站上来源的链接?
      • node.js 的文档很好 - 对于 Java,不太好。这是 jo 关于使用 Java 和 Lambda 创建技能的教程:github.com/jjaquinta/EchoProofOfConcepts/tree/master/…
      • 啊,谢谢! Github 上的教程绝对有帮助。看起来至少有几个项目出了问题。我会为正在发生的事情输入一个完整的答案,但绝对要为资源 +1!
      猜你喜欢
      • 1970-01-01
      • 2011-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多