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.
org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler::handleRequest
as per the comment by Thannasi on mydeveloperplanet blog post@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)));
}
}
localhost:8083/lowercase -d ":SFDLKLs is A "
and localhost:8083/getSquare -d 2
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 variable spring_cloud_function_definition
with one of the function names as valueorg.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
. However it gives the exception of missing FunctionCatalogBelow 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
With help of Oleg's Comment I was able to achieve multiple functions with Functional Bean definition on AWS Lambda.
The changes done were as below
public static void main(String[] args) {
//FunctionalSpringApplication.run(Multi_FunctionalBean1Application.class, args);
}
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
<wrapper.version>1.0.27.RELEASE</wrapper.version>
<aws-lambda-events.version>3.9.0</aws-lambda-events.version>
<spring-cloud-function.version>3.2.0-SNAPSHOT</spring-cloud-function.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-web</artifactId>
</dependency>
<!-- AWS Specific dependency for deployment in Lambda -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.1</version>
<scope>provided</scope>
</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-dependencies</artifactId>
<version>${spring-cloud-function.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 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>${wrapper.version}</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>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
spring_cloud_function_definition
with function name as the value or a composition like func1|func2|func3