0

I have been trying to replicate this aws function example to deploy a lambda with spring cloud function and graalvm.

The function works locally and starts up without a problem.

❯ ./demo
2021-05-10 15:56:17.964  INFO 10764 --- [           main] o.s.nativex.NativeListener               
: This application is bootstrapped with code generated with Spring AOT

.   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
'  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::                (v2.4.5)

2021-05-10 16:42:42.607  INFO 12792 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication using Java 11.0.11 on loyalty-C02F70R8MD6R with PID 12792 (/Users/user/Workspace/learning/demo/target/demo started by user in /Users/user/Workspace/learning/demo/target)
2021-05-10 16:42:42.607  INFO 12792 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2021-05-10 16:42:42.637  INFO 12792 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
May 10, 2021 4:42:42 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-nio-8080"]
May 10, 2021 4:42:42 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service [Tomcat]
May 10, 2021 4:42:42 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet engine: [Apache Tomcat/9.0.45]
May 10, 2021 4:42:42 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring embedded WebApplicationContext
2021-05-10 16:42:42.640  INFO 12792 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 32 ms
2021-05-10 16:42:42.650  INFO 12792 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
May 10, 2021 4:42:42 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
2021-05-10 16:42:42.658  INFO 12792 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-05-10 16:42:42.658  INFO 12792 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.071 seconds (JVM running for 0.072)

However, when I deployed it to aws it failed with the following exception

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cloud.function.adapter.aws.CustomRuntimeEventLoop': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.function.adapter.aws.CustomRuntimeEventLoop]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.cloud.function.adapter.aws.CustomRuntimeEventLoop.<init>()
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1316) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1214) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[na:na]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[na:na]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[na:na]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[na:na]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[na:na]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[na:na]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[na:na]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[na:na]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[na:na]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:782) ~[demo:na]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:774) ~[demo:na]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[demo:na]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:339) ~[demo:na]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1340) ~[demo:na]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329) ~[demo:na]
at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[demo:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.function.adapter.aws.CustomRuntimeEventLoop]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.cloud.function.adapter.aws.CustomRuntimeEventLoop.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1308) ~[na:na]
... 18 common frames omitted
Caused by: java.lang.NoSuchMethodException: org.springframework.cloud.function.adapter.aws.CustomRuntimeEventLoop.<init>()
at java.lang.Class.getConstructor0(DynamicHub.java:3349) ~[na:na]
at java.lang.Class.getDeclaredConstructor(DynamicHub.java:2553) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78) ~[na:na]
... 19 common frames omitted

I inspected the CustomRuntimeEventLoop and found that class is annotate with

@Configuration
@ConditionalOnProperty("AWS_LAMBDA_RUNTIME_API")

Which means it, only, gets initialised in the AWS environment. And this is why the function did not fail locally. I tried to initialised the class at build time by adding the following snippet to my spring boot application

@NativeHint(initialization = {@InitializationHint(types = {CustomRuntimeEventLoop.class}, initTime = BUILD)})

But this still did not affect the build or runtime behaviour.

Any idea how can I initialise this in the build time?

Matto
  • 2,538
  • 2
  • 18
  • 23
  • 1
    The sample you copied from is very old. If I were you I would start from the one in "main" (https://github.com/spring-projects-experimental/spring-native/blob/main/samples/cloud-function-aws) and modify that. Pay attention to the plugins defined in the parent pom. – Dave Syer May 11 '21 at 15:52
  • Any reason why you prefer using a 3rd party API over the official AWS SDK for Java API V2 which also gives you support from the AWS SDK team? You can use AWS Java V2 API with the Spring framework. – smac2020 May 11 '21 at 20:45
  • 1
    I updated the sample that the OP copied so it works now: https://github.com/dsyer/lambda-aws-demo. FWIW Spring Cloud uses the AWS SDK as a library, so I don't think it's really "unofficial" in any way. Works for me anyway. – Dave Syer May 12 '21 at 09:11

1 Answers1

1

Have you seem this example - https://github.com/spring-projects-experimental/spring-native/tree/main/samples/cloud-function-aws?

Also, there were issues with that new CustomRuntimeEventLoop that have already been addressed, so consider using the latest snapshot.

Oleg Zhurakousky
  • 5,820
  • 16
  • 17
  • Thanks, this example and @DavesSyer comment helped me to get my demo up and running, here is a running demo https://github.com/muhamadto/spring-native-aws-lambda – Matto May 28 '21 at 01:15
  • 1
    Cool. Just as an FYI, the s-c-function 3.1.3 has just been released so all the fixes I was mentioning are there. – Oleg Zhurakousky May 28 '21 at 06:49
  • upgrading org.springframework.cloud:spring-cloud-dependencies:2020.0.2 to 2020.0.3 caused the service to go into loop in aws. the following keep getting printed o.s.c.f.web.source.SupplierExporter : Posting to: origin reactor.Mono.Peek.169 : onSubscribe(FluxPeek.PeekSubscriber) reactor.Mono.Peek.169 : request(32) reactor.Mono.Peek.169:onNext(org.springframework.web.reactive.function.client.DefaultClientRespon reactor.Mono.Peek.169 : onComplete() reactor.Flux.MonoRepeatPredicate.1 : request(1) reactor.Flux.MonoRepeatPredicate.1 : onNext(GenericMessage [payload={"name":"value1"}, hea – Matto Jun 18 '21 at 07:37
  • Can you please post your app somewhere in Github so we can take a look? The above stack trace does not provide any relevant info – Oleg Zhurakousky Jun 28 '21 at 06:26
  • Hey @Oleg, I have found the problem. It happened when I upgraded the dependency from org.springframework.cloud:spring-cloud-dependencies:2020.0.2 to org.springframework.cloud:spring-cloud-dependencies:2020.0.3. you can find the project here https://github.com/muhamadto/spring-native-aws-lambda.git, I reverted this back so now it works find – Matto Jul 04 '21 at 13:57