I am trying to create a Spring Cloud Function application which will have multiple functions defined in it. I need to use the Functional Bean definition approach for reduced cold start time. The jar will be deployed in AWS Lambda.
The code works in local environment and I am able to curl for all the functions defined. However when deployed in Lambda , the function is not getting located by AWS.
The code runs and is working as expected on Lambda ,if there is only 1 function defined.
I will mention below the things that I have tried.
- Followed the Spring Doc to create the project
- This works fine in local and also runs in Lambda with Handler
org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler::handleRequest
as per the comment by Thannasi on mydeveloperplanet blog post - Next I added few more functions and registered them with the Generic ApplicationContext
@SpringBootConfiguration
public class Multi_FunctionalBean1Application implements ApplicationContextInitializer<GenericApplicationContext> {
public static void main(String[] args) {
FunctionalSpringApplication.run(Multi_FunctionalBean1Application.class, args);
}
public Function<String, Boolean> containsCloud() {
return value -> {
System.out.println("Value is " + value);
return value.contains("cloud");
};
}
public Function<String, String> lowercase() {
return String::toLowerCase;
}
public Function<String, String> uppercase() {
return String::toUpperCase;
}
@Override
public void initialize(GenericApplicationContext context) {
context.registerBean("containsCloud", FunctionRegistration.class,
() -> new FunctionRegistration<>(containsCloud())
.type(FunctionType.from(String.class).to(Boolean.class)));
context.registerBean("uppercase", FunctionRegistration.class,
() -> new FunctionRegistration<>(uppercase()).type(FunctionType.from(String.class).to(String.class)));
context.registerBean("lowercase", FunctionRegistration.class,
() -> new FunctionRegistration<>(lowercase()).type(FunctionType.from(String.class).to(String.class)));
context.registerBean("getLength", FunctionRegistration.class,
() -> new FunctionRegistration<>(AnotherDemoFunction.getLength())
.type(FunctionType.from(String.class).to(String.class)));
context.registerBean("getSquare", FunctionRegistration.class,
() -> new FunctionRegistration<>(DemoFunction.getSquare())
.type(FunctionType.from(Integer.class).to(Double.class)));
}
}
- This runs fine in local, I am able to call all the functions separately eg.
localhost:8083/lowercase -d ":SFDLKLs is A "
andlocalhost:8083/getSquare -d 2
- I tried running this on Lambda , but I get the exception
Failed to locate function. Tried locating default function, function by '_HANDLER' env variable as well as'spring.cloud.function.definition
. I used the same handler function as before. Additionally provided the environment variablespring_cloud_function_definition
with one of the function names as value - I tried also by changing the handler function to
org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
. However it gives the exception of missing FunctionCatalog
Below are my dependencies and build plugin. spring-boot-starter-parent
version is 2.5.4
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Required only during build phase for spring tests to pass and local run-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-function-webflux</artifactId>
<version>3.0.10.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Basic Spring Cloud Function dependency -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-context</artifactId>
<version>3.1.3</version>
</dependency>
<!-- AWS Specific dependency for deployment in Lambda -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.1</version>
</dependency>
<!-- Required for reading the AWS Lambda Request/Response event in Proxy
Mode -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>3.9.0</version>
</dependency>
</dependencies>
<!-- Created Shaded and Thin jars -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>1.0.27.RELEASE</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>aws</shadedClassifierName>
</configuration>
</plugin>
</plugins>
</build>
Is there any other way to have multiple Functions in Spring Cloud Functional Bean Definition for AWS Lambda