Я развернул AWS Lambda, написанный на Kotlin, используя Spring Cloud Function.Когда я тестирую его с запросом json
{"id":"1",
"name":"John"
}
, я получаю следующую ошибку:
"No suitable constructor found for type [simple type, class step.Request]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: lambdainternal.util.NativeMemoryAsInputStream@4b53f538; line: 1, column: 2]",
"errorType": "com.fasterxml.jackson.databind.JsonMappingException",
"stackTrace": [
"com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)",
"com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1106)",
"com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:296)",
"com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133)",
"com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1511)",
"com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1102)"
Если я запускаю свое приложение локально и выполняю запрос POST на http://localhost:8080/function стот же запрос json, он работает нормально.
Хотя я знаю, что могу добиться этого, добавив аннотации @JsonCreator и @JsonProperty в класс Request, но я хочу избежать этого и хочу понять причину сбоя при запускеэто как лямбда.
Любые входы очень ценятся.Заранее спасибо
Соответствующий код выглядит следующим образом:
package step
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Primary
import org.springframework.stereotype.Component
import java.util.function.Function
@SpringBootApplication
class F1 {
@Bean
@Primary
fun objectMapper() = ObjectMapper().apply {
this.registerModule(KotlinModule())
}
}
data class Request (val id: String, val name: String)
data class Response(val message: String)
class Handler : SpringBootRequestHandler<Request, Response>()
@Component("function")
class Function :
Function<Request, Response> {
override fun apply(t: Request): Response {
println("$t")
return Response("${t.id}:${t.name}")
}
}
fun main(args: Array<String>) {
SpringApplication.run(F1::class.java, *args)
}
build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer
import org.jetbrains.kotlin.noarg.gradle.NoArgExtension
buildscript {
var springBootVersion: String by extra
springBootVersion = "2.0.0.RELEASE"
var wrapperVersion: String by extra
wrapperVersion = "1.0.12.BUILD-SNAPSHOT"
var shadowVersion: String by extra
shadowVersion = "2.0.1"
var kotlinVersion: String by extra
kotlinVersion = "1.2.70"
repositories {
mavenCentral()
maven("https://repo.spring.io/snapshot")
maven("https://repo.spring.io/milestone")
}
dependencies {
classpath(kotlinModule("gradle-plugin", kotlinVersion))
classpath("com.github.jengelman.gradle.plugins:shadow:$shadowVersion")
classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-noarg:$kotlinVersion")
}
}
var springCloudVersion: String by extra
springCloudVersion = "1.0.0.BUILD-SNAPSHOT"
var awsLambdaVersion: String by extra
awsLambdaVersion = "1.1.0"
var awsLambdaEventsVersion: String by extra
awsLambdaEventsVersion = "1.2.1"
extra["reactor.version"] = "3.1.7.RELEASE"
plugins {
kotlin("jvm") version "1.3.0-rc-57"
java
maven
idea
}
group = "stepfunctions"
version = "1.0-SNAPSHOT"
apply {
plugin("maven")
plugin("kotlin")
plugin("kotlin-spring")
plugin("org.jetbrains.kotlin.plugin.noarg")
plugin("io.spring.dependency-management")
plugin("org.springframework.boot")
plugin("com.github.johnrengelman.shadow")
}
repositories {
mavenLocal()
mavenCentral()
maven("https://repo.spring.io/snapshot")
maven("https://repo.spring.io/milestone")
maven { setUrl("http://dl.bintray.com/kotlin/kotlin-eap") }
}
dependencies {
compile("org.jetbrains.kotlin", "kotlin-stdlib-jdk8", extra.get("kotlinVersion") as String)
compile("org.jetbrains.kotlin", "kotlin-reflect", extra.get("kotlinVersion") as String)
compile("org.springframework.cloud", "spring-cloud-function-adapter-aws", extra.get("springCloudVersion") as String)
compile("org.springframework.cloud", "spring-cloud-starter-function-web", extra.get("springCloudVersion") as String)
compile("io.github.microutils:kotlin-logging:1.5.4")
compile("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.0")
compileOnly("com.amazonaws:aws-lambda-java-events:$awsLambdaEventsVersion")
compileOnly("com.amazonaws", "aws-lambda-java-core", extra.get("awsLambdaVersion") as String)
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
tasks.withType<ShadowJar> {
classifier = "function"
manifest {
attributes(
mapOf(
"Start-Class" to "step.F1",
"Main-Class" to "step.F1"
)
)
}
dependencies {
exclude("org.springframework.cloud:spring-cloud-function-web:1.0.0.BUILD-SNAPSHOT")
}
mergeServiceFiles()
append("META-INF/spring.handlers")
append("META-INF/spring.schemas")
append("META-INF/spring.tooling")
transform(PropertiesFileTransformer::class.java) {
paths = listOf("META-INF/spring.factories")
mergeStrategy = "append"
}
}
tasks.getByPath("assemble").dependsOn("shadowJar")