0

Creating a simple spring boot project using kotlin+Gradle and I get the following error from AWS

ATEST]7eaf7391bd074416bb2acc17a521a803, AWS_LAMBDA_INITIALIZATION_TYPE=on-demand, AWS_XRAY_DAEMON_ADDRESS=169.254.79.2:2000, _AWS_XRAY_DAEMON_PORT=2000, AWS_XRAY_CONTEXT_MISSING=LOG_ERROR, AWS_LAMBDA_FUNCTION_VERSION=$LATEST, AWS_ACCESS_KEY=ASIAU7C4QO4VEP4KLVH2, AWS_LAMBDA_FUNCTION_NAME=swaves-beach-rate}
00:14:04.221 [main] INFO org.springframework.cloud.function.adapter.aws.CustomRuntimeInitializer - AWS Handler: org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler
00:14:04.321 [main] INFO lambdainternal.AWSLambda - Starting AWSLambda using Java 11.0.11 on 169.254.24.133 with PID 8 (/var/runtime/lib/aws-lambda-java-runtime-0.2.0.jar started by sbx_user1051 in /var/task)
00:14:04.321 [main] DEBUG lambdainternal.AWSLambda - Running with Spring Boot, Spring
00:14:04.321 [main] INFO lambdainternal.AWSLambda - No active profile set, falling back to default profiles: default
00:14:04.323 [main] DEBUG org.springframework.boot.SpringApplication - Loading source class com.aio.swaves.SwavesApplication
00:14:04.767 [main] DEBUG org.springframework.context.support.GenericApplicationContext - Refreshing org.springframework.context.support.GenericApplicationContext@204f30ec
00:14:04.807 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
00:14:07.024 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
00:14:07.028 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
00:14:07.039 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
00:14:07.059 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
00:14:07.083 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'swavesApplication'
00:14:07.099 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'greet'
00:14:07.139 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.AutoConfigurationPackages'
00:14:07.140 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.cloud.function.adapter.aws.CustomRuntimeEventLoop'
00:14:07.205 [main] INFO lambdainternal.AWSLambda - Started AWSLambda in 3.652 seconds (JVM running for 4.394)
00:14:08.210 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework
No function defined: java.lang.IllegalStateException
java.lang.IllegalStateException: No function defined
    at org.springframework.cloud.function.context.AbstractSpringFunctionAdapterInitializer.apply(AbstractSpringFunctionAdapterInitializer.java:189)
    at org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler.handleRequest(SpringBootStreamHandler.java:55)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)

END RequestId: 7ea16b3f-47d5-4763-b9fe-f97d940cf55c
REPORT RequestId: 7ea16b3f-47d5-4763-b9fe-f97d940cf55c  Duration: 5006.33 ms    Billed Duration: 5007 ms    Memory Size: 1024 MB    Max Memory Used: 166 MB Init Duration: 546.69 ms    

build.gradle.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.github.jengelman.gradle.plugins.shadow.transformers.*
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
    id("org.springframework.boot") version "2.5.4"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    id("com.github.johnrengelman.shadow") version "7.0.0"

    kotlin("jvm") version "1.5.21"
    kotlin("plugin.spring") version "1.5.21"
}

group = "com.aio"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
}

val springCloudVersion = "2020.0.3"
val awsLambdaEventsVersion = "3.10.0"
val awsLambdaCoreVersion = "1.2.1"

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-webflux")
    implementation("org.springframework.cloud:spring-cloud-function-web")
    implementation("org.springframework.cloud:spring-cloud-function-adapter-aws")
    implementation("org.jsoup:jsoup:1.14.2")

    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

    runtimeOnly("com.amazonaws:aws-lambda-java-core:${awsLambdaCoreVersion}")
    runtimeOnly("com.amazonaws:aws-lambda-java-events:${awsLambdaEventsVersion}")

    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude(module = "junit")
        exclude(module = "mockito-core")
    }
    testImplementation("io.projectreactor:reactor-test")
    testImplementation("org.junit.jupiter:junit-jupiter-api")
    testImplementation("com.ninja-squad:springmockk:3.0.1")

    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}

dependencyManagement {
    imports {
        mavenBom("org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}")
    }
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "11"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

tasks.assemble{
    dependsOn("shadowJar")
}

tasks.withType<Jar> {
    manifest {
        attributes["Start-Class"] = "com.aio.swaves.SwavesApplication"
    }
}

tasks.withType<ShadowJar> {
    archiveClassifier.set("aws")
    archiveFileName.set("swaves.jar")
    dependencies {
        exclude(
            dependency("org.springframework.cloud:spring-cloud-function-web:3.1.3"))
    }
    // Required for Spring
    mergeServiceFiles()
    append("META-INF/spring.handlers")
    append ("META-INF/spring.schemas")
    append("META-INF/spring.tooling")
    transform(PropertiesFileTransformer::class.java) {
        val paths = arrayOf("META-INF/spring.factories")
        val mergeStrategy = "append"
    }
}

application.yml

spring:
  cloud:
    function:
      definition: greet
  profiles:
    active: production

SwavesApplication.kt

package com.aio.swaves

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean

@SpringBootApplication
class SwavesApplication {
    @Bean
    fun greet(): (String) -> String {
        return { "Hello Kotlin" }
    }
}

fun main(args: Array<String>) {
    runApplication<SwavesApplication>(*args)
}

Notes

Notice that the error says that there is not active profile, so it will select the default, despite that the application.yml is setting an active profile to production.

Also notice that the Bean greet is created, which means that the start-class attribute is correctly configured. I am a bit lost in what is missed, I have make it work using java but not Kotlin any suggestion?

Daniel Branco
  • 117
  • 2
  • 9
  • 2
    Why and how are you using `SpringBootStreamHandler`. It's been deprecated for a long time, but regardless it is not clear from the above information how it's even used/activated. You can see more info from this Getting Started guide - https://docs.spring.io/spring-cloud-function/docs/3.1.3/reference/html/aws.html#_getting_started As you'll see there is only one invoker that you should be using now `org.springframework.cloud.function.adapter.aws.FunctionInvoker` – Oleg Zhurakousky Sep 09 '21 at 13:27

1 Answers1

0

Thanks to Oleg Zhurakousky's answer, I took my time to create samples project and document it at github. In the samples, you will find even how I push the code to AWS Lambda.

The error is that I was using the deprecated SpringBootStreamHandler instead the new FunctionInvoker.

Daniel Branco
  • 117
  • 2
  • 9